From 823dcbafd8362c797f96e4c0265fd7638c962f68 Mon Sep 17 00:00:00 2001 From: Tastybento Date: Sun, 8 Apr 2018 15:37:29 -0700 Subject: [PATCH] Added challenges import from ASkyBlock --- addon.yml | 2 +- challenges.yml | 778 ++++++++++++++++++ locales/en-US.yml | 6 +- .../addon/challenges/ChallengesAddon.java | 92 +-- .../addon/challenges/ChallengesManager.java | 147 +++- .../challenges/FreshSqueezedChallenges.java | 232 ++++++ .../admin/ChallengesAdminCommand.java | 1 + .../challenges/commands/admin/SetIcon.java | 63 ++ .../database/object/Challenges.java | 202 +++-- .../challenges/panel/ChallengesPanels.java | 4 +- .../addon/challenges/panel/TryToComplete.java | 6 +- .../addon/challenges/ChallengesAddonTest.java | 2 +- 12 files changed, 1320 insertions(+), 215 deletions(-) create mode 100644 challenges.yml create mode 100644 src/main/java/bskyblock/addon/challenges/FreshSqueezedChallenges.java create mode 100644 src/main/java/bskyblock/addon/challenges/commands/admin/SetIcon.java diff --git a/addon.yml b/addon.yml index 7ca9e6d..b9a53ff 100755 --- a/addon.yml +++ b/addon.yml @@ -2,7 +2,7 @@ name: BSkyBlock-Challenges main: bskyblock.addon.challenges.ChallengesAddon version: 0.1 -authors: [tastybento] +authors: tastybento permissions: bskyblock.island.challenges: diff --git a/challenges.yml b/challenges.yml new file mode 100644 index 0000000..ad122bd --- /dev/null +++ b/challenges.yml @@ -0,0 +1,778 @@ +########################################################################################## +# Challenges +# Rewards and required items have to be described using Bukkit Materials +# and be exactly correct +# Do not use Type Id's - they will not work +# Challenges can be one of three types - inventory, island or level. +# inventory - means the player must have the items on them +# island - means the items have to be on the island and within 10 blocks of the player +# entities are also supported, e.g., COW. +# level - means the island level has to be equal or over this amount. +# If level is set as nothing '', then the challenge is a free challenge and can be +# done at any time. +# Challenges can be repeatable only if they are inventory challenges +# permissions can be given as a reward +# +# Reward Commands - commands can be run when a challenge is completed and repeated +# Commands are: +# rewardcommands: +# - command1 +# - command2 +# repeatrewardcommands: +# - command1 +# - command2 +# The commands are listed and run in order. Do not put a / in front of the command. +# The token [player] will be replaced with the player's name. +# Example: +# rewardcommands: +# - pex promote [player] +# - heal [player] +# - warp winner_circle [player] +# If a command fails, it will be noted in the console. +# +# The format for POTIONS is as follows: +# +# Format POTION:NAME::::QTY +# LEVEL, EXTENDED, SPLASH, LINGER are optional. +# LEVEL is a number, 1 or 2 +# LINGER is for V1.9 servers and later +# Examples: +# POTION:STRENGTH:1:EXTENDED:SPLASH:1 +# POTION:INSTANT_DAMAGE:2::LINGER:2 +# POTION:JUMP:2:NOTEXTENDED:NOSPLASH:1 +# POTION:WEAKNESS::::1 - any weakness potion +# +# Valid potion names are: +# WATER, REGEN, SPEED, FIRE_RESISTANCE, POISON, INSTANT_HEAL, NIGHT_VISION, WEAKNESS, +# STRENGTH, SLOWNESS, JUMP, INSTANT_DAMAGE, WATER_BREATHING, INVISIBILITY +# For V1.9 these are also available: +# LUCK, MUNDANE, THICK, AWKWARD +# +# +# Reseting islands and challenges - usually challenges are reset when a player resets +# their island (see resetchallenges in config.yml). You can stop some challenges from +# being reset by using resetallowed:false in the challenge. +########################################################################################## + +challenges: + # Challenge levels - list as many as you like. If a challenge's level is '' it can + # be done anytime. You cannot name a challenge the same as a level. + levels: 'Novice Competent Expert Advanced Elite' + + # The number of undone tasks that can be left on a level before unlocking next level + waiveramount: 1 + + # Free levels - which levels above should be auto done when reached, therefore unlocking next level. + # Example: + # freelevels: 'Novice' will immediately put player onto Competent level challenges + # freelevels: 'Novice Competent' will make all Novice, Competent and Expert challenges available immediately. + # freelevels: 'Competent' will open Competent and Expert levels once Novice is complete + freelevels: '' + + # This section determines what happens when a player unlocks a new level + # The subname should correspond to the levels listed above + # Note that there is no section for the first level as it is automatically unlocked + levelUnlock: + Competent: + # What additional message to send player + message: 'Congratulations - you unlocked the &9Competent level!' + rewardDesc: 'A diamond!' + itemReward: 'DIAMOND:1' + moneyReward: 100 + expReward: 100 + # List permissions separated by spaces + permissionReward: '' + # Commands to run on this player. Use [player] for their name. + commands: + #- kit tools [player] + #- some other command + Expert: + # What additional message to send player + message: 'Congratulations - you unlocked the &aExpert level!' + rewardDesc: '3 diamonds!' + itemReward: 'DIAMOND:3' + moneyReward: 100 + expReward: 100 + permissionReward: '' + # Commands to run on this player. Use [player] for their name. + commands: + #- kit tools [player] + #- some other command + Advanced: + # What additional message to send player + message: 'Congratulations - you unlocked the &bAdvanced level!' + rewardDesc: '5 diamonds!' + itemReward: 'DIAMOND:5' + moneyReward: 100 + expReward: 100 + permissionReward: '' + # Commands to run on this player. Use [player] for their name. + commands: + #- kit tools [player] + #- some other command + Elite: + # What additional message to send player + message: 'Congratulations - you unlocked the &dElite level!' + rewardDesc: '7 diamonds!' + itemReward: 'DIAMOND:7' + moneyReward: 100 + expReward: 100 + permissionReward: '' + # Commands to run on this player. Use [player] for their name. + commands: + #- kit tools [player] + #- some other command + + # Challenge list + # Challenge names must be in lowercase. Do not use the same name as a level! + challengeList: + glassmaker: + friendlyname: 'Glass Maker' + description: 'Create 1 block of glass' + icon: GLASS + level: 'Novice' + type: inventory + requiredItems: 'GLASS:1' + # You can require the player has a certain amount of money for inventory challenges. + # Remember to mention it in the description! + # If takeItems is true, the money will be removed, so you may want to give it + # back in the reward. + #requiredMoney: 10 + takeItems: true + itemReward: 'ICE:1' + rewardText: '1 block of ice' + #rewardcommands: + #- kit tools [player] + moneyReward: 10 + expReward: 30 + permissionReward: '' + repeatable: true + repeatItemReward: 'ICE:1' + repeatRewardText: '1 block of ice' + repeatMoneyReward: 5 + repeatExpReward: 10 + #repeatrewardcommands: + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 2 + # Allow this challenge to reset when the player resets their island + # Default is true. Set to false to keep this challenge completed. + # Admins can always reset challenges even if this is set to false. + resetallowed: true + breadmaker: + friendlyname: 'Bread Maker' + description: 'Bake 21 loaves of bread' + icon: BREAD + level: 'Novice' + type: inventory + requiredItems: 'BREAD:21' + takeItems: true + itemReward: 'DIRT:5' + rewardText: '5 dirt' + moneyReward: 10 + expReward: 30 + permissionReward: '' + repeatable: true + repeatItemReward: 'DIRT:1' + repeatRewardText: '1 dirt' + repeatMoneyReward: 5 + repeatExpReward: 10 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + dyemaker: + friendlyname: 'Dye Maker' + description: 'Craft 32 cactus green dyes' + icon: INK_SACK:2 + level: 'Novice' + type: inventory + requiredItems: 'INK_SACK:2:32' + takeItems: true + itemReward: 'SAPLING:0:2 SAPLING:1:2 SAPLING:2:2 SAPLING:3:2' + rewardText: '2 oak, 2 birch, 2 jungle and 2 spruce saplings' + moneyReward: 10 + expReward: 30 + permissionReward: '' + repeatable: true + repeatItemReward: 'SAPLING:0:1 SAPLING:1:1 SAPLING:2:1 SAPLING:3:1 SAPLING:4:1 SAPLING:5:1' + repeatRewardText: '1 of each kind of sapling' + repeatMoneyReward: 5 + repeatExpReward: 10 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + papermaker: + friendlyname: 'Paper Maker' + description: 'Create 21 pages of paper' + icon: PAPER + level: 'Novice' + type: inventory + requiredItems: 'PAPER:21' + takeItems: true + itemReward: 'DIRT:5 CLAY:15' + rewardText: '5 dirt and 15 clay blocks' + moneyReward: 15 + expReward: 30 + permissionReward: '' + repeatable: true + repeatItemReward: 'SAND:2' + repeatRewardText: '2 sand blocks' + repeatMoneyReward: 5 + repeatExpReward: 10 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + cobblemaker: + friendlyname: 'Cobble Maker' + description: 'Create a cobblestone generator and mine 64 cobblestone.' + icon: COBBLESTONE + level: 'Novice' + type: inventory + requiredItems: 'COBBLESTONE:64' + takeItems: true + itemReward: 'LEATHER:4' + permissionReward: '' + rewardText: '4 leather - boots or a book perhaps?' + moneyReward: 10 + expReward: 30 + repeatable: true + repeatItemReward: 'LEATHER:1' + repeatRewardText: '1 leather' + repeatMoneyReward: 5 + repeatExpReward: 10 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + seedbank: + friendlyname: 'Seedbank' + description: 'Collect 64 melon seeds, 64 pumpkin seeds and 64 wheat seeds' + icon: PUMPKIN_SEEDS + level: 'Novice' + type: inventory + requiredItems: 'MELON_SEEDS:64 PUMPKIN_SEEDS:64 SEEDS:64' + takeItems: true + itemReward: 'DIRT:5 VINE:20' + rewardText: '5 dirt blocks and 20 vines' + moneyReward: 15 + expReward: 30 + permissionReward: '' + repeatable: true + repeatItemReward: 'DIRT:2 VINE:20' + repeatRewardText: '2 dirt blocks and 5 vines' + repeatMoneyReward: 5 + repeatExpReward: 10 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + stewmaker: + friendlyname: 'Stew Maker' + description: 'Cook up 18 bowls of mushroom stew' + icon: MUSHROOM_SOUP + level: 'Novice' + type: inventory + requiredItems: 'MUSHROOM_SOUP:18' + takeItems: true + itemReward: 'MYCEL:2' + rewardText: '2 mycelium blocks' + moneyReward: 15 + expReward: 30 + permissionReward: '' + repeatable: true + repeatItemReward: 'MYCEL:1' + repeatRewardText: '1 mycelium block' + repeatMoneyReward: 5 + repeatExpReward: 10 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + builder: + friendlyname: 'Builder' + description: 'Reach island level 10 (/[label] level).' + icon: WOOD + level: 'Novice' + type: level + requiredItems: 10 + takeItems: false + itemReward: 'IRON_PICKAXE:1 DIRT:5 SPONGE:1' + rewardText: '1 iron pickaxe, 5 dirt and a Sponge' + moneyReward: 50 + expReward: 50 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + grinder: + description: 'Kill monsters and collect 64 rotten flesh, 32 skeleton bones, 32 string, 32 arrows, 16 gunpowder, 5 spider eyes' + icon: BONE + level: 'Competent' + type: inventory + requiredItems: 'ROTTEN_FLESH:64 STRING:32 SULPHUR:16 ARROW:32 BONE:32 SPIDER_EYE:5' + takeItems: true + itemReward: 'REDSTONE:16 IRON_ORE:5 FLINT:1 POTION:WATER_BREATHING:1 POTION:NIGHT_VISION:1' + rewardText: '16 redstone dust, 1 flint, 1 water breathing potion, 1 night vision potion and 5 iron(ore)' + moneyReward: 75 + expReward: 75 + permissionReward: '' + repeatable: true + repeatItemReward: 'REDSTONE:2 IRON_ORE:1 FLINT:1 POTION:WATER_BREATHING:1' + repeatRewardText: '2 redstone dust, 1 flint, 1 water breathing potion and 1 iron(ore)' + repeatMoneyReward: 15 + repeatExpReward: 15 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + farmer: + description: 'Harvest 64 units of the following: wheat, sugar, melon, carrots, potatoes, pumpkin' + icon: WHEAT + level: 'Competent' + type: inventory + requiredItems: 'WHEAT:64 SUGAR:64 MELON:64 CARROT_ITEM:64 POTATO_ITEM:64 PUMPKIN:64' + takeItems: true + itemReward: 'REDSTONE:16 INK_SACK:3:1 MONSTER_EGG:PIG:1 MONSTER_EGG:COW:1 MONSTER_EGG:CHICKEN:1' + rewardText: '16 redstone dust, 1 cocoa bean, 1 spawn egg(chicken,cow,pig)' + moneyReward: 75 + expReward: 75 + permissionReward: '' + repeatable: true + repeatItemReward: 'INK_SACK:3:1 MONSTER_EGG:PIG:1 MONSTER_EGG:COW:1 MONSTER_EGG:CHICKEN:1' + repeatRewardText: '1 cocoa bean, 1 spawn egg(chicken,cow,pig)' + repeatMoneyReward: 20 + repeatExpReward: 20 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + angler: + friendlyname: 'Angler' + description: 'Catch and cook 10 standard fish (no salmon)' + icon: COOKED_FISH + level: 'Competent' + type: inventory + requiredItems: 'COOKED_FISH:10' + takeItems: true + itemReward: 'REDSTONE:16 IRON_ORE:5 INK_SACK:5' + rewardText: '16 redstone dust, 5 inksacs, 5 iron (ore)' + moneyReward: 75 + expReward: 75 + permissionReward: '' + repeatable: true + repeatItemReward: 'REDSTONE:2 IRON_ORE:1 INK_SACK:1' + repeatRewardText: '2 redstone dust, 1 inksac, 1 iron (ore)' + repeatMoneyReward: 15 + repeatExpReward: 15 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + treecutter: + friendlyname: 'Treecutter' + description: 'Create a tree farm and collect 16 oak, birch, jungle, and spruce logs' + icon: LOG + level: 'Competent' + type: inventory + requiredItems: 'LOG:0:16 LOG:1:16 LOG:2:16 LOG:3:16' + takeItems: true + itemReward: 'REDSTONE:16 IRON_ORE:5 MONSTER_EGG:WOLF:1' + rewardText: '16 redstone dust, 5 iron (ore), 1 wolf spawn egg' + moneyReward: 75 + expReward: 75 + permissionReward: '' + repeatable: true + repeatItemReward: 'REDSTONE:2 IRON_ORE:1' + repeatRewardText: '2 redstone dust, 1 iron (ore)' + repeatMoneyReward: 15 + repeatExpReward: 15 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + cookiemaker: + friendlyname: 'Cookie Maker' + description: 'Make 128 cookies and a bucket of milk' + icon: COOKIE + level: 'Competent' + type: inventory + requiredItems: 'MILK_BUCKET:1 COOKIE:128' + takeItems: true + itemReward: 'REDSTONE:16 IRON_ORE:5' + rewardText: '16 redstone dust, 5 iron (ore)' + moneyReward: 75 + expReward: 75 + permissionReward: '' + repeatable: true + repeatItemReward: 'REDSTONE:2 IRON_ORE:1' + repeatRewardText: '2 redstone dust, 1 iron (ore)' + repeatMoneyReward: 15 + repeatExpReward: 15 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + craftsman: + friendlyname: 'Craftsman' + description: 'Reach island level 75 (/[label] level).' + icon: IRON_BLOCK + level: 'Competent' + type: level + requiredItems: 75 + takeItems: false + itemReward: 'OBSIDIAN:10' + rewardText: '10 obsidian blocks' + moneyReward: 50 + expReward: 50 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + homestead: + friendlyname: 'Homestead' + description: 'Build a house that contains at least 1 wooden door, bed, bookshelf, crafting table, furnace, glass-block window, and torch.' + icon: BED + level: 'Competent' + type: island + requiredItems: 'BED_BLOCK:1 WORKBENCH:1 GLASS:1 WOODEN_DOOR:1 FURNACE:1 BOOKSHELF:1 TORCH:1' + # Search radius - the number of blocks that will be searched around the player + # Minimum 10, which searches from -10 to +10 blocks around the player in x,y,z + # Max is 50 because big searches cause lag + searchRadius: 10 + takeItems: false + itemReward: 'JUKEBOX:1 RECORD_12:1 LAPIS_BLOCK:10' + rewardText: '1 jukebox, 1 music disk, 10 lapis lazuli blocks' + moneyReward: 100 + expReward: 100 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + nether: + friendlyname: 'Nether' + description: 'Build a nether portal on your island and activate it.' + icon: NETHERRACK + level: 'Expert' + type: island + requiredItems: 'OBSIDIAN:10 PORTAL:1' + takeItems: false + itemReward: 'DIAMOND_SWORD:1' + rewardText: '1 diamond sword' + moneyReward: 100 + expReward: 100 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + enderpearls: + friendlyname: 'Enderpearls' + description: 'Collect 15 enderpearls from endermen' + icon: ENDER_PEARL + level: 'Expert' + type: inventory + requiredItems: 'ENDER_PEARL:15' + takeItems: true + itemReward: 'GOLD_INGOT:5 BLAZE_ROD:1' + rewardText: '5 gold ingots and 1 blaze rod' + moneyReward: 50 + expReward: 100 + permissionReward: '' + repeatable: true + repeatItemReward: 'GOLD_INGOT:1 BLAZE_ROD:1' + repeatRewardText: '1 gold ingot and 1 blaze rod' + repeatMoneyReward: 15 + repeatExpReward: 15 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + slimeballfarmer: + friendlyname: 'Slimeball Farmer' + description: 'Collect 40 slimeballs from slimes' + icon: SLIME_BALL + level: 'Expert' + type: inventory + requiredItems: 'SLIME_BALL:40' + takeItems: true + itemReward: 'GOLD_INGOT:5 IRON_ORE:5' + rewardText: '5 gold ingots and 5 blocks of iron ore' + moneyReward: 50 + expReward: 100 + permissionReward: '' + repeatable: true + repeatItemReward: 'REDSTONE:8' + repeatRewardText: '8 redstone dust' + repeatMoneyReward: 15 + repeatExpReward: 15 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + baker: + friendlyname: 'baker' + description: 'Bake 5 cakes and 5 pumpkin pies' + icon: CAKE + level: 'Expert' + type: inventory + requiredItems: 'CAKE:5 PUMPKIN_PIE:5' + takeItems: true + itemReward: 'GOLD_INGOT:5 DIAMOND:1' + rewardText: '5 gold ingots and 1 diamond' + moneyReward: 50 + expReward: 100 + permissionReward: '' + repeatable: true + repeatItemReward: 'IRON_ORE:1' + repeatRewardText: '1 iron (ore)' + repeatMoneyReward: 15 + repeatExpReward: 15 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + pioneer: + friendlyname: 'Pioneer' + description: 'Make 1 map and use it, a compass, a clock and collect 64 netherrack, 16 soulsand, and 1 ghast tear' + icon: MAP + level: 'Expert' + type: inventory + requiredItems: 'NETHERRACK:64 SOUL_SAND:16 GHAST_TEAR:1 MAP:1 COMPASS:1 WATCH:1' + takeItems: true + itemReward: 'POWERED_RAIL:32 RAILS:256 DIAMOND:1 MONSTER_EGG:OCELOT:1' + rewardText: '256 rails, 32 powered rails, 1 ocelot spawn egg, 1 diamond' + moneyReward: 100 + expReward: 100 + permissionReward: '' + repeatable: true + repeatItemReward: 'IRON_ORE:1' + repeatRewardText: '1 iron (ore)' + repeatMoneyReward: 20 + repeatExpReward: 20 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + mason: + friendlyname: 'Mason' + description: 'Reach island level 150 (/[label] level).' + icon: GOLD_BLOCK + level: 'Expert' + type: level + requiredItems: 150 + takeItems: false + itemReward: 'DIAMOND:1 DIRT:20 GOLD_BLOCK:2' + rewardText: '1 diamond, 20 dirt, and 2 gold blocks' + moneyReward: 150 + expReward: 150 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + shepherd: + friendlyname: 'Shepherd' + description: 'Collect 5 of every color of wool' + icon: WOOL:2 + level: 'Advanced' + type: inventory + requiredItems: 'WOOL:0:5 WOOL:1:5 WOOL:2:5 WOOL:3:5 WOOL:4:5 WOOL:5:5 WOOL:6:5 WOOL:7:5 WOOL:8:5 WOOL:9:5 WOOL:10:5 WOOL:11:5 WOOL:12:5 WOOL:13:5 WOOL:14:5 WOOL:15:5' + takeItems: true + itemReward: 'DIAMOND:2 RECORD_7:1 RECORD_8:1 RECORD_6:1 MONSTER_EGG:SHEEP:1 EMERALD:5' + rewardText: '2 diamonds, 5 emeralds, 3 music disks, 1 sheep spawn egg' + moneyReward: 200 + expReward: 200 + permissionReward: '' + repeatable: true + repeatItemReward: 'EMERALD:1 MONSTER_EGG:SHEEP:1' + repeatRewardText: '1 emerald, 1 sheep spawn egg' + repeatMoneyReward: 20 + repeatExpReward: 20 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + alchemist: + friendlyname: 'Alchemist' + description: 'Brew 1 potion of Fire Resistance, Slowness, Swiftness, Healing, Harming, Invisibility, Strength and Regeneration' + icon: BREWING_STAND_ITEM + level: 'Advanced' + type: inventory + requiredItems: 'POTION:FIRE_RESISTANCE::::1 POTION:SLOWNESS::::1 POTION:SPEED::::1 POTION:INSTANT_HEAL::::1 POTION:INSTANT_DAMAGE::::1 POTION:INVISIBILITY::::1 POTION:STRENGTH::::1 POTION:REGEN::::1' + takeItems: true + itemReward: 'ENCHANTMENT_TABLE:1' + rewardText: 'Enchantment Table' + moneyReward: 200 + expReward: 200 + permissionReward: '' + repeatable: true + repeatItemReward: 'DIAMOND:1' + repeatRewardText: '1 diamond' + repeatMoneyReward: 20 + repeatExpReward: 20 + dj: + friendlyname: 'DJ' + description: 'Craft a jukebox and collect all music discs' + icon: RECORD_5 + level: 'Advanced' + type: inventory + requiredItems: 'GOLD_RECORD:1 GREEN_RECORD:1 RECORD_3:1 RECORD_4:1 RECORD_5:1 RECORD_6:1 RECORD_7:1 RECORD_8:1 RECORD_9:1 RECORD_10:1 RECORD_11:1 RECORD_12:1 JUKEBOX:1' + takeItems: true + itemReward: 'DIAMOND:3 EMERALD:10 GOLD_INGOT:5' + rewardText: '3 diamonds, 10 emeralds and 5 gold ingots' + moneyReward: 200 + expReward: 200 + permissionReward: '' + repeatable: true + repeatItemReward: 'DIAMOND:1 EMERALD:5 GOLD_INGOT:2' + repeatRewardText: '1 diamond, 5 emeralds and 2 gold bars' + repeatMoneyReward: 20 + repeatExpReward: 20 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + gemcollector: + friendlyname: 'Gem Collector' + description: 'Collect 50 emeralds' + icon: EMERALD + level: 'Advanced' + type: inventory + requiredItems: 'EMERALD:50' + takeItems: true + itemReward: 'DIAMOND:10' + rewardText: '10 diamonds' + moneyReward: 200 + expReward: 200 + permissionReward: '' + repeatable: true + repeatItemReward: 'GOLD_INGOT:2' + repeatRewardText: '2 gold ingots' + repeatMoneyReward: 20 + repeatExpReward: 20 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + culinaryartist: + friendlyname: 'Culinary Artist' + description: 'Collect 1 of every kind of cooked or crafted edible food (no raw food, zombie flesh, or super golden apples)' + icon: GOLDEN_APPLE + level: 'Advanced' + type: inventory + requiredItems: 'BAKED_POTATO:1 BREAD:1 CAKE:1 COOKED_CHICKEN:1 COOKED_FISH:1 GRILLED_PORK:1 COOKIE:1 GOLDEN_APPLE:0:1 GOLDEN_CARROT:1 MUSHROOM_SOUP:1 PUMPKIN_PIE:1 COOKED_BEEF:1' + # If you are running 1.8 change to this: + # requiredItems: 'BAKED_POTATO:1 BREAD:1 CAKE:1 COOKED_CHICKEN:1 COOKED_FISH:1 GRILLED_PORK:1 COOKIE:1 GOLDEN_APPLE:0:1 GOLDEN_CARROT:1 MUSHROOM_SOUP:1 PUMPKIN_PIE:1 COOKED_BEEF:1 COOKED_RABBIT:1 RABBIT_STEW:1 COOKED_MUTTON:1' + takeItems: true + itemReward: 'GOLD_BLOCK:2 GREEN_RECORD:1 RECORD_3:1 RECORD_5:1 MONSTER_EGG:MUSHROOM_COW:1 EMERALD:5' + rewardText: '2 gold blocks, 3 music discs, 1 mooshroom spawn egg, and 5 emeralds' + moneyReward: 200 + expReward: 200 + permissionReward: '' + repeatable: true + repeatItemReward: 'GOLD_INGOT:10 MONSTER_EGG:MUSHROOM_COW:1 EMERALD:1' + repeatRewardText: '10 gold ingots, 1 mooshroom spawn egg, 1 emerald' + repeatMoneyReward: 20 + repeatExpReward: 20 + # Max times limits how many times a challenge can be done. Comment out to make unlimited + maxtimes: 100 + beaconator: + friendlyname: 'Beaconator' + description: 'Build a beacon and let it shine!' + icon: BEACON + level: 'Advanced' + type: island + requiredItems: 'BEACON:1' + takeItems: false + itemReward: 'SMOOTH_BRICK:20 SMOOTH_BRICK:1:20 SMOOTH_BRICK:2:20 SMOOTH_BRICK:3:20' + rewardText: '20 blocks of every kind of stone brick' + moneyReward: 300 + expReward: 300 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + ittakesavillage: + friendlyname: 'It Takes A Village' + description: 'Hold a village meeting with 10 villagers!' + icon: STONE + level: 'Advanced' + type: island + requiredItems: 'VILLAGER:10' + takeItems: false + itemReward: 'HOPPER:4' + rewardText: '4 hoppers' + moneyReward: 300 + expReward: 300 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + myprecious: + friendlyname: 'My Precious' + description: 'Build an iron golem' + icon: NAME_TAG + level: 'Advanced' + type: island + requiredItems: 'IRON_GOLEM:1' + takeItems: false + itemReward: 'NAME_TAG:1 ANVIL:1 CAULDRON_ITEM:1 IRON_BLOCK:2' + rewardText: 'A name tag, an anvil, a cauldron and 2 iron blocks' + moneyReward: 300 + expReward: 300 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + snowplay: + friendlyname: 'Snow Play!' + description: 'Build a snow golem' + icon: SNOW_BALL + level: 'Advanced' + type: island + requiredItems: 'SNOWMAN:1' + takeItems: false + itemReward: 'DIAMOND_SPADE:1' + rewardText: 'A diamond spade - get shoveling!' + moneyReward: 300 + expReward: 300 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + itsaparty: + friendlyname: "It's a party" + description: 'Have a party! Invite 4 friends.' + icon: PUMPKIN_PIE + level: 'Advanced' + type: island + requiredItems: 'PLAYER:5' + takeItems: false + itemReward: 'EMERALD:6 PUMPKIN_PIE:6' + rewardText: '6 Emeralds, 6 pumpkin pies' + moneyReward: 200 + expReward: 200 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + itsamonsterparty: + friendlyname: "It's a Monster Party" + description: 'Have a party - all monsters invited! Get close to a Skeleton, Zombie, Spider, Creeper and Enderman all at the same time.' + icon: SKULL_ITEM + level: 'Advanced' + type: island + requiredItems: 'SKELETON:1 ZOMBIE:1 SPIDER:1 CREEPER:1 ENDERMAN:1' + takeItems: false + itemReward: 'SKULL_ITEM:0:2 SKULL_ITEM:2:2 SKULL_ITEM:3:2' + rewardText: 'Skulls!' + moneyReward: 200 + expReward: 400 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 + acidduke: + friendlyname: 'Arch Duke' + description: 'Achieve an island level of 1000' + icon: DIAMOND_BLOCK + level: 'Elite' + type: level + requiredItems: 1000 + takeItems: false + itemReward: 'DIAMOND:1' + rewardText: '1 diamond' + moneyReward: 250 + expReward: 250 + permissionReward: '' + repeatable: false + repeatItemReward: '' + repeatRewardText: '' + repeatMoneyReward: 0 + repeatExpReward: 0 diff --git a/locales/en-US.yml b/locales/en-US.yml index a6328bd..b5f967c 100755 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -65,4 +65,8 @@ challenges: no-name: "You must include a challenge name" challenge-created: "[challenge] created!" you-added: "You added one [thing] to the challenge" - \ No newline at end of file + seticon: + error: + no-such-challenge: "&cNo such challenge name" + description: "sets the challenge icon to inhand item" + parameters: "[challenge name]" \ No newline at end of file diff --git a/src/main/java/bskyblock/addon/challenges/ChallengesAddon.java b/src/main/java/bskyblock/addon/challenges/ChallengesAddon.java index 33310c4..05b73f6 100644 --- a/src/main/java/bskyblock/addon/challenges/ChallengesAddon.java +++ b/src/main/java/bskyblock/addon/challenges/ChallengesAddon.java @@ -1,34 +1,11 @@ package bskyblock.addon.challenges; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.logging.Logger; - import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.potion.PotionData; -import org.bukkit.potion.PotionType; - -import com.google.gson.Gson; import bskyblock.addon.challenges.commands.ChallengesCommand; import bskyblock.addon.challenges.commands.admin.ChallengesAdminCommand; import bskyblock.addon.challenges.config.PluginConfig; -import bskyblock.addon.challenges.database.object.Challenges; -import bskyblock.addon.challenges.database.object.Challenges.ChallengeType; -import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.api.addons.Addon; -import us.tastybento.bskyblock.database.DatabaseConnectionSettingsImpl; -import us.tastybento.bskyblock.database.mysql.MySQLDatabaseConnecter; /** * Add-on to BSkyBlock that enables challenges @@ -52,76 +29,13 @@ public class ChallengesAddon extends Addon { // Challenges Manager challengesManager = new ChallengesManager(this); + // First time challenges creation + new FreshSqueezedChallenges(this); + // Register commands new ChallengesCommand(this); new ChallengesAdminCommand(this); // Done - /* - Gson gson = new Gson(); - Challenges challenges = new Challenges(); - challenges.setChallengeType(ChallengeType.SURROUNDING); - Map map = new HashMap<>(); - map.put(Material.DIRT, 5); - map.put(Material.ACACIA_FENCE_GATE, 3); - challenges.setRequiredBlocks(map); - challenges.setIcon(new ItemStack(Material.ACACIA_FENCE_GATE)); - List requiredItems = new ArrayList<>(); - ItemStack result = new ItemStack(Material.POTION, 55); - ItemStack result2 = new ItemStack(Material.SPLASH_POTION, 22); - ItemStack result3 = new ItemStack(Material.LINGERING_POTION, 11); - - PotionMeta potionMeta = (PotionMeta) result.getItemMeta(); - PotionData potionData = new PotionData(PotionType.FIRE_RESISTANCE, true, false); - potionMeta.setBasePotionData(potionData); - result.setItemMeta(potionMeta); - - PotionMeta potionMeta2 = (PotionMeta) result2.getItemMeta(); - PotionData potionData2 = new PotionData(PotionType.SPEED, true, false); - potionMeta2.setBasePotionData(potionData2); - potionMeta2.addEnchant(Enchantment.BINDING_CURSE, 1, true); - result2.setItemMeta(potionMeta2); - - requiredItems.add(result); - requiredItems.add(result2); - requiredItems.add(result3); - challenges.setRequiredItems(requiredItems); - challenges.setUniqueId(UUID.randomUUID().toString()); - String json = gson.toJson(challenges); - - Logger.getAnonymousLogger().info(json); - - BSkyBlock plugin = BSkyBlock.getInstance(); - MySQLDatabaseConnecter conn = new MySQLDatabaseConnecter(new DatabaseConnectionSettingsImpl( - plugin.getSettings().getDbHost(), - plugin.getSettings().getDbPort(), - plugin.getSettings().getDbName(), - plugin.getSettings().getDbUsername(), - plugin.getSettings().getDbPassword() - )); - try (Connection connection = conn.createConnection()) { - StringBuilder sql = new StringBuilder(); - sql.append("create table if not exists test (json JSON, uniqueId VARCHAR(255) GENERATED ALWAYS AS (json->\"$.uniqueId\"), INDEX i (uniqueId) );"); - // Prepare and execute the database statements - try (PreparedStatement pstmt = connection.prepareStatement(sql.toString())) { - pstmt.executeUpdate(); - } catch (SQLException e) { - plugin.getLogger().severe(() -> "Problem trying to create schema for data object "); - } - sql = new StringBuilder(); - sql.append("INSERT INTO `TEST` (`json`) VALUES (?)"); - try (PreparedStatement pstmt = connection.prepareStatement(sql.toString())) { - pstmt.setString(1, json); - pstmt.executeUpdate(); - } catch (SQLException e) { - plugin.getLogger().severe(() -> "Problem trying to create data object "); - e.printStackTrace(); - } - - } catch (SQLException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - */ } @Override diff --git a/src/main/java/bskyblock/addon/challenges/ChallengesManager.java b/src/main/java/bskyblock/addon/challenges/ChallengesManager.java index a80efae..6f971f0 100644 --- a/src/main/java/bskyblock/addon/challenges/ChallengesManager.java +++ b/src/main/java/bskyblock/addon/challenges/ChallengesManager.java @@ -1,10 +1,13 @@ package bskyblock.addon.challenges; import java.util.ArrayList; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import org.bukkit.Bukkit; @@ -26,7 +29,7 @@ import us.tastybento.bskyblock.util.Util; public class ChallengesManager { public static final String FREE = "Free"; - private LinkedHashMap> challengeList; + private LinkedHashMap> challengeList; private BSBConfig chConfig; private BSBConfig lvConfig; private ChallengesPanels challengesPanels; @@ -41,6 +44,46 @@ public class ChallengesManager { load(); } + /** + * Check if a challenge exists - case insensitive + * @param name - name of challenge + * @return true if it exists, otherwise false + */ + public boolean isChallenge(String name) { + for (Set ch : challengeList.values()) { + if (ch.stream().filter(c -> c.getUniqueId().equalsIgnoreCase(name)).findFirst().isPresent()) { + return true; + } + } + return false; + } + + /** + * Get challenge by name + * @param name - unique name of challenge + * @return - challenge or null if it does not exist + */ + public Challenges getChallenge(String name) { + for (Set ch : challengeList.values()) { + Optional challenge = ch.stream().filter(c -> c.getUniqueId().equalsIgnoreCase(name)).findFirst(); + if (challenge.isPresent()) { + return challenge.get(); + } + } + return null; + } + + /** + * Get the list of all challenge unique names. + * Used for checking admin commands and tab complete + * @return List of challenge names + */ + public List getAllChallengesList() { + List result = new ArrayList<>(); + challengeList.values().forEach(ch -> ch.forEach(c -> result.add(c.getUniqueId()))); + return result; + } + public long checkChallengeTimes(User user, Challenges challenge) { // TODO Auto-generated method stub return 0; @@ -69,7 +112,6 @@ public class ChallengesManager { newChallenge.setTakeItems(true); newChallenge.setUniqueId(inventory.getTitle()); newChallenge.setIcon(new ItemStack(Material.EMPTY_MAP)); - newChallenge.setFreeChallenge(true); newChallenge.setLevel(FREE); newChallenge.setDescription(createDescription(user, requiredItems)); @@ -119,14 +161,13 @@ public class ChallengesManager { return false; } Challenges newChallenge = new Challenges(); - newChallenge.setChallengeType(ChallengeType.SURROUNDING); + newChallenge.setChallengeType(ChallengeType.ISLAND); newChallenge.setFriendlyName(challengeInfo.getName()); newChallenge.setDeployed(true); newChallenge.setRequiredBlocks(challengeInfo.getReqBlocks()); newChallenge.setRequiredEntities(challengeInfo.getReqEntities()); newChallenge.setUniqueId(challengeInfo.getName()); newChallenge.setIcon(new ItemStack(Material.ARMOR_STAND)); - newChallenge.setFreeChallenge(true); newChallenge.setLevel(FREE); // Save the challenge @@ -145,7 +186,7 @@ public class ChallengesManager { public List getChallengeLevelStatus(User user) { List result = new ArrayList<>(); ChallengeLevels previousLevel = null; - for (Entry> en : challengeList.entrySet()) { + for (Entry> en : challengeList.entrySet()) { int challsToDo = 0; // TODO - calculate how many challenges still to do for this player boolean complete = false; // TODO result.add(new LevelStatus(en.getKey(), previousLevel, challsToDo, complete)); @@ -154,12 +195,12 @@ public class ChallengesManager { } /** - * Get the list of challenges for this level + * Get the set of challenges for this level * @param level - the level required - * @return the list of challenges for this level, or the first set of challenges if level is blank, or a blank list if there are no challenges + * @return the set of challenges for this level, or the first set of challenges if level is blank, or a blank list if there are no challenges */ - public List getChallenges(String level) { - return challengeList.getOrDefault(level, challengeList.isEmpty() ? new ArrayList() : challengeList.values().iterator().next()); + public Set getChallenges(String level) { + return challengeList.getOrDefault(level, challengeList.isEmpty() ? new HashSet() : challengeList.values().iterator().next()); } /** @@ -215,38 +256,52 @@ public class ChallengesManager { Bukkit.getLogger().info("Loading challenges..."); for (Challenges challenge : chConfig.loadConfigObjects()) { Bukkit.getLogger().info("Loading challenge " + challenge.getFriendlyName() + " level " + challenge.getLevel()); - // See if we have this level already - ChallengeLevels level; - if (lvConfig.configObjectExists(challenge.getLevel())) { - //Bukkit.getLogger().info("DEBUG: Level contains level " + challenge.getLevel()); - // Get it from the database - level = lvConfig.loadConfigObject(challenge.getLevel()); - } else { - //Bukkit.getLogger().info("DEBUG: Level does not contains level " + challenge.getLevel()); - // Make it - level = new ChallengeLevels(); - level.setUniqueId(challenge.getLevel()); - //Bukkit.getLogger().info("DEBUG: Level unique Id set to " + level.getUniqueId()); - lvConfig.saveConfigObject(level); - } - if (challengeList.containsKey(level)) { - //Bukkit.getLogger().info("DEBUG: Challenge contains level " + level.getUniqueId()); - challengeList.get(level).add(challenge); - } else { - //Bukkit.getLogger().info("DEBUG: No key found"); - // First challenge of this level type - List challenges = new ArrayList<>(); - challenges.add(challenge); - challengeList.put(level, challenges); - } + storeChallenge(challenge); } - //Bukkit.getLogger().info("DEBUG: " + challengeList.size()); + sortChallenges(); + } + + public void sortChallenges() { // Sort the challenge list into level order challengeList = challengeList.entrySet().stream() .sorted(Map.Entry.comparingByKey()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldValue, newValue) -> oldValue, LinkedHashMap::new)); - //Bukkit.getLogger().info("DEBUG: " + challengeList.size()); + } + + /** + * Stores the challenge. If a challenge already exists with the same name, it is overwritten. + * @param challenge + */ + public void storeChallenge(Challenges challenge) { + // See if we have this level already + ChallengeLevels level; + if (lvConfig.configObjectExists(challenge.getLevel())) { + //Bukkit.getLogger().info("DEBUG: Level contains level " + challenge.getLevel()); + // Get it from the database + level = lvConfig.loadConfigObject(challenge.getLevel()); + } else { + //Bukkit.getLogger().info("DEBUG: Level does not contains level " + challenge.getLevel()); + // Make it + level = new ChallengeLevels(); + level.setUniqueId(challenge.getLevel()); + //Bukkit.getLogger().info("DEBUG: Level unique Id set to " + level.getUniqueId()); + lvConfig.saveConfigObject(level); + } + if (challengeList.containsKey(level)) { + //Bukkit.getLogger().info("DEBUG: Challenge contains level " + level.getUniqueId()); + // Replace if this challenge uniqueId already exists + if (challengeList.get(level).contains(challenge)) { + challengeList.get(level).remove(challenge); + } + challengeList.get(level).add(challenge); + } else { + //Bukkit.getLogger().info("DEBUG: No key found"); + // First challenge of this level type + Set challenges = new HashSet<>(); + challenges.add(challenge); + challengeList.put(level, challenges); + } } private void save() { @@ -278,4 +333,26 @@ public class ChallengesManager { } + /** + * Checks number of challenges + * @return true if no challenges + */ + public boolean isFirstTime() { + return challengeList.isEmpty(); + } + + /** + * @return the challengeList + */ + public LinkedHashMap> getChallengeList() { + return challengeList; + } + + /** + * @param challengeList the challengeList to set + */ + public void setChallengeList(LinkedHashMap> challengeList) { + this.challengeList = challengeList; + } + } diff --git a/src/main/java/bskyblock/addon/challenges/FreshSqueezedChallenges.java b/src/main/java/bskyblock/addon/challenges/FreshSqueezedChallenges.java new file mode 100644 index 0000000..08968fd --- /dev/null +++ b/src/main/java/bskyblock/addon/challenges/FreshSqueezedChallenges.java @@ -0,0 +1,232 @@ +package bskyblock.addon.challenges; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.inventory.meta.SpawnEggMeta; +import org.bukkit.potion.PotionData; +import org.bukkit.potion.PotionType; + +import bskyblock.addon.challenges.database.object.Challenges; + +public class FreshSqueezedChallenges { + + private static final boolean DEBUG = false; + ChallengesAddon addon; + + public FreshSqueezedChallenges(ChallengesAddon challengesAddon) { + this.addon = challengesAddon; + makeChallenges(); + addon.getChallengesManager().save(true); + } + + /** + * Makes the level 1 challenges + */ + private void makeChallenges() { + File challengeFile = new File(addon.getDataFolder(), "challenges.yml"); + if (!challengeFile.exists()) { + addon.saveResource("challenges.yml",false); + } + YamlConfiguration chal = new YamlConfiguration(); + try { + chal.load(challengeFile); + } catch (IOException | InvalidConfigurationException e) { + addon.getLogger().severe("Could not set up initial challenges"); + } + // Parse the challenge file + ConfigurationSection chals = chal.getConfigurationSection("challenges.challengeList"); + for (String challenge : chals.getKeys(false)) { + Challenges newChallenge = new Challenges(); + newChallenge.setUniqueId(challenge); + ConfigurationSection details = chals.getConfigurationSection(challenge); + newChallenge.setFriendlyName(details.getString("friendlyname", challenge)); + newChallenge.setDescription(details.getString("description", "")); + newChallenge.setIcon(parseItem(details.getString("icon") + ":1")); + newChallenge.setLevel(details.getString("level", ChallengesManager.FREE)); + newChallenge.setChallengeType(Challenges.ChallengeType.valueOf(details.getString("type","INVENTORY").toUpperCase())); + newChallenge.setTakeItems(details.getBoolean("takeItems",true)); + newChallenge.setRewardText(details.getString("rewardText", "")); + newChallenge.setRewardCommands(details.getStringList("rewardcommands")); + newChallenge.setMoneyReward(details.getInt("moneyReward",0)); + newChallenge.setExpReward(details.getInt("expReward")); + newChallenge.setRepeatable(details.getBoolean("repeatable")); + newChallenge.setRepeatRewardText(details.getString("repeatRewardText","")); + newChallenge.setRepeatMoneyReward(details.getInt("repearMoneyReward")); + newChallenge.setRepeatExpReward(details.getInt("repeatExpReward")); + newChallenge.setRepeatRewardCommands(details.getStringList("repeatrewardcommands")); + newChallenge.setMaxTimes(details.getInt("maxtimes")); + // TODO reset allowed + newChallenge.setReqMoney(details.getInt("requiredMoney")); + newChallenge.setReqExp(details.getInt("requiredExp")); + if (newChallenge.getChallengeType().equals(Challenges.ChallengeType.INVENTORY)) { + newChallenge.setRequiredItems(parseItems(details.getString("requiredItems",""))); + } else if (newChallenge.getChallengeType().equals(Challenges.ChallengeType.LEVEL)) { + newChallenge.setReqIslandlevel(Long.parseLong(details.getString("requiredItems",""))); + } else if (newChallenge.getChallengeType().equals(Challenges.ChallengeType.ISLAND)) { + parseEntities(newChallenge, details.getString("requiredItems","")); + } + newChallenge.setItemReward(parseItems(details.getString("itemReward"))); + newChallenge.setRepeatItemReward(parseItems(details.getString("repeatItemReward"))); + // Save + addon.getChallengesManager().storeChallenge(newChallenge); + } + addon.getChallengesManager().sortChallenges(); + } + + private void parseEntities(Challenges challenge, String string) { + Map req = new HashMap<>(); + Map blocks = new HashMap<>(); + if (!string.isEmpty()) { + for (String s : string.split(" ")) { + String[] part = s.split(":"); + try { + for (EntityType type : EntityType.values()) { + if (type.toString().equalsIgnoreCase(part[0])) { + req.put(type, Integer.valueOf(part[1])); + break; + } + } + for (Material type : Material.values()) { + if (type.toString().equalsIgnoreCase(part[0])) { + blocks.put(type, Integer.valueOf(part[1])); + break; + } + } + + } catch (Exception e) { + addon.getLogger().severe("Cannot parse '" + s + "'. Skipping..."); + } + } + } + challenge.setRequiredEntities(req); + challenge.setRequiredBlocks(blocks); + } + + private List parseItems(String reqList) { + List result = new ArrayList<>(); + if (!reqList.isEmpty()) { + for (String s : reqList.split(" ")) { + ItemStack item = parseItem(s); + if (item != null) { + result.add(item); + } + } + } + return result; + } + + @SuppressWarnings("deprecation") + private ItemStack parseItem(String s) { + Material reqItem = null; + int reqAmount = 0; + String[] part = s.split(":"); + // Correct some common mistakes + if (part[0].equalsIgnoreCase("potato")) { + part[0] = "POTATO_ITEM"; + } else if (part[0].equalsIgnoreCase("brewing_stand")) { + part[0] = "BREWING_STAND_ITEM"; + } else if (part[0].equalsIgnoreCase("carrot")) { + part[0] = "CARROT_ITEM"; + } else if (part[0].equalsIgnoreCase("cauldron")) { + part[0] = "CAULDRON_ITEM"; + } else if (part[0].equalsIgnoreCase("skull")) { + part[0] = "SKULL_ITEM"; + } + // TODO: add netherwart vs. netherstalk? + // Material:Qty + if (part.length == 2) { + try { + if (StringUtils.isNumeric(part[0])) { + reqItem = Material.getMaterial(Integer.parseInt(part[0])); + } else { + reqItem = Material.getMaterial(part[0].toUpperCase()); + } + reqAmount = Integer.parseInt(part[1]); + ItemStack item = new ItemStack(reqItem); + if (DEBUG) { + addon.getLogger().info("DEBUG: required item = " + reqItem.toString()); + addon.getLogger().info("DEBUG: item amount = " + reqAmount); + } + return item; + + } catch (Exception e) { + addon.getLogger().severe("Problem with " + s + " in challenges.yml!"); + } + } else if (part.length == 3) { + if (DEBUG) + addon.getLogger().info("DEBUG: Item with durability"); + if (StringUtils.isNumeric(part[0])) { + reqItem = Material.getMaterial(Integer.parseInt(part[0])); + } else { + reqItem = Material.getMaterial(part[0].toUpperCase()); + } + reqAmount = Integer.parseInt(part[2]); + ItemStack item = new ItemStack(reqItem); + int reqDurability = 0; + if (StringUtils.isNumeric(part[1])) { + reqDurability = Integer.parseInt(part[1]); + item.setDurability((short) reqDurability); + } else if (reqItem.equals(Material.MONSTER_EGG)) { + reqDurability = -1; // non existent + // Check if this is a string + EntityType entityType = EntityType.valueOf(part[1]); + item = new ItemStack(Material.MONSTER_EGG); + SpawnEggMeta meta = ((SpawnEggMeta)item.getItemMeta()); + meta.setSpawnedType(entityType); + item.setItemMeta(meta); + } + return item; + } else if (part.length == 6 && part[0].contains("POTION")) { + try { + reqAmount = Integer.parseInt(part[5]); + if (DEBUG) + addon.getLogger().info("DEBUG: required amount is " + reqAmount); + } catch (Exception e) { + addon.getLogger().severe("Could not parse the quantity of the potion item " + s); + return null; + } + /* + * # Format POTION:NAME::::QTY + # LEVEL, EXTENDED, SPLASH, LINGER are optional. + # LEVEL is a number, 1 or 2 + # LINGER is for V1.9 servers and later + # Examples: + # POTION:STRENGTH:1:EXTENDED:SPLASH:1 + # POTION:INSTANT_DAMAGE:2::LINGER:2 + # POTION:JUMP:2:NOTEXTENDED:NOSPLASH:1 + # POTION:WEAKNESS::::1 - any weakness potion + */ + ItemStack item = part[4].isEmpty() ? new ItemStack(Material.POTION) : part[4].equalsIgnoreCase("SPLASH") + ? new ItemStack(Material.SPLASH_POTION) : new ItemStack(Material.LINGERING_POTION); + PotionMeta potionMeta = (PotionMeta)(item.getItemMeta()); + PotionType type = PotionType.valueOf(part[1].toUpperCase()); + boolean isExtended = part[3].equalsIgnoreCase("EXTENDED") ? true : false; + boolean isUpgraded = (part[4].isEmpty() || part[4].equalsIgnoreCase("1")) ? false: true; + PotionData data = new PotionData(type, isExtended, isUpgraded); + potionMeta.setBasePotionData(data); + + item.setAmount(reqAmount); + return item; + + } else { + addon.getLogger().severe("Problem with " + s + " in challenges.yml!"); + } + + return null; + + } + +} diff --git a/src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminCommand.java b/src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminCommand.java index e46e54f..2dbdf2c 100644 --- a/src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminCommand.java +++ b/src/main/java/bskyblock/addon/challenges/commands/admin/ChallengesAdminCommand.java @@ -16,6 +16,7 @@ public class ChallengesAdminCommand extends CompositeCommand { this.addon = addon; // Set up create command new CreateChallenge(addon, this); + new SetIcon(addon, this); } @Override diff --git a/src/main/java/bskyblock/addon/challenges/commands/admin/SetIcon.java b/src/main/java/bskyblock/addon/challenges/commands/admin/SetIcon.java new file mode 100644 index 0000000..91c0b51 --- /dev/null +++ b/src/main/java/bskyblock/addon/challenges/commands/admin/SetIcon.java @@ -0,0 +1,63 @@ +/** + * + */ +package bskyblock.addon.challenges.commands.admin; + +import java.util.List; + +import org.bukkit.inventory.ItemStack; + +import bskyblock.addon.challenges.ChallengesAddon; +import bskyblock.addon.challenges.database.object.Challenges; +import us.tastybento.bskyblock.api.commands.CompositeCommand; +import us.tastybento.bskyblock.api.user.User; + +/** + * @author tastybento + * + */ +public class SetIcon extends CompositeCommand { + + private ChallengesAddon addon; + + /** + * @param parent + * @param label + * @param aliases + */ + public SetIcon(ChallengesAddon addon, CompositeCommand parent) { + super(parent, "seticon"); + this.addon = addon; + } + + /* (non-Javadoc) + * @see us.tastybento.bskyblock.api.commands.BSBCommand#setup() + */ + @Override + public void setup() { + setParameters("challenges.admin.seticon.parameters"); + setDescription("challenges.admin.seticon.description"); + } + + /* (non-Javadoc) + * @see us.tastybento.bskyblock.api.commands.BSBCommand#execute(us.tastybento.bskyblock.api.commands.User, java.util.List) + */ + @Override + public boolean execute(User user, List args) { + ItemStack icon = user.getInventory().getItemInMainHand(); + if (args.isEmpty() || icon == null) { + user.sendMessage("challenges.admin.seticon.description"); + return true; + } + Challenges challenge = addon.getChallengesManager().getChallenge(args.get(0)); + // Check if this challenge name exists + if (challenge == null) { + user.sendMessage("challenges.admin.seticon.error.no-such-challenge"); + return true; + } + challenge.setIcon(icon); + user.sendMessage("general.success"); + return true; + } + +} diff --git a/src/main/java/bskyblock/addon/challenges/database/object/Challenges.java b/src/main/java/bskyblock/addon/challenges/database/object/Challenges.java index 95602dd..5b7bdea 100644 --- a/src/main/java/bskyblock/addon/challenges/database/object/Challenges.java +++ b/src/main/java/bskyblock/addon/challenges/database/object/Challenges.java @@ -1,13 +1,16 @@ package bskyblock.addon.challenges.database.object; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import org.bukkit.ChatColor; import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.entity.EntityType; import org.bukkit.inventory.ItemStack; @@ -17,6 +20,42 @@ import us.tastybento.bskyblock.database.objects.DataObject; public class Challenges implements DataObject { + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((uniqueId == null) ? 0 : uniqueId.hashCode()); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Challenges)) { + return false; + } + Challenges other = (Challenges) obj; + if (uniqueId == null) { + if (other.uniqueId != null) { + return false; + } + } else if (!uniqueId.equals(other.uniqueId)) { + return false; + } + return true; + } + public enum ChallengeType { /** * This challenge only shows and icon in the GUI and doesn't do anything. @@ -33,101 +72,89 @@ public class Challenges implements DataObject { /** * Items or required entities have to be within x blocks of the player. */ - SURROUNDING + ISLAND } - - @ConfigComment("This is a map of the blocks required in a SURROUNDING challenge. Material, Integer") - private Map requiredBlocks; - - @ConfigComment("Challenge type can be ICON, INVENTORY, LEVEL or SURROUNDING.") - private ChallengeType challengeType; - + + // The order of the fields is the order shown in the YML files @ConfigComment("Whether this challenge is deployed or not") private boolean deployed; - - @ConfigComment("Description of the challenge. Will become the lore on the icon. Can include & color codes. String List.") - private List description = new ArrayList<>(); - - @ConfigComment("Experience point reward") - private int expReward; - - @ConfigComment("This challenge can be completed at any time") - private boolean freeChallenge; - + + // Description @ConfigComment("Name of the icon and challenge. May include color codes. Single line.") private String friendlyName = ""; - + @ConfigComment("Description of the challenge. Will become the lore on the icon. Can include & color codes. String List.") + private List description = new ArrayList<>(); @ConfigComment("The icon in the GUI for this challenge. ItemStack.") private ItemStack icon = new ItemStack(Material.PAPER); + @ConfigComment("Icon slot where this challenge should be placed. 0 to 49. A negative value means any slot") + private int slot = -1; + // Definition @ConfigComment("Challenge level. Default is Free") private String level = ChallengesManager.FREE; - - @ConfigComment("Maximum number of times the challenge can be repeated") - private int maxTimes = 1; - - @ConfigComment("Money reward") - private int moneyReward; - - @ConfigComment("If true, the challenge will disappear from the GUI when completed") - private boolean removeWhenCompleted; - - @ConfigComment("True if the challenge is repeatable") - private boolean repeatable; - - @ConfigComment("Repeat exp award") - private int repeatExpReward; - - @ConfigComment("Reward items for repeating the challenge. List of ItemStacks.") - private List repeatItemReward = new ArrayList<>(); - - @ConfigComment("Repeat money award") - private int repeatMoneyReward; - - @ConfigComment("Commands to run when challenge is repeated. String List.") - private List repeatRewardCommands = new ArrayList<>(); - - @ConfigComment("Description of the repeat rewards. If blank, it will be autogenerated.") - private String repeatRewardText = ""; - - @ConfigComment("Minimum amount of player experience") - private int reqExp; - - @ConfigComment("Require level for this challenge. Only works if Level Addon is being used.") - private long reqIslandlevel; - - @ConfigComment("Minimum amount of money required") - private int reqMoney; - + @ConfigComment("Challenge type can be ICON, INVENTORY, LEVEL or SURROUNDING.") + private ChallengeType challengeType = ChallengeType.INVENTORY; + @ConfigComment("List of environments where this challenge will occur: NETHER, NORMAL, THE_END. Leave blank for all.") + private List environment = new ArrayList<>(); @ConfigComment("The required permissions to see this challenge. String Set.") private Set reqPerms = new HashSet<>(); + @ConfigComment("The number of blocks around the player to search for items on an island") + private int searchRadius = 10; + @ConfigComment("If true, the challenge will disappear from the GUI when completed") + private boolean removeWhenCompleted; + @ConfigComment("Take the required items from the player") + private boolean takeItems = true; + @ConfigComment("Take the money from the player") + private boolean takeMoney = false; + // Requirements + @ConfigComment("This is a map of the blocks required in a SURROUNDING challenge. Material, Integer") + private Map requiredBlocks = new HashMap<>(); @ConfigComment("The items that must be in the inventory to complete the challenge. ItemStack List.") private List requiredItems = new ArrayList<>(); - @ConfigComment("Any entities that must be in the area for SURROUNDING type challenges. Map EntityType, Number") private Map requiredEntities = new HashMap<>(); + @ConfigComment("Required experience") + private int reqExp; + @ConfigComment("Required island level for this challenge. Only works if Level Addon is being used.") + private long reqIslandlevel; + @ConfigComment("Required money") + private int reqMoney; + // Rewards + @ConfigComment("List of items the player will receive first time. ItemStack List.") + private List itemReward = new ArrayList<>(); + @ConfigComment("If this is blank, the reward text will be auto-generated, otherwise this will be used.") + private String rewardText = ""; + @ConfigComment("Experience point reward") + private int expReward; + @ConfigComment("Money reward") + private int moneyReward; @ConfigComment("Commands to run when the player completes the challenge for the first time. String List") private List rewardCommands = new ArrayList<>(); - @ConfigComment("List of items the player will receive first time. ItemStack List.") - private List itemReward = new ArrayList<>(); + // Repeatable + @ConfigComment("True if the challenge is repeatable") + private boolean repeatable; + @ConfigComment("Maximum number of times the challenge can be repeated") + private int maxTimes = 1; + @ConfigComment("Repeat exp award") + private int repeatExpReward; + @ConfigComment("Reward items for repeating the challenge. List of ItemStacks.") + private List repeatItemReward = new ArrayList<>(); + @ConfigComment("Repeat money award") + private int repeatMoneyReward; + @ConfigComment("Commands to run when challenge is repeated. String List.") + private List repeatRewardCommands = new ArrayList<>(); + @ConfigComment("Description of the repeat rewards. If blank, it will be autogenerated.") + private String repeatRewardText = ""; + + - @ConfigComment("If this is blank, the reward text will be auto-generated, otherwise this will be used.") - private String rewardText = ""; - @ConfigComment("The number of blocks around the player to search for items on an island") - private int searchRadius = 10; - @ConfigComment("Inventory slot where this challenge should be placed. 0 to 49. A negative value means any slot") - private int slot = -1; - @ConfigComment("Take the required items from the player") - private boolean takeItems = true; - @ConfigComment("Take the money from the player") - private boolean takeMoney = false; @ConfigComment("Unique name of the challenge") private String uniqueId = ""; @@ -189,20 +216,6 @@ public class Challenges implements DataObject { this.expReward = expReward; } - /** - * @return the freeChallenge - */ - public boolean isFreeChallenge() { - return freeChallenge; - } - - /** - * @param freeChallenge the freeChallenge to set - */ - public void setFreeChallenge(boolean freeChallenge) { - this.freeChallenge = freeChallenge; - } - /** * @return the friendlyName */ @@ -570,6 +583,20 @@ public class Challenges implements DataObject { this.takeMoney = takeMoney; } + /** + * @return the environment + */ + public List getEnvironment() { + return environment; + } + + /** + * @param environment the environment to set + */ + public void setEnvironment(List environment) { + this.environment = environment; + } + /** * @return the uniqueId */ @@ -586,5 +613,14 @@ public class Challenges implements DataObject { this.uniqueId = uniqueId; } + /** + * Create a description from a single string + * Use | as new line, & as a color char + * @param string + */ + public void setDescription(String string) { + string = ChatColor.translateAlternateColorCodes('&', string); + this.description = Arrays.asList(string.split("\\|")); + } } diff --git a/src/main/java/bskyblock/addon/challenges/panel/ChallengesPanels.java b/src/main/java/bskyblock/addon/challenges/panel/ChallengesPanels.java index 3cc2c79..8d6db22 100644 --- a/src/main/java/bskyblock/addon/challenges/panel/ChallengesPanels.java +++ b/src/main/java/bskyblock/addon/challenges/panel/ChallengesPanels.java @@ -1,7 +1,7 @@ package bskyblock.addon.challenges.panel; import java.util.Arrays; -import java.util.List; +import java.util.Set; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -73,7 +73,7 @@ public class ChallengesPanels { private void addChallengeItems(PanelBuilder panelBuilder, User user, String level) { - List levelChallenges = manager.getChallenges(level); + Set levelChallenges = manager.getChallenges(level); // Do some checking if (DEBUG) addon.getLogger().info("DEBUG: Opening level " + level + " with " + levelChallenges.size() + " challenges"); diff --git a/src/main/java/bskyblock/addon/challenges/panel/TryToComplete.java b/src/main/java/bskyblock/addon/challenges/panel/TryToComplete.java index 51a0a4a..cd6837e 100644 --- a/src/main/java/bskyblock/addon/challenges/panel/TryToComplete.java +++ b/src/main/java/bskyblock/addon/challenges/panel/TryToComplete.java @@ -82,7 +82,7 @@ public class TryToComplete { */ private ChallengeResult checkIfCanCompleteChallenge(User user, ChallengesManager manager, Challenges challenge) { // Check if user has the - if (!challenge.isFreeChallenge() && !manager.isLevelAvailable(user, challenge.getLevel())) { + if (!challenge.getLevel().equals(ChallengesManager.FREE) && !manager.isLevelAvailable(user, challenge.getLevel())) { user.sendMessage("challenges.errors.challenge-level-not-available"); return new ChallengeResult(); } @@ -98,7 +98,7 @@ public class TryToComplete { // Check repeatability if (manager.isChallengeComplete(user, challenge.getUniqueId()) && (!challenge.isRepeatable() || challenge.getChallengeType().equals(ChallengeType.LEVEL) - || challenge.getChallengeType().equals(ChallengeType.SURROUNDING))) { + || challenge.getChallengeType().equals(ChallengeType.ISLAND))) { user.sendMessage("challenges.errors.cannot-repeat"); return new ChallengeResult(); } @@ -108,7 +108,7 @@ public class TryToComplete { return checkInventory(user, manager, challenge); case LEVEL: return checkLevel(user, manager, challenge); - case SURROUNDING: + case ISLAND: return checkSurrounding(user, manager, challenge); default: return new ChallengeResult(); diff --git a/src/test/java/bskyblock/addon/challenges/ChallengesAddonTest.java b/src/test/java/bskyblock/addon/challenges/ChallengesAddonTest.java index 9153f8a..38db86a 100644 --- a/src/test/java/bskyblock/addon/challenges/ChallengesAddonTest.java +++ b/src/test/java/bskyblock/addon/challenges/ChallengesAddonTest.java @@ -79,7 +79,7 @@ public class ChallengesAddonTest { Gson gson = new GsonBuilder().setPrettyPrinting().create(); Challenges challenges = new Challenges(); - challenges.setChallengeType(ChallengeType.SURROUNDING); + challenges.setChallengeType(ChallengeType.ISLAND); Map map = new HashMap<>(); map.put(Material.DIRT, 5); map.put(Material.ACACIA_FENCE_GATE, 3);