//! Default seed data for Quests, Achievements, and Level Rewards. use anyhow::Result; use sqlx::SqlitePool; // Targets with a material, mob, or dimension requirement use the action // telemetry sent by both Paper and the Fabric/Forge bridge. Other quests use // the aggregate counters in the sync payload. const SPECIFIC_QUEST_TARGETS: &[(&str, &str)] = &[ ("q_d_mine_coal", "action:block_broken:COAL_ORE|DEEPSLATE_COAL_ORE|COAL_BLOCK"), ("q_d_mine_stone", "action:block_broken:STONE|COBBLESTONE"), ("q_d_mine_iron", "action:block_broken:IRON_ORE|DEEPSLATE_IRON_ORE"), ("q_d_mine_copper", "action:block_broken:COPPER_ORE|DEEPSLATE_COPPER_ORE"), ("q_d_mine_gold", "action:block_broken:GOLD_ORE|DEEPSLATE_GOLD_ORE|NETHER_GOLD_ORE"), ("q_d_mine_diamond", "action:block_broken:DIAMOND_ORE|DEEPSLATE_DIAMOND_ORE"), ("q_d_mine_redstone", "action:block_broken:REDSTONE_ORE|DEEPSLATE_REDSTONE_ORE"), ("q_d_mine_deepslate", "action:block_broken:DEEPSLATE|COBBLED_DEEPSLATE"), ("q_d_mine_quartz", "action:block_broken:NETHER_QUARTZ_ORE"), ("q_d_mine_debris", "action:block_broken:ANCIENT_DEBRIS"), ("q_d_mine_sand", "action:block_broken:SAND|GRAVEL"), ("q_d_mine_obsidian", "action:block_broken:OBSIDIAN"), ("q_d_mob_zombies", "action:mob_kills:ZOMBIE"), ("q_d_mob_skeletons", "action:mob_kills:SKELETON"), ("q_d_mob_spiders", "action:mob_kills:SPIDER|CAVE_SPIDER"), ("q_d_mob_creepers", "action:mob_kills:CREEPER"), ("q_d_mob_endermen", "action:mob_kills:ENDERMAN"), ("q_d_mob_witches", "action:mob_kills:WITCH"), ("q_d_mob_slimes", "action:mob_kills:SLIME|MAGMA_CUBE"), ("q_d_mob_piglins", "action:mob_kills:PIGLIN|ZOMBIFIED_PIGLIN"), ("q_d_mob_blazes", "action:mob_kills:BLAZE"), ("q_d_mob_drowned", "action:mob_kills:DROWNED"), ("q_d_build_planks", "action:block_placed:*_PLANKS"), ("q_d_build_bricks", "action:block_placed:STONE_BRICKS|POLISHED_*"), ("q_d_build_glass", "action:block_placed:GLASS|GLASS_PANE|*_GLASS|*_GLASS_PANE"), ("q_d_build_torches", "action:block_placed:TORCH|WALL_TORCH"), ("q_d_build_lanterns", "action:block_placed:LANTERN|SOUL_LANTERN"), ("q_d_build_slabs", "action:block_placed:*_SLAB|*_STAIRS"), ("q_d_build_walls", "action:block_placed:*_WALL"), ("q_d_farm_wood", "action:block_broken:*_LOG|*_WOOD"), ("q_d_farm_birch", "action:block_broken:BIRCH_LOG|SPRUCE_LOG"), ("q_d_farm_jungle", "action:block_broken:JUNGLE_LOG|ACACIA_LOG"), ("q_d_farm_wheat", "action:block_broken:WHEAT"), ("q_d_farm_potatoes", "action:block_broken:POTATOES"), ("q_d_farm_carrots", "action:block_broken:CARROTS"), ("q_d_farm_sugarcane", "action:block_broken:SUGAR_CANE"), ("q_d_farm_pumpkins", "action:block_broken:PUMPKIN|MELON"), ("q_d_farm_flowers", "action:block_broken:*_TULIP|DANDELION|POPPY|OXEYE_DAISY|CORNFLOWER|AZURE_BLUET|ALLIUM"), ("q_d_farm_leaves", "action:block_broken:*_LEAVES"), ("q_d_explore_depths", "action:block_broken:TUFF|DEEPSLATE_TILES"), ("q_d_explore_diorite", "action:block_broken:GRANITE|DIORITE|ANDESITE"), ("q_d_explore_nether", "action:block_broken:*@minecraft:the_nether"), ("q_d_explore_clay", "action:block_broken:CLAY"), ("q_d_explore_snow", "action:block_broken:SNOW_BLOCK|SNOW|ICE|PACKED_ICE|BLUE_ICE"), ("q_d_explore_magma", "action:block_broken:MAGMA_BLOCK|BASALT"), ("q_d_build_decor", "action:block_placed:*_CARPET|FLOWER_POT|PAINTING"), ("q_w_mine_deepslate_grand", "action:block_broken:DEEPSLATE|COBBLED_DEEPSLATE"), ("q_w_mine_iron_hoard", "action:block_broken:IRON_ORE|DEEPSLATE_IRON_ORE"), ("q_w_mine_diamonds_grand", "action:block_broken:DIAMOND_ORE|DEEPSLATE_DIAMOND_ORE"), ("q_w_mine_gold_grand", "action:block_broken:GOLD_ORE|DEEPSLATE_GOLD_ORE|NETHER_GOLD_ORE"), ("q_w_mine_redstone_grand", "action:block_broken:REDSTONE_ORE|DEEPSLATE_REDSTONE_ORE"), ("q_w_mine_debris_grand", "action:block_broken:ANCIENT_DEBRIS"), ("q_w_mine_nether_grand", "action:block_broken:*@minecraft:the_nether"), ("q_w_mine_stone_grand", "action:block_broken:STONE|COBBLESTONE"), ("q_w_mob_skeletons_grand", "action:mob_kills:SKELETON"), ("q_w_mob_creepers_grand", "action:mob_kills:CREEPER"), ("q_w_mob_endermen_grand", "action:mob_kills:ENDERMAN"), ("q_w_mob_blazes_grand", "action:mob_kills:BLAZE"), ("q_w_mob_withers_grand", "action:mob_kills:WITHER_SKELETON"), ("q_w_build_castle", "action:block_placed:STONE_BRICKS|*_STONE_BRICKS"), ("q_w_build_planks_grand", "action:block_placed:*_PLANKS"), ("q_w_build_glass_grand", "action:block_placed:GLASS|*_GLASS"), ("q_w_build_lanterns_grand", "action:block_placed:LANTERN|SOUL_LANTERN|GLOWSTONE"), ("q_w_build_enclosure", "action:block_placed:*_FENCE|*_WALL"), ("q_w_farm_logs_grand", "action:block_broken:*_LOG|*_WOOD"), ("q_w_farm_crops_grand", "action:block_broken:WHEAT|POTATOES|CARROTS|BEETROOTS"), ("q_w_farm_reeds_grand", "action:block_broken:SUGAR_CANE|BAMBOO"), ("q_w_farm_pumpkins_grand", "action:block_broken:PUMPKIN|MELON"), ("q_w_explore_nether_grand2", "action:block_broken:*@minecraft:the_nether"), ("q_w_explore_ocean", "action:block_broken:PRISMARINE|PRISMARINE_BRICKS|DARK_PRISMARINE|GRAVEL|*_CORAL_BLOCK"), ("q_w_explore_sand_grand", "action:block_broken:SAND|RED_SAND"), ("q_w_build_complex", "action:block_placed:STONE_BRICKS|POLISHED_GRANITE"), ]; pub async fn upgrade_seeded_quest_targets(pool: &SqlitePool) -> Result<()> { for (id, target) in SPECIFIC_QUEST_TARGETS { sqlx::query("UPDATE quests SET target_stat = ? WHERE id = ? AND target_stat IN ('blocks_broken', 'blocks_placed', 'mob_kills')") .bind(target).bind(id).execute(pool).await?; } Ok(()) } pub async fn seed_quests_and_achievements(pool: &SqlitePool) -> Result<()> { // Only seed if quests table is empty let count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM quests").fetch_one(pool).await?; if count == 0 { seed_quests(pool).await?; } let ach_count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM achievements").fetch_one(pool).await?; if ach_count == 0 { seed_achievements(pool).await?; } let rew_count: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM level_rewards").fetch_one(pool).await?; if rew_count == 0 { seed_rewards(pool).await?; } Ok(()) } async fn seed_quests(pool: &SqlitePool) -> Result<()> { let now = chrono::Utc::now().to_rfc3339(); // 100 total quests: 60 Daily, 40 Weekly let raw_quests = [ // Daily Mining ("q_d_mine_coal", "Coal Miner", "Mine 16 coal ore or coal blocks", "daily", "mining", "blocks_broken", 16, 100, "pickaxe"), ("q_d_mine_stone", "Stonebreaker", "Break 64 stone or cobblestone blocks", "daily", "mining", "blocks_broken", 64, 120, "pickaxe"), ("q_d_mine_iron", "Iron Prospector", "Mine 16 iron ore blocks underground", "daily", "mining", "blocks_broken", 16, 150, "pickaxe"), ("q_d_mine_copper", "Copper Collector", "Gather 24 copper ore blocks", "daily", "mining", "blocks_broken", 24, 130, "pickaxe"), ("q_d_mine_gold", "Gold Rush", "Mine 8 gold ore blocks in caves or the Nether", "daily", "mining", "blocks_broken", 8, 180, "pickaxe"), ("q_d_mine_diamond", "Diamond Digger", "Mine 4 rare diamond ore blocks", "daily", "mining", "blocks_broken", 4, 300, "gem"), ("q_d_mine_redstone", "Redstone Engineer", "Mine 12 redstone ore blocks", "daily", "mining", "blocks_broken", 12, 160, "zap"), ("q_d_mine_deepslate", "Deepslate Delver", "Mine 48 deepslate blocks in the depths", "daily", "mining", "blocks_broken", 48, 140, "pickaxe"), ("q_d_mine_quartz", "Nether Prospecting", "Mine 16 Nether quartz ore blocks", "daily", "mining", "blocks_broken", 16, 180, "sparkles"), ("q_d_mine_debris", "Debris Hunter", "Mine 2 Ancient Debris blocks in the Nether", "daily", "mining", "blocks_broken", 2, 450, "shield"), ("q_d_mine_sand", "Dune Excavator", "Dig 32 sand or gravel blocks", "daily", "mining", "blocks_broken", 32, 90, "layers"), ("q_d_mine_obsidian", "Obsidian Forger", "Mine 8 obsidian blocks", "daily", "mining", "blocks_broken", 8, 250, "shield"), // Daily Combat ("q_d_mob_zombies", "Zombie Purge", "Defeat 8 zombies wandering in the dark", "daily", "combat", "mob_kills", 8, 120, "swords"), ("q_d_mob_skeletons", "Bone Collector", "Take down 6 skeleton archers", "daily", "combat", "mob_kills", 6, 130, "crosshair"), ("q_d_mob_spiders", "Arachnid Slayer", "Defeat 5 creepy spiders or cave spiders", "daily", "combat", "mob_kills", 5, 120, "shield-alert"), ("q_d_mob_creepers", "Bomb Squad", "Eliminate 4 creepers before they explode", "daily", "combat", "mob_kills", 4, 180, "flame"), ("q_d_mob_endermen", "Ender Stalker", "Defeat 2 mysterious Endermen", "daily", "combat", "mob_kills", 2, 220, "eye"), ("q_d_mob_witches", "Witch Trial", "Defeat 1 witch brewing dangerous potions", "daily", "combat", "mob_kills", 1, 200, "flask-conical"), ("q_d_mob_slimes", "Slime Sweeper", "Defeat 6 bouncy slimes or magma cubes", "daily", "combat", "mob_kills", 6, 140, "sparkles"), ("q_d_mob_piglins", "Piglin Skirmish", "Defeat 6 hostile piglins or zombified piglins", "daily", "combat", "mob_kills", 6, 160, "swords"), ("q_d_mob_blazes", "Firestarter", "Defeat 4 blazing fortress defenders", "daily", "combat", "mob_kills", 4, 250, "flame"), ("q_d_mob_drowned", "Deep Water Danger", "Defeat 5 drowned lurkers in rivers or oceans", "daily", "combat", "mob_kills", 5, 140, "droplets"), ("q_d_mob_monsters", "Night Watch", "Defeat any 15 mobs", "daily", "combat", "mob_kills", 15, 200, "swords"), ("q_d_pvp_champion", "Gladiator's Glory", "Defeat 1 player in honorable combat", "daily", "combat", "player_kills", 1, 250, "trophy"), // Daily Building ("q_d_build_planks", "Woodworker", "Place 48 wooden planks in any construction", "daily", "building", "blocks_placed", 48, 120, "hammer"), ("q_d_build_bricks", "Mason's Pride", "Place 32 stone bricks or polished stones", "daily", "building", "blocks_placed", 32, 130, "box"), ("q_d_build_glass", "Window Pane", "Place 16 glass blocks or panes", "daily", "building", "blocks_placed", 16, 100, "eye"), ("q_d_build_torches", "Let There Be Light", "Place 20 torches to illuminate the area", "daily", "building", "blocks_placed", 20, 90, "flame"), ("q_d_build_lanterns", "Cozy Hearth", "Place 6 lanterns around your settlement", "daily", "building", "blocks_placed", 6, 120, "sparkles"), ("q_d_build_slabs", "Tiered Architecture", "Place 24 slabs or stairs", "daily", "building", "blocks_placed", 24, 110, "layers"), ("q_d_build_roof", "Under Cover", "Place 50 blocks of any kind", "daily", "building", "blocks_placed", 50, 140, "home"), ("q_d_build_walls", "Fortified Walls", "Place 30 cobblestone or deepslate walls", "daily", "building", "blocks_placed", 30, 130, "shield"), ("q_d_build_general", "Master Builder", "Place 100 blocks of any material", "daily", "building", "blocks_placed", 100, 180, "hammer"), ("q_d_build_monument", "Grand Monument", "Place 150 blocks of any kind", "daily", "building", "blocks_placed", 150, 220, "castle"), // Daily Farming & Harvesting ("q_d_farm_wood", "Lumberjack", "Chop down 32 wood logs", "daily", "farming", "blocks_broken", 32, 120, "axe"), ("q_d_farm_birch", "Birch Forester", "Harvest 20 birch or spruce logs", "daily", "farming", "blocks_broken", 20, 110, "axe"), ("q_d_farm_jungle", "Jungle Explorer", "Chop 24 jungle or acacia logs", "daily", "farming", "blocks_broken", 24, 130, "axe"), ("q_d_farm_wheat", "Wheat Harvester", "Harvest 24 ripe wheat stalks", "daily", "farming", "blocks_broken", 24, 100, "sprout"), ("q_d_farm_potatoes", "Potato Bounty", "Gather 24 potatoes from the fields", "daily", "farming", "blocks_broken", 24, 100, "sprout"), ("q_d_farm_carrots", "Golden Nutrition", "Harvest 24 fresh carrots", "daily", "farming", "blocks_broken", 24, 100, "sprout"), ("q_d_farm_sugarcane", "Sugar Rush", "Cut 16 sugar cane reeds", "daily", "farming", "blocks_broken", 16, 90, "sprout"), ("q_d_farm_pumpkins", "Patch Patrol", "Harvest 8 pumpkins or melons", "daily", "farming", "blocks_broken", 8, 110, "apple"), ("q_d_farm_flowers", "Botanist", "Collect 12 wild flowers", "daily", "farming", "blocks_broken", 12, 80, "flower"), ("q_d_farm_leaves", "Foliage Trimmer", "Break 40 leaf blocks", "daily", "farming", "blocks_broken", 40, 80, "scissors"), // Daily Social & Playtime ("q_d_play_15m", "Quick Check-in", "Play on any server for 15 minutes", "daily", "social", "playtime_secs", 900, 100, "clock"), ("q_d_play_30m", "Dedicated Citizen", "Spend 30 minutes in game", "daily", "social", "playtime_secs", 1800, 180, "clock"), ("q_d_play_60m", "Hour of Power", "Play for a total of one hour", "daily", "social", "playtime_secs", 3600, 250, "clock"), ("q_d_chat_chatty", "Good Morning", "Send 5 chat messages", "daily", "social", "messages", 5, 80, "message-square"), ("q_d_chat_talkative", "Community Voice", "Send 15 chat messages participating in chat", "daily", "social", "messages", 15, 120, "message-square"), ("q_d_join_again", "Frequent Flyer", "Join a server 2 distinct times today", "daily", "social", "joins", 2, 80, "door-open"), ("q_d_explore_depths", "Into the Deep", "Mine 30 tuff or deepslate tiles", "daily", "exploration", "blocks_broken", 30, 110, "compass"), ("q_d_explore_caves", "Spelunker", "Break 50 blocks of any kind", "daily", "exploration", "blocks_broken", 50, 130, "compass"), ("q_d_explore_diorite", "Geologist", "Collect 20 granite, diorite, or andesite blocks", "daily", "exploration", "blocks_broken", 20, 100, "mountain"), ("q_d_explore_nether", "Nether Expedition", "Mine 40 nether blocks while surviving", "daily", "exploration", "blocks_broken", 40, 160, "flame"), ("q_d_explore_clay", "Clay Digger", "Excavate 16 clay blocks from river beds", "daily", "exploration", "blocks_broken", 16, 110, "droplets"), ("q_d_explore_snow", "Winter Wonderland", "Shovel 32 snow or ice blocks", "daily", "exploration", "blocks_broken", 32, 90, "snowflake"), ("q_d_explore_magma", "Volcanic Venture", "Mine 8 magma blocks or basalt", "daily", "exploration", "blocks_broken", 8, 140, "flame"), ("q_d_build_decor", "Interior Decorator", "Place 15 decorative items or carpets", "daily", "building", "blocks_placed", 15, 90, "palette"), // Weekly Quests (Higher targets & XP rewards) ("q_w_mine_deepslate_grand", "Excavation Giant", "Mine 500 deepslate blocks in the darkest depths", "weekly", "mining", "blocks_broken", 500, 750, "pickaxe"), ("q_w_mine_iron_hoard", "Iron Hoarder", "Mine 128 iron ore across the week", "weekly", "mining", "blocks_broken", 128, 850, "pickaxe"), ("q_w_mine_diamonds_grand", "Diamond Empire", "Discover and mine 32 diamonds", "weekly", "mining", "blocks_broken", 32, 1200, "gem"), ("q_w_mine_gold_grand", "Midas Touch", "Mine 64 gold ore from caves or fortresses", "weekly", "mining", "blocks_broken", 64, 900, "award"), ("q_w_mine_redstone_grand", "Automation Maestro", "Mine 128 redstone ore blocks", "weekly", "mining", "blocks_broken", 128, 800, "zap"), ("q_w_mine_debris_grand", "Netherite Titan", "Locate and extract 12 Ancient Debris blocks", "weekly", "mining", "blocks_broken", 12, 1600, "shield"), ("q_w_mine_nether_grand", "Underworld Quarry", "Break 300 blocks in the Nether dimension", "weekly", "mining", "blocks_broken", 300, 700, "flame"), ("q_w_mine_stone_grand", "Mountain Mover", "Break 1,000 stone or cobblestone blocks", "weekly", "mining", "blocks_broken", 1000, 1100, "mountain"), ("q_w_mob_purge_grand", "Monster Exterminator", "Defeat 100 mobs", "weekly", "combat", "mob_kills", 100, 1000, "swords"), ("q_w_mob_skeletons_grand", "Archer's Nemesis", "Defeat 40 skeleton sharpshooters", "weekly", "combat", "mob_kills", 40, 750, "crosshair"), ("q_w_mob_creepers_grand", "Demolition Defuser", "Take down 30 dangerous creepers", "weekly", "combat", "mob_kills", 30, 850, "flame"), ("q_w_mob_endermen_grand", "Void Hunter", "Defeat 15 elusive Endermen", "weekly", "combat", "mob_kills", 15, 1100, "eye"), ("q_w_mob_blazes_grand", "Fortress Conqueror", "Extinguish 25 fiery blazes in Nether fortresses", "weekly", "combat", "mob_kills", 25, 1200, "flame"), ("q_w_mob_withers_grand", "Skull Seeker", "Defeat 12 wither skeletons", "weekly", "combat", "mob_kills", 12, 1300, "skull"), ("q_w_pvp_champion_grand", "Arena Legend", "Defeat 10 players in competitive PvP matches", "weekly", "combat", "player_kills", 10, 1500, "trophy"), ("q_w_pvp_master_grand", "Warlord of SCOPENET", "Claim 25 PvP victories across all servers", "weekly", "combat", "player_kills", 25, 2500, "crown"), ("q_w_build_castle", "Castle Founder", "Place 800 stone bricks or fortified blocks", "weekly", "building", "blocks_placed", 800, 1000, "castle"), ("q_w_build_planks_grand", "Town Carpenter", "Place 500 wooden planks on structures", "weekly", "building", "blocks_placed", 500, 800, "hammer"), ("q_w_build_glass_grand", "Sky Dome", "Place 150 glass blocks", "weekly", "building", "blocks_placed", 150, 700, "eye"), ("q_w_build_lanterns_grand", "Beacon of Light", "Place 40 lanterns or glowstone blocks", "weekly", "building", "blocks_placed", 40, 750, "sparkles"), ("q_w_build_grand_city", "Metropolis Architect", "Place 1,500 total blocks across any build", "weekly", "building", "blocks_placed", 1500, 1400, "hammer"), ("q_w_build_enclosure", "Fortress Perimeters", "Place 150 fence posts or wall segments", "weekly", "building", "blocks_placed", 150, 700, "shield"), ("q_w_farm_logs_grand", "Deforestation Duty", "Harvest 250 wood logs of any species", "weekly", "farming", "blocks_broken", 250, 800, "axe"), ("q_w_farm_crops_grand", "Granary Overflow", "Harvest 200 total food crops", "weekly", "farming", "blocks_broken", 200, 750, "sprout"), ("q_w_farm_reeds_grand", "Sugar Empire", "Harvest 100 sugar cane or bamboo", "weekly", "farming", "blocks_broken", 100, 650, "sprout"), ("q_w_farm_pumpkins_grand", "Autumn Festival", "Harvest 40 pumpkins or melons", "weekly", "farming", "blocks_broken", 40, 700, "apple"), ("q_w_play_3h", "Weekly Adventurer", "Spend 3 hours playing on SCOPENET servers", "weekly", "social", "playtime_secs", 10800, 800, "clock"), ("q_w_play_8h", "Dedicated Veteran", "Spend 8 hours playing across the week", "weekly", "social", "playtime_secs", 28800, 1500, "clock"), ("q_w_play_15h", "No-Lifer Supremacy", "Clock in 15 hours of active gameplay", "weekly", "social", "playtime_secs", 54000, 2500, "zap"), ("q_w_chat_social", "Town Hall Speaker", "Contribute 50 chat messages across community servers", "weekly", "social", "messages", 50, 600, "message-square"), ("q_w_joins_loyal", "Daily Habits", "Join game servers on at least 5 occasions", "weekly", "social", "joins", 5, 700, "door-open"), ("q_w_explore_caves_grand", "Underground Cartographer", "Break 400 blocks of any kind", "weekly", "exploration", "blocks_broken", 400, 850, "compass"), ("q_w_explore_nether_grand2", "Infernal Pioneer", "Travel and mine 250 blocks in the Nether", "weekly", "exploration", "blocks_broken", 250, 800, "flame"), ("q_w_explore_ocean", "Abyssal Diver", "Break 100 prismarine, gravel, or coral blocks", "weekly", "exploration", "blocks_broken", 100, 750, "droplets"), ("q_w_explore_sand_grand", "Desert Terraformer", "Dig 300 sand or red sand blocks", "weekly", "exploration", "blocks_broken", 300, 650, "layers"), ("q_w_build_complex", "Civil Engineer", "Place 600 stone bricks or polished granite", "weekly", "building", "blocks_placed", 600, 950, "box"), ]; for (id, title, desc, period, cat, stat, target, xp, icon) in raw_quests { sqlx::query( "INSERT OR IGNORE INTO quests (id, title, description, period, category, target_stat, target_count, xp_reward, icon, enabled, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?)" ) .bind(id) .bind(title) .bind(desc) .bind(period) .bind(cat) .bind(SPECIFIC_QUEST_TARGETS.iter().find(|(quest_id, _)| *quest_id == id).map(|(_, target)| *target).unwrap_or(stat)) .bind(target) .bind(xp) .bind(icon) .bind(&now) .execute(pool) .await?; } Ok(()) } async fn seed_achievements(pool: &SqlitePool) -> Result<()> { let now = chrono::Utc::now().to_rfc3339(); let raw_achievements = [ ("ach_first_steps", "First Steps", "Join your first SCOPENET server and begin your journey.", "progression", "task", "wooden_pickaxe", "stone", "bronze", "stat", "joins", 1, 100, 0), ("ach_miner_49er", "Strike It Rich!", "Mine your first diamond ore underground.", "mining", "task", "diamond", "deepslate", "gold", "stat", "blocks_broken", 50, 250, 0), ("ach_first_blood", "First Blood", "Defeat your first monster in battle.", "combat", "task", "iron_sword", "dirt", "bronze", "stat", "mob_kills", 1, 100, 0), ("ach_monster_hunter", "Monster Hunter", "Defeat 100 hostile mobs across servers.", "combat", "goal", "diamond_sword", "stone", "gold", "stat", "mob_kills", 100, 500, 0), ("ach_master_slayer", "Slayer of the Night", "Vanquish 500 monsters threatening players.", "combat", "challenge", "netherite_sword", "obsidian", "purple", "stat", "mob_kills", 500, 1500, 0), ("ach_duelist", "Arena Duelist", "Defeat another player in PvP combat.", "combat", "task", "bow", "stone", "silver", "stat", "player_kills", 1, 200, 0), ("ach_gladiator", "SCOPENET Gladiator", "Defeat 25 players in competitive combat.", "combat", "challenge", "netherite_axe", "bedrock", "gold", "stat", "player_kills", 25, 1000, 0), ("ach_architect", "Apprentice Architect", "Place your first 500 building blocks.", "building", "task", "bricks", "stone", "bronze", "stat", "blocks_placed", 500, 250, 0), ("ach_master_builder", "Master Builder", "Construct structures using over 5,000 blocks.", "building", "goal", "stone_bricks", "oak_planks", "gold", "stat", "blocks_placed", 5000, 1000, 0), ("ach_monument_maker", "Wonders of the World", "Place 20,000 blocks leaving your mark on the realm.", "building", "challenge", "beacon", "obsidian", "diamond", "stat", "blocks_placed", 20000, 2500, 0), ("ach_playtime_10h", "Seasoned Traveler", "Accumulate 10 hours of playtime.", "progression", "task", "clock", "oak_planks", "silver", "stat", "playtime_secs", 36000, 500, 0), ("ach_playtime_50h", "Hardened Veteran", "Reach 50 hours of active adventure.", "progression", "goal", "compass", "stone", "gold", "stat", "playtime_secs", 180000, 1200, 0), ("ach_playtime_100h", "Centurion", "Dedicate 100 hours to the SCOPENET community.", "progression", "challenge", "totem_of_undying", "gilded_blackstone", "diamond", "stat", "playtime_secs", 360000, 2500, 0), ("ach_level_10", "Rising Star", "Reach SCOPENET Global Level 10.", "progression", "task", "experience_bottle", "stone", "bronze", "level", "global_level", 10, 300, 0), ("ach_level_25", "Champion", "Ascend to Global Level 25.", "progression", "goal", "enchanted_book", "stone", "gold", "level", "global_level", 25, 800, 0), ("ach_level_50", "Grandmaster", "Attain Global Level 50 through valor and persistence.", "progression", "challenge", "nether_star", "obsidian", "purple", "level", "global_level", 50, 2000, 0), ("ach_level_100", "Mythic Legend", "Surpass all expectations by reaching Global Level 100.", "progression", "challenge", "dragon_egg", "bedrock", "gold", "level", "global_level", 100, 5000, 0), ("ach_chatty", "Social Butterfly", "Send 100 messages in server chat.", "social", "task", "book", "oak_planks", "bronze", "stat", "messages", 100, 200, 0), ("ach_guild_initiate", "United We Stand", "Join or found a Guild.", "guilds", "task", "shield", "stone", "silver", "event", "join_guild", 1, 300, 0), ("ach_land_claim", "Territorial Sovereign", "Claim your first chunk of guild territory.", "guilds", "goal", "grass_block", "dirt", "gold", "event", "claim_land", 1, 400, 0), ("ach_nether_walker", "Into the Fire", "Set foot in the Nether dimension.", "exploration", "task", "flint_and_steel", "netherrack", "bronze", "event", "nether", 1, 200, 0), ("ach_end_slayer", "Free the End", "Slay the Ender Dragon.", "exploration", "challenge", "dragon_head", "end_stone", "purple", "event", "ender_dragon", 1, 2000, 1), ]; for (id, title, desc, cat, frame, item, bg, border, req_type, req_key, req_val, xp, secret) in raw_achievements { sqlx::query( "INSERT OR IGNORE INTO achievements (id, title, description, category, icon_frame, icon_item, icon_bg, icon_border, requirement_type, requirement_key, requirement_value, xp_reward, secret, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" ) .bind(id) .bind(title) .bind(desc) .bind(cat) .bind(frame) .bind(item) .bind(bg) .bind(border) .bind(req_type) .bind(req_key) .bind(req_val) .bind(xp) .bind(secret) .bind(&now) .execute(pool) .await?; } Ok(()) } async fn seed_rewards(pool: &SqlitePool) -> Result<()> { let now = chrono::Utc::now().to_rfc3339(); let raw_rewards = [ ("global", None::, 2, "title", "Apprentice", r##"{"title": "Apprentice", "color": "#a8a29e"}"##), ("global", None, 5, "title", "Journeyman", r##"{"title": "Journeyman", "color": "#38bdf8"}"##), ("global", None, 5, "badge", "Bronze Star", r##"{"badge": "star_bronze", "icon": "sparkles"}"##), ("global", None, 10, "title", "Veteran", r##"{"title": "Veteran", "color": "#4ade80"}"##), ("global", None, 10, "cosmetic", "Emerald Aura", r##"{"particle": "emerald", "type": "aura"}"##), ("global", None, 20, "title", "Warden", r##"{"title": "Warden", "color": "#818cf8"}"##), ("global", None, 25, "title", "Hero", r##"{"title": "Hero", "color": "#facc15"}"##), ("global", None, 25, "badge", "Silver Shield", r##"{"badge": "shield_silver", "icon": "shield"}"##), ("global", None, 35, "title", "Warlord", r##"{"title": "Warlord", "color": "#fb923c"}"##), ("global", None, 50, "title", "Legend", r##"{"title": "Legend", "color": "#f43f5e"}"##), ("global", None, 50, "badge", "Golden Crown", r##"{"badge": "crown_gold", "icon": "crown"}"##), ("global", None, 75, "title", "Ascendant", r##"{"title": "Ascendant", "color": "#c084fc"}"##), ("global", None, 100, "title", "Immortal", r##"{"title": "Immortal", "color": "#e879f9"}"##), ("global", None, 100, "badge", "Mythic Champion", r##"{"badge": "mythic_star", "icon": "trophy"}"##), ]; for (lvl_type, srv_id, lvl_req, rew_type, rew_name, rew_data) in raw_rewards { sqlx::query( "INSERT INTO level_rewards (level_type, server_id, level_req, reward_type, reward_name, reward_data, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)" ) .bind(lvl_type) .bind(srv_id) .bind(lvl_req) .bind(rew_type) .bind(rew_name) .bind(rew_data) .bind(&now) .execute(pool) .await?; } Ok(()) }