diff --git a/Changelog.txt b/Changelog.txt index e5728469d..7572ca8f1 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -8,7 +8,7 @@ Key: - Removal Version 1.4.08-dev - + Added new Skill - Alchemy! + + Added a new skill; Alchemy. Special thanks to EasyMFnE for creating this! + Added SecondaryAbilityType enum, and new SecondaryAbilityWeightedActivationCheckEvent, fired when a secondary ability checkes its activation chances + Added the possibility to gain experience when using Fishing "Shake" + Added config options to disable various sound effects diff --git a/README.md b/README.md index 935b14097..094581106 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,15 @@ mcMMO is currently developed by a team of individuals from all over the world. (https://github.com/t00thpick1) [![riking](https://1.gravatar.com/avatar/aca9f37e569ac3a63929920035a91ba4.png)] (https://github.com/riking) + +### Special thanks [![EasyMFnE](https://www.gravatar.com/avatar/99c9a1fa3bbf957791ceac7b45daadb0.png)] (https://github.com/EasyMFnE) +Added the Alchemy skill ## Compiling -mcMMO uses Maven 3 to manage dependancies, packaging, and shading of necessary classes; Maven 3 is required to compile mcMMO. +mcMMO uses Maven 3 to manage dependencies, packaging, and shading of necessary classes; Maven 3 is required to compile mcMMO. The typical command used to build mcMMO is: `mvn clean package install` diff --git a/src/main/java/com/gmail/nossr50/commands/skills/AlchemyCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/AlchemyCommand.java index c9ed5118e..e0fd61c4c 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/AlchemyCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/AlchemyCommand.java @@ -6,9 +6,11 @@ import java.util.List; import org.bukkit.entity.Player; import com.gmail.nossr50.config.AdvancedConfig; +import com.gmail.nossr50.datatypes.skills.SecondaryAbility; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.skills.alchemy.Alchemy.Tier; +import com.gmail.nossr50.skills.alchemy.AlchemyManager; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.player.UserManager; @@ -27,11 +29,12 @@ public class AlchemyCommand extends SkillCommand { super(SkillType.ALCHEMY); } - protected String[] calculateAbilityDisplayValues(Player player, float skillValue, boolean isLucky) { + protected String[] calculateAbilityDisplayValues(Player player, boolean isLucky) { + AlchemyManager alchemyManager = UserManager.getPlayer(player).getAlchemyManager(); String[] displayValues = new String[2]; - displayValues[0] = decimal.format(UserManager.getPlayer(player).getAlchemyManager().getBrewSpeed()) + "x"; - displayValues[1] = isLucky ? decimal.format(UserManager.getPlayer(player).getAlchemyManager().getBrewSpeedLucky()) + "x" : null; + displayValues[0] = decimal.format(alchemyManager.getBrewSpeed()) + "x"; + displayValues[1] = isLucky ? decimal.format(alchemyManager.getBrewSpeedLucky()) + "x" : null; return displayValues; } @@ -40,29 +43,30 @@ public class AlchemyCommand extends SkillCommand { protected void dataCalculations(Player player, float skillValue, boolean isLucky) { // CATALYSIS if (canCatalysis) { - String[] catalysisStrings = calculateAbilityDisplayValues(player, skillValue, isLucky); + String[] catalysisStrings = calculateAbilityDisplayValues(player, isLucky); brewSpeed = catalysisStrings[0]; brewSpeedLucky = catalysisStrings[1]; } // CONCOCTIONS if (canConcoctions) { - tier = UserManager.getPlayer(player).getAlchemyManager().getTier(); - ingredientCount = UserManager.getPlayer(player).getAlchemyManager().getIngredients().size(); - ingredientList = UserManager.getPlayer(player).getAlchemyManager().getIngredientList(); + AlchemyManager alchemyManager = UserManager.getPlayer(player).getAlchemyManager(); + tier = alchemyManager.getTier(); + ingredientCount = alchemyManager.getIngredients().size(); + ingredientList = alchemyManager.getIngredientList(); } } @Override protected void permissionsCheck(Player player) { - canCatalysis = Permissions.catalysis(player); - canConcoctions = Permissions.concoctions(player); + canCatalysis = Permissions.secondaryAbilityEnabled(player, SecondaryAbility.CATALYSIS); + canConcoctions = Permissions.secondaryAbilityEnabled(player, SecondaryAbility.CONCOCTIONS); } @Override protected List effectsDisplay() { List messages = new ArrayList(); - + if (canCatalysis) { messages.add(LocaleLoader.getString("Effects.Template", LocaleLoader.getString("Alchemy.Effect.0"), LocaleLoader.getString("Alchemy.Effect.1"))); } @@ -70,7 +74,7 @@ public class AlchemyCommand extends SkillCommand { if (canConcoctions) { messages.add(LocaleLoader.getString("Effects.Template", LocaleLoader.getString("Alchemy.Effect.2"), LocaleLoader.getString("Alchemy.Effect.3"))); } - + return messages; } diff --git a/src/main/java/com/gmail/nossr50/config/potion/PotionConfig.java b/src/main/java/com/gmail/nossr50/config/potion/PotionConfig.java index 3a12d6790..47023b2f2 100644 --- a/src/main/java/com/gmail/nossr50/config/potion/PotionConfig.java +++ b/src/main/java/com/gmail/nossr50/config/potion/PotionConfig.java @@ -41,7 +41,7 @@ public class PotionConfig extends ConfigLoader { return instance; } - + @Override protected void loadKeys() { loadConcoctions(); @@ -59,7 +59,7 @@ public class PotionConfig extends ConfigLoader { loadConcoctionsTier(concoctionsIngredientsTierSix, concoctionSection.getStringList("Tier_Six_Ingredients")); loadConcoctionsTier(concoctionsIngredientsTierSeven, concoctionSection.getStringList("Tier_Seven_Ingredients")); loadConcoctionsTier(concoctionsIngredientsTierEight, concoctionSection.getStringList("Tier_Eight_Ingredients")); - + concoctionsIngredientsTierTwo.addAll(concoctionsIngredientsTierOne); concoctionsIngredientsTierThree.addAll(concoctionsIngredientsTierTwo); concoctionsIngredientsTierFour.addAll(concoctionsIngredientsTierThree); @@ -73,7 +73,7 @@ public class PotionConfig extends ConfigLoader { if (ingredientStrings != null && ingredientStrings.size() > 0) { for (String ingredientString : ingredientStrings) { ItemStack ingredient = loadIngredient(ingredientString); - + if (ingredient != null) { ingredientList.add(ingredient); } @@ -91,7 +91,7 @@ public class PotionConfig extends ConfigLoader { for (String dataValue : potionSection.getKeys(false)) { AlchemyPotion potion = loadPotion(potionSection.getConfigurationSection(dataValue)); - + if (potion != null) { potionMap.put(potion.getDataValue(), potion); pass++; @@ -100,30 +100,31 @@ public class PotionConfig extends ConfigLoader { fail++; } } - - mcMMO.p.getLogger().info("Loaded " + pass + " Alchemy potions, skipped " + fail + "."); + + mcMMO.p.debug("Loaded " + pass + " Alchemy potions, skipped " + fail + "."); } /** * Parse a ConfigurationSection representing a AlchemyPotion. * Returns null if input cannot be parsed. - * + * * @param potion_section ConfigurationSection to be parsed. + * * @return Parsed AlchemyPotion. */ private AlchemyPotion loadPotion(ConfigurationSection potion_section) { try { short dataValue = Short.parseShort(potion_section.getName()); - + String name = potion_section.getString("Name"); - + List lore = new ArrayList(); if (potion_section.contains("Lore")) { for (String line : potion_section.getStringList("Lore")) { lore.add(line); } } - + List effects = new ArrayList(); if (potion_section.contains("Effects")) { for (String effect : potion_section.getStringList("Effects")) { @@ -167,22 +168,25 @@ public class PotionConfig extends ConfigLoader { * Parse a string representation of an ingredient. * Format: '<MATERIAL>[:data]' * Returns null if input cannot be parsed. - * + * * @param ingredient String representing an ingredient. + * * @return Parsed ingredient. */ private ItemStack loadIngredient(String ingredient) { if (ingredient == null || ingredient.isEmpty()) { return null; } + String[] parts = ingredient.split(":"); - + Material material = parts.length > 0 ? Material.getMaterial(parts[0]) : null; short data = parts.length > 1 ? Short.parseShort(parts[1]) : 0; - + if (material != null) { return new ItemStack(material, 1, data); } + return null; } } diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/SecondaryAbility.java b/src/main/java/com/gmail/nossr50/datatypes/skills/SecondaryAbility.java index 252cc4734..d1cc554c9 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/SecondaryAbility.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/SecondaryAbility.java @@ -6,6 +6,10 @@ public enum SecondaryAbility { GRACEFUL_ROLL, ROLL, + /* ALCHEMY */ + CATALYSIS, + CONCOCTIONS, + /* ARCHERY */ DAZE, RETRIEVE, diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java b/src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java index 279b80851..f16f43a58 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java @@ -36,7 +36,7 @@ import com.google.common.collect.ImmutableList; public enum SkillType { ACROBATICS(AcrobaticsManager.class, Color.WHITE, ImmutableList.of(SecondaryAbility.DODGE, SecondaryAbility.GRACEFUL_ROLL, SecondaryAbility.ROLL)), - ALCHEMY(AlchemyManager.class, Color.FUCHSIA, null), + ALCHEMY(AlchemyManager.class, Color.FUCHSIA, ImmutableList.of(SecondaryAbility.CATALYSIS, SecondaryAbility.CONCOCTIONS)), ARCHERY(ArcheryManager.class, Color.MAROON, ImmutableList.of(SecondaryAbility.DAZE, SecondaryAbility.RETRIEVE, SecondaryAbility.SKILL_SHOT)), AXES(AxesManager.class, Color.AQUA, AbilityType.SKULL_SPLITTER, ToolType.AXE, ImmutableList.of(SecondaryAbility.ARMOR_IMPACT, SecondaryAbility.AXE_MASTERY, SecondaryAbility.CRITICAL_HIT, SecondaryAbility.GREATER_IMPACT)), EXCAVATION(ExcavationManager.class, Color.fromRGB(139, 69, 19), AbilityType.GIGA_DRILL_BREAKER, ToolType.SHOVEL, ImmutableList.of(SecondaryAbility.EXCAVATION_TREASURE_HUNTER)), diff --git a/src/main/java/com/gmail/nossr50/events/skills/alchemy/McMMOPlayerBrewEvent.java b/src/main/java/com/gmail/nossr50/events/skills/alchemy/McMMOPlayerBrewEvent.java index e8c890e24..983a11a82 100644 --- a/src/main/java/com/gmail/nossr50/events/skills/alchemy/McMMOPlayerBrewEvent.java +++ b/src/main/java/com/gmail/nossr50/events/skills/alchemy/McMMOPlayerBrewEvent.java @@ -10,7 +10,7 @@ import com.gmail.nossr50.events.skills.McMMOPlayerSkillEvent; public class McMMOPlayerBrewEvent extends McMMOPlayerSkillEvent implements Cancellable { private Block brewingStand; - + private boolean cancelled; public McMMOPlayerBrewEvent(Player player, Block brewingStand) { diff --git a/src/main/java/com/gmail/nossr50/events/skills/alchemy/McMMOPlayerCatalysisEvent.java b/src/main/java/com/gmail/nossr50/events/skills/alchemy/McMMOPlayerCatalysisEvent.java index c7872baa8..48c2e27c1 100644 --- a/src/main/java/com/gmail/nossr50/events/skills/alchemy/McMMOPlayerCatalysisEvent.java +++ b/src/main/java/com/gmail/nossr50/events/skills/alchemy/McMMOPlayerCatalysisEvent.java @@ -8,7 +8,7 @@ import com.gmail.nossr50.events.skills.McMMOPlayerSkillEvent; public class McMMOPlayerCatalysisEvent extends McMMOPlayerSkillEvent implements Cancellable { private double speed; - + private boolean cancelled; public McMMOPlayerCatalysisEvent(Player player, double speed) { diff --git a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java index 2e6113173..8d1b27b79 100644 --- a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java @@ -598,20 +598,21 @@ public class EntityListener implements Listener { /** * Handle PotionSplash events in order to fix broken Splash Potion of Saturation. - * + * * @param event The event to process */ @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onPotionSplash(PotionSplashEvent event) { for (PotionEffect effect : ((PotionMeta) event.getEntity().getItem().getItemMeta()).getCustomEffects()) { - // (effect.getType() == PotionEffectType.SATURATION) is seemingly broken, so we use deprecated method for now. - if (effect.getType().getId() == 23) { - for (LivingEntity entity : event.getAffectedEntities()) { - int duration = (int) (effect.getDuration() * event.getIntensity(entity)); - entity.addPotionEffect(new PotionEffect(effect.getType(), duration, effect.getAmplifier(), effect.isAmbient())); - } + // (effect.getType() != PotionEffectType.SATURATION) is seemingly broken, so we use deprecated method for now. + if (effect.getType().getId() != 23) { + return; + } + + for (LivingEntity entity : event.getAffectedEntities()) { + int duration = (int) (effect.getDuration() * event.getIntensity(entity)); + entity.addPotionEffect(new PotionEffect(effect.getType(), duration, effect.getAmplifier(), effect.isAmbient())); } - return; } } } diff --git a/src/main/java/com/gmail/nossr50/listeners/InventoryListener.java b/src/main/java/com/gmail/nossr50/listeners/InventoryListener.java index 24a1a010e..7e4ed79a9 100644 --- a/src/main/java/com/gmail/nossr50/listeners/InventoryListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/InventoryListener.java @@ -136,8 +136,8 @@ public class InventoryListener implements Listener { event.setExpToDrop(UserManager.getPlayer(player).getSmeltingManager().vanillaXPBoost(event.getExpToDrop())); } - @EventHandler(ignoreCancelled = true) - public void onAlchemyClickEvent(InventoryClickEvent event) { + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onInventoryClickEventNormal(InventoryClickEvent event) { if (event.getInventory().getType() != InventoryType.BREWING || !(event.getInventory().getHolder() instanceof BrewingStand)) { return; } @@ -149,8 +149,8 @@ public class InventoryListener implements Listener { AlchemyPotionBrewer.handleInventoryClick(event); } - @EventHandler(ignoreCancelled = true) - public void onAlchemyDragEvent(InventoryDragEvent event) { + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onInventoryDragEvent(InventoryDragEvent event) { if (event.getInventory().getType() != InventoryType.BREWING || !(event.getInventory().getHolder() instanceof BrewingStand)) { return; } @@ -162,13 +162,13 @@ public class InventoryListener implements Listener { AlchemyPotionBrewer.handleInventoryDrag(event); } - @EventHandler(ignoreCancelled = true) - public void onAlchemyMoveItemEvent(InventoryMoveItemEvent event) { + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onInventoryMoveItemEvent(InventoryMoveItemEvent event) { if (event.getDestination().getType() != InventoryType.BREWING || !(event.getDestination().getHolder() instanceof BrewingStand)) { return; } - if (Config.getInstance().getPreventHopperTransfer() && event.getItem() != null && event.getItem().getType() != Material.POTION) { + if (Config.getInstance().getPreventHopperTransfer() && event.getItem() != null && event.getItem().getType() != Material.POTION) { event.setCancelled(true); return; } diff --git a/src/main/java/com/gmail/nossr50/runnables/skills/AlchemyBrewTask.java b/src/main/java/com/gmail/nossr50/runnables/skills/AlchemyBrewTask.java index ff77b334b..0619e42b4 100644 --- a/src/main/java/com/gmail/nossr50/runnables/skills/AlchemyBrewTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/skills/AlchemyBrewTask.java @@ -6,6 +6,7 @@ import org.bukkit.block.BrewingStand; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; +import com.gmail.nossr50.datatypes.skills.SecondaryAbility; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.events.skills.alchemy.McMMOPlayerBrewEvent; @@ -32,7 +33,7 @@ public class AlchemyBrewTask extends BukkitRunnable { brewSpeed = DEFAULT_BREW_SPEED; brewTimer = DEFAULT_BREW_TICKS; - if (player != null && !Misc.isNPCEntity(player) && Permissions.catalysis(player)) { + if (player != null && !Misc.isNPCEntity(player) && Permissions.secondaryAbilityEnabled(player, SecondaryAbility.CATALYSIS)) { double catalysis = UserManager.getPlayer(player).getAlchemyManager().getBrewSpeed(); if (Permissions.lucky(player, SkillType.ALCHEMY)) { diff --git a/src/main/java/com/gmail/nossr50/skills/alchemy/Alchemy.java b/src/main/java/com/gmail/nossr50/skills/alchemy/Alchemy.java index 676ec4e6b..4f4aec379 100644 --- a/src/main/java/com/gmail/nossr50/skills/alchemy/Alchemy.java +++ b/src/main/java/com/gmail/nossr50/skills/alchemy/Alchemy.java @@ -2,13 +2,11 @@ package com.gmail.nossr50.skills.alchemy; import java.util.HashMap; import java.util.Map; -import java.util.Map.Entry; import org.bukkit.block.Block; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.AdvancedConfig; -import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.runnables.skills.AlchemyBrewTask; public final class Alchemy { @@ -31,7 +29,7 @@ public final class Alchemy { public int toNumerical() { return numerical; } - + public static Tier fromNumerical(int numerical) { for (Tier tier : Tier.values()) { if (tier.toNumerical() == numerical) { @@ -45,22 +43,21 @@ public final class Alchemy { return AdvancedConfig.getInstance().getConcoctionsTierLevel(this); } } - + public static int catalysisUnlockLevel = AdvancedConfig.getInstance().getCatalysisUnlockLevel(); public static int catalysisMaxBonusLevel = AdvancedConfig.getInstance().getCatalysisMaxBonusLevel(); public static double catalysisMinSpeed = AdvancedConfig.getInstance().getCatalysisMinSpeed(); public static double catalysisMaxSpeed = AdvancedConfig.getInstance().getCatalysisMaxSpeed(); - public static double potionXp = ExperienceConfig.getInstance().getPotionXP(); - public static Map brewingStandMap = new HashMap(); - private Alchemy() {}; - + private Alchemy() {} + /** * Calculate base brewing speed, given a skill level and ignoring all perks. - * + * * @param skillLevel Skill level used for calculation. + * * @return Base brewing speed for the level. */ public static double calculateBrewSpeed(int skillLevel) { @@ -70,14 +67,14 @@ public final class Alchemy { return Math.min(catalysisMaxSpeed, catalysisMinSpeed + (catalysisMaxSpeed - catalysisMinSpeed) * (skillLevel - catalysisUnlockLevel) / (catalysisMaxBonusLevel - catalysisUnlockLevel)); } - + /** * Finish all active brews. Used upon Disable to prevent vanilla potions from being brewed upon next Enable. */ public static void finishAllBrews() { - mcMMO.p.getLogger().info("Completing " + brewingStandMap.size() + " unfinished Alchemy brews."); - for (Entry entry : brewingStandMap.entrySet()) { - entry.getValue().finishImmediately(); + mcMMO.p.debug("Completing " + brewingStandMap.size() + " unfinished Alchemy brews."); + for (AlchemyBrewTask alchemyBrewTask : brewingStandMap.values()) { + alchemyBrewTask.finishImmediately(); } } } diff --git a/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyManager.java b/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyManager.java index abacfc923..ef37975ac 100644 --- a/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyManager.java +++ b/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyManager.java @@ -7,6 +7,7 @@ import org.bukkit.inventory.ItemStack; import com.gmail.nossr50.config.experience.ExperienceConfig; import com.gmail.nossr50.config.potion.PotionConfig; import com.gmail.nossr50.datatypes.player.McMMOPlayer; +import com.gmail.nossr50.datatypes.skills.SecondaryAbility; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.skills.SkillManager; import com.gmail.nossr50.util.Permissions; @@ -20,7 +21,11 @@ public class AlchemyManager extends SkillManager { } public boolean canCatalysis() { - return Permissions.catalysis(getPlayer()); + return Permissions.secondaryAbilityEnabled(getPlayer(), SecondaryAbility.CATALYSIS); + } + + public boolean canConcoctions() { + return Permissions.secondaryAbilityEnabled(getPlayer(), SecondaryAbility.CONCOCTIONS); } public boolean canUseIngredient(ItemStack item) { @@ -66,21 +71,28 @@ public class AlchemyManager extends SkillManager { public String getIngredientList() { String list = ""; for (ItemStack ingredient : getIngredients()) { - list += ", " + StringUtils.getPrettyItemString(ingredient.getType()) + (ingredient.getDurability() != 0 ? ":" + ingredient.getDurability() : ""); + String string = StringUtils.getPrettyItemString(ingredient.getType()) + (ingredient.getDurability() != 0 ? ":" + ingredient.getDurability() : ""); + if (string.equals("LONG_GRASS:2")) { + string = "Fern"; + } + else if (string.equals("RAW_FISH:3")) { + string = "Pufferfish"; + } + + list += ", " + string; } return list.substring(2); } - public double getBrewSpeed() { + public double getBrewSpeed() { return Alchemy.calculateBrewSpeed(getSkillLevel()); } - + public double getBrewSpeedLucky() { return LUCKY_MODIFIER * Alchemy.calculateBrewSpeed(getSkillLevel()); } - + public void handlePotionBrewSuccesses(int amount) { applyXpGain((float) (ExperienceConfig.getInstance().getPotionXP() * amount)); } - } diff --git a/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyPotionBrewer.java b/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyPotionBrewer.java index 71654ddff..33c07d580 100644 --- a/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyPotionBrewer.java +++ b/src/main/java/com/gmail/nossr50/skills/alchemy/AlchemyPotionBrewer.java @@ -21,36 +21,40 @@ import org.bukkit.inventory.ItemStack; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.potion.PotionConfig; import com.gmail.nossr50.datatypes.AlchemyPotion; +import com.gmail.nossr50.datatypes.skills.SecondaryAbility; import com.gmail.nossr50.runnables.PlayerUpdateInventoryTask; import com.gmail.nossr50.runnables.skills.AlchemyBrewCheckTask; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.player.UserManager; public final class AlchemyPotionBrewer { - private final static int[] BOTTLE_SLOTS = new int[] { 0, 1, 2 }; + private final static int[] BOTTLE_SLOTS = new int[]{0, 1, 2}; private final static int INGREDIENT_SLOT = 3; public static boolean isValidBrew(Player player, ItemStack[] contents) { - if (isValidIngredient(player, contents[INGREDIENT_SLOT])) { - for (int bottle : BOTTLE_SLOTS) { - if (contents[bottle] != null && contents[bottle].getType() == Material.POTION) { - AlchemyPotion potion = PotionConfig.getInstance().potionMap.get(contents[bottle].getDurability()); - - if (getChildPotion(potion, contents[INGREDIENT_SLOT]) != null) { - return true; - } + if (!isValidIngredient(player, contents[INGREDIENT_SLOT])) { + return false; + } + + for (int bottle : BOTTLE_SLOTS) { + if (contents[bottle] != null && contents[bottle].getType() == Material.POTION) { + AlchemyPotion potion = PotionConfig.getInstance().potionMap.get(contents[bottle].getDurability()); + + if (getChildPotion(potion, contents[INGREDIENT_SLOT]) != null) { + return true; } } } - + return false; + } private static AlchemyPotion getChildPotion(AlchemyPotion potion, ItemStack ingredient) { if (potion != null && potion.getChildDataValue(ingredient) != -1) { return PotionConfig.getInstance().potionMap.get(potion.getChildDataValue(ingredient)); } - + return null; } @@ -60,19 +64,19 @@ public final class AlchemyPotionBrewer { private static boolean removeIngredient(BrewerInventory inventory, Player player) { ItemStack ingredient = inventory.getIngredient(); - + if (isEmpty(ingredient) || !isValidIngredient(player, ingredient)) { return false; } else if (ingredient.getAmount() <= 1) { inventory.setItem(INGREDIENT_SLOT, null); - + return true; } else { ingredient.setAmount(ingredient.getAmount() - 1); inventory.setItem(INGREDIENT_SLOT, ingredient); - + return true; } } @@ -81,21 +85,21 @@ public final class AlchemyPotionBrewer { if (isEmpty(item)) { return false; } - + for (ItemStack ingredient : getValidIngredients(player)) { if (item.isSimilar(ingredient)) { return true; } } - + return false; } private static List getValidIngredients(Player player) { - if (player == null || !Permissions.concoctions(player)) { + if (player == null || !Permissions.secondaryAbilityEnabled(player, SecondaryAbility.CONCOCTIONS)) { return PotionConfig.getInstance().concoctionsIngredientsTierOne; } - + switch (UserManager.getPlayer(player).getAlchemyManager().getTier()) { case 5: return PotionConfig.getInstance().concoctionsIngredientsTierFive; @@ -114,38 +118,38 @@ public final class AlchemyPotionBrewer { if (!(brewingStand.getState() instanceof BrewingStand)) { return; } - + BrewerInventory inventory = ((BrewingStand) brewingStand.getState()).getInventory(); ItemStack ingredient = inventory.getIngredient() == null ? null : inventory.getIngredient().clone(); - - if (removeIngredient(inventory, player)) { - for (int bottle : BOTTLE_SLOTS) { - if (!isEmpty(inventory.getItem(bottle)) && PotionConfig.getInstance().potionMap.containsKey(inventory.getItem(bottle).getDurability())) { - AlchemyPotion input = PotionConfig.getInstance().potionMap.get(inventory.getItem(bottle).getDurability()); - AlchemyPotion output = PotionConfig.getInstance().potionMap.get(input.getChildDataValue(ingredient)); - - if (output != null) { - inventory.setItem(bottle, output.toItemStack(inventory.getItem(bottle).getAmount()).clone()); - - if (player != null) { - UserManager.getPlayer(player).getAlchemyManager().handlePotionBrewSuccesses(1); - } + + if (!removeIngredient(inventory, player)) { + return; + } + + for (int bottle : BOTTLE_SLOTS) { + if (!isEmpty(inventory.getItem(bottle)) && PotionConfig.getInstance().potionMap.containsKey(inventory.getItem(bottle).getDurability())) { + AlchemyPotion input = PotionConfig.getInstance().potionMap.get(inventory.getItem(bottle).getDurability()); + AlchemyPotion output = PotionConfig.getInstance().potionMap.get(input.getChildDataValue(ingredient)); + + if (output != null) { + inventory.setItem(bottle, output.toItemStack(inventory.getItem(bottle).getAmount()).clone()); + + if (player != null) { + UserManager.getPlayer(player).getAlchemyManager().handlePotionBrewSuccesses(1); } } } - - if (!forced) { - scheduleUpdate(inventory); - } - - return; + } + + if (!forced) { + scheduleUpdate(inventory); } } private static boolean transferOneItem(InventoryView view, int fromSlot, int toSlot) { ItemStack from = view.getItem(fromSlot).clone(); ItemStack to = view.getItem(toSlot).clone(); - + if (isEmpty(from)) { return false; } @@ -160,14 +164,14 @@ public final class AlchemyPotionBrewer { else { to.setAmount(to.getAmount() + 1); } - + from.setAmount(from.getAmount() - 1); view.setItem(toSlot, isEmpty(to) ? null : to); view.setItem(fromSlot, isEmpty(from) ? null : from); - + return true; } - + return false; } @@ -181,29 +185,29 @@ public final class AlchemyPotionBrewer { else if (isEmpty(view.getItem(toSlot))) { view.setItem(toSlot, view.getItem(fromSlot).clone()); view.setItem(fromSlot, null); - + return true; } else if (view.getItem(fromSlot).isSimilar(view.getItem(toSlot))) { if (view.getItem(fromSlot).getAmount() + view.getItem(toSlot).getAmount() > view.getItem(toSlot).getType().getMaxStackSize()) { int left = view.getItem(fromSlot).getAmount() + view.getItem(toSlot).getAmount() - view.getItem(toSlot).getType().getMaxStackSize(); - + ItemStack to = new ItemStack(view.getItem(toSlot)); to.setAmount(to.getType().getMaxStackSize()); view.setItem(toSlot, to); - + ItemStack from = new ItemStack(view.getItem(fromSlot)); from.setAmount(left); view.setItem(fromSlot, from); - + return true; } - + ItemStack to = new ItemStack(view.getItem(toSlot)); to.setAmount(view.getItem(fromSlot).getAmount() + view.getItem(toSlot).getAmount()); view.setItem(fromSlot, null); view.setItem(toSlot, to); - + return true; } return false; @@ -214,12 +218,13 @@ public final class AlchemyPotionBrewer { } private static void scheduleUpdate(Inventory inventory) { - for (HumanEntity he : inventory.getViewers()) { - if (he instanceof Player) { - scheduleUpdate((Player) he); + for (HumanEntity humanEntity : inventory.getViewers()) { + if (humanEntity instanceof Player) { + scheduleUpdate((Player) humanEntity); } } } + private static void scheduleUpdate(Player player) { Bukkit.getScheduler().scheduleSyncDelayedTask(mcMMO.p, new PlayerUpdateInventoryTask(player)); } @@ -227,19 +232,19 @@ public final class AlchemyPotionBrewer { public static void handleInventoryClick(InventoryClickEvent event) { Player player = event.getWhoClicked() instanceof Player ? (Player) event.getWhoClicked() : null; BrewingStand brewingStand = (BrewingStand) event.getInventory().getHolder(); - + ItemStack cursor = event.getCursor(); ItemStack clicked = event.getCurrentItem(); - + if (clicked != null && clicked.getType() == Material.POTION) { scheduleCheck(player, brewingStand); - + return; } if (event.isShiftClick()) { if (event.getSlotType() == SlotType.FUEL) { scheduleCheck(player, brewingStand); - + return; } else if (event.getSlotType() == SlotType.CONTAINER || event.getSlotType() == SlotType.QUICKBAR) { @@ -250,12 +255,12 @@ public final class AlchemyPotionBrewer { else if (event.isRightClick()) { transferOneItem(event.getView(), event.getRawSlot(), INGREDIENT_SLOT); } - + event.setCancelled(true); - + scheduleUpdate(brewingStand.getInventory()); scheduleCheck(player, brewingStand); - + return; } } @@ -266,37 +271,37 @@ public final class AlchemyPotionBrewer { } else if (isEmpty(cursor)) { scheduleCheck(player, brewingStand); - + return; } else if (isEmpty(clicked)) { if (isValidIngredient(player, event.getCursor())) { if (event.getClick() == ClickType.LEFT || (event.getClick() == ClickType.RIGHT && event.getCursor().getAmount() == 1)) { event.setCancelled(true); - + event.setCurrentItem(event.getCursor().clone()); event.setCursor(null); - + scheduleUpdate(brewingStand.getInventory()); scheduleCheck(player, brewingStand); - + return; } else if (event.getClick() == ClickType.RIGHT) { event.setCancelled(true); - + ItemStack one = event.getCursor().clone(); one.setAmount(1); - + ItemStack rest = event.getCursor().clone(); rest.setAmount(event.getCursor().getAmount() - 1); - + event.setCurrentItem(one); event.setCursor(rest); - + scheduleUpdate(brewingStand.getInventory()); scheduleCheck(player, brewingStand); - + return; } } @@ -308,41 +313,44 @@ public final class AlchemyPotionBrewer { public static void handleInventoryDrag(InventoryDragEvent event) { Player player = event.getWhoClicked() instanceof Player ? (Player) event.getWhoClicked() : null; BrewingStand brewingStand = (BrewingStand) event.getInventory().getHolder(); - + ItemStack cursor = event.getCursor(); ItemStack ingredient = brewingStand.getInventory().getIngredient(); - - if (event.getInventorySlots().contains(INGREDIENT_SLOT)) { - if (isEmpty(ingredient) || ingredient.isSimilar(cursor)) { - if (isValidIngredient(player, cursor)) { - // Not handled: dragging custom ingredients over ingredient slot (does not trigger any event) - scheduleCheck(player, brewingStand); - - return; - } - else { - event.setCancelled(true); - - scheduleUpdate(brewingStand.getInventory()); - - return; - } + + if (!event.getInventorySlots().contains(INGREDIENT_SLOT)) { + return; + } + + if (isEmpty(ingredient) || ingredient.isSimilar(cursor)) { + if (isValidIngredient(player, cursor)) { + // Not handled: dragging custom ingredients over ingredient slot (does not trigger any event) + scheduleCheck(player, brewingStand); + + return; + } + else { + event.setCancelled(true); + + scheduleUpdate(brewingStand.getInventory()); + + return; } } + } public static void handleInventoryMoveItem(InventoryMoveItemEvent event) { Player player = null; BrewingStand brewingStand = (BrewingStand) event.getDestination().getHolder(); - + if (isValidIngredient(player, event.getItem())) { scheduleCheck(player, brewingStand); - + return; } else { event.setCancelled(true); - + return; } } diff --git a/src/main/resources/locale/locale_en_US.properties b/src/main/resources/locale/locale_en_US.properties index 66319ffe7..577ae5bd0 100644 --- a/src/main/resources/locale/locale_en_US.properties +++ b/src/main/resources/locale/locale_en_US.properties @@ -40,7 +40,7 @@ Alchemy.Effect.3=Brew potions with more ingredients Alchemy.Listener=Alchemy: Alchemy.Ability.Locked.0=LOCKED UNTIL {0}+ SKILL (CATALYSIS) Alchemy.Catalysis.Speed=[[RED]]Brewing Speed: [[YELLOW]]{0} -Alchemy.Concoctions.Rank=[[RED]]Concoctions Rank: [[YELLOW]]{0} +Alchemy.Concoctions.Rank=[[RED]]Concoctions Rank: [[YELLOW]]{0}/{1} Alchemy.Concoctions.Ingredients=[[RED]]Ingredients [[[YELLOW]]{0}[[RED]]]: [[YELLOW]]{1} Alchemy.SkillName=ALCHEMY Alchemy.Skillup=[[YELLOW]]Alchemy skill increased by {0}. Total ({1}) @@ -421,7 +421,7 @@ Combat.TouchedFuzzy=[[DARK_RED]]Touched Fuzzy. Felt Dizzy. #COMMANDS ##generic -mcMMO.Description=[[DARK_AQUA]]About the [[YELLOW]]mcMMO[[DARK_AQUA]] Project:,[[GOLD]]mcMMO is an [[RED]]open source[[GOLD]] RPG mod created in February 2011,[[GOLD]]by [[BLUE]]nossr50[[GOLD]]. The goal is to provide a quality RPG experience.,[[DARK_AQUA]]Tips:,[[GOLD]] - [[GREEN]]Use [[RED]]/mcmmo help[[GREEN]] to see commands,[[GOLD]] - [[GREEN]]Type [[RED]]/SKILLNAME[[GREEN]] to see detailed skill info,[[DARK_AQUA]]Developers:,[[GOLD]] - [[GREEN]]nossr50 [[BLUE]](Founder),[[GOLD]] - [[GREEN]]GJ [[BLUE]](Project Lead),[[GOLD]] - [[GREEN]]NuclearW [[BLUE]](Developer),[[GOLD]] - [[GREEN]]bm01 [[BLUE]](Developer),[[GOLD]] - [[GREEN]]TfT_02 [[BLUE]](Developer),[[GOLD]] - [[GREEN]]Glitchfinder [[BLUE]](Developer),[[GOLD]] - [[GREEN]]t00thpick1 [[BLUE]](Developer),[[GOLD]] - [[GREEN]]EasyMFnE [[BLUE]](Developer),[[DARK_AQUA]]Useful Links:,[[GOLD]] - [[GREEN]]https://github.com/mcMMO-Dev/mcMMO/issues[[GOLD]] Bug Reporting,[[GOLD]] - [[GREEN]]#mcmmo @ irc.esper.net[[GOLD]] IRC Chat, +mcMMO.Description=[[DARK_AQUA]]About the [[YELLOW]]mcMMO[[DARK_AQUA]] Project:,[[GOLD]]mcMMO is an [[RED]]open source[[GOLD]] RPG mod created in February 2011,[[GOLD]]by [[BLUE]]nossr50[[GOLD]]. The goal is to provide a quality RPG experience.,[[DARK_AQUA]]Tips:,[[GOLD]] - [[GREEN]]Use [[RED]]/mcmmo help[[GREEN]] to see commands,[[GOLD]] - [[GREEN]]Type [[RED]]/SKILLNAME[[GREEN]] to see detailed skill info,[[DARK_AQUA]]Developers:,[[GOLD]] - [[GREEN]]nossr50 [[BLUE]](Founder),[[GOLD]] - [[GREEN]]GJ [[BLUE]](Project Lead),[[GOLD]] - [[GREEN]]NuclearW [[BLUE]](Developer),[[GOLD]] - [[GREEN]]bm01 [[BLUE]](Developer),[[GOLD]] - [[GREEN]]TfT_02 [[BLUE]](Developer),[[GOLD]] - [[GREEN]]Glitchfinder [[BLUE]](Developer),[[GOLD]] - [[GREEN]]t00thpick1 [[BLUE]](Developer),[[DARK_AQUA]]Useful Links:,[[GOLD]] - [[GREEN]]https://github.com/mcMMO-Dev/mcMMO/issues[[GOLD]] Bug Reporting,[[GOLD]] - [[GREEN]]#mcmmo @ irc.esper.net[[GOLD]] IRC Chat, Commands.addlevels.AwardAll.1=[[GREEN]]You were awarded {0} levels in all skills! Commands.addlevels.AwardAll.2=[[RED]]All skills have been modified for {0}. Commands.addlevels.AwardSkill.1=[[GREEN]]You were awarded {0} levels in {1}! @@ -669,6 +669,15 @@ Guides.Acrobatics.Section.0=[[DARK_AQUA]]About Acrobatics:\n[[YELLOW]]Acrobatics Guides.Acrobatics.Section.1=[[DARK_AQUA]]How does Rolling work?\n[[YELLOW]]You have a passive chance when you take fall damage\n[[YELLOW]]to negate the damage done. You can hold the sneak button to\n[[YELLOW]]double your chances during the fall.\n[[YELLOW]]This triggers a Graceful Roll instead of a standard one.\n[[YELLOW]]Graceful Rolls are like regular rolls but are twice as likely to\n[[YELLOW]]occur and provide more damage safety than regular rolls.\n[[YELLOW]]Rolling chance is tied to your skill level Guides.Acrobatics.Section.2=[[DARK_AQUA]]How does Dodge work?\n[[YELLOW]]Dodge is a passive chance when you are\n[[YELLOW]]injured in combat to halve the damage taken.\n[[YELLOW]]It is tied to your skill level. +##Alchemy +Guides.Alchemy.Section.0=[[DARK_AQUA]]About Alchemy:\n[[YELLOW]]Alchemy is about brewing potions.\n[[YELLOW]]It provides a speed increase in the potion brew time, as well\n[[YELLOW]]as the addition of new (previously) unobtainable potions.\n\n\n[[DARK_AQUA]]XP GAIN:\n[[YELLOW]]To gain XP in this skill you need to brew potions. +Guides.Alchemy.Section.1=[[DARK_AQUA]]How does Catalysis work?\n[[YELLOW]]Catalysis speeds of the brewing process, with a\n[[YELLOW]]max speed of 4x at level 1000.\n[[YELLOW]]This ability is unlocked at level 100 by default. +Guides.Alchemy.Section.2=[[DARK_AQUA]]How does Concoctions work?\n[[YELLOW]]Concoctions allows brewing of more potions with custom ingredients.\n[[YELLOW]]Which special ingredients are unlocked is determined\n[[YELLOW]]by your Rank. There are 8 ranks to unlock. +Guides.Alchemy.Section.3=[[DARK_AQUA]]Concotions tier 1 ingredients:\n[[YELLOW]]Blaze Powder, Fermented Spider Eye, Ghast Tear, Redstone,\n[[YELLOW]]Glowstone Dust, Sugar, Glistering Melon, Golden Carrot,\n[[YELLOW]]Magma Cream, Nether Wart, Spider Eye, Suplhur, Water Lily,\n[[YELLOW]]Pufferfish\n[[YELLOW]](Vanilla Potions) +Guides.Alchemy.Section.4=[[DARK_AQUA]]Concotions tier 2 ingredients:\n[[YELLOW]]Carrot (Potion of Haste)\n[[YELLOW]]Slimeball (Potion of Dullness)\n\n[[DARK_AQUA]]Concotions tier 3 ingredients:\n[[YELLOW]]Quartz (Potion of Absorption)\n[[YELLOW]]Red Mushroom (Potion of Leaping) +Guides.Alchemy.Section.5=[[DARK_AQUA]]Concotions tier 4 ingredients:\n[[YELLOW]]Apple (Potion of Health Boost)\n[[YELLOW]]Rotten Flesh (Potion of Hunger)\n\n[[DARK_AQUA]]Concotions tier 5 ingredients:\n[[YELLOW]]Brown Mushroom (Potion of Nausea)\n[[YELLOW]]Ink Sack (Potion of Blindness) +Guides.Alchemy.Section.6=[[DARK_AQUA]]Concotions tier 6 ingredients:\n[[YELLOW]]Fern (Potion of Saturation)\n\n[[DARK_AQUA]]Concotions tier 7 ingredients:\n[[YELLOW]]Poisonous Potato (Potion of Decay)\n\n[[DARK_AQUA]]Concotions tier 8 ingredients:\n[[YELLOW]]Regular Golden Apple (Potion of Resistance) + ##Archery Guides.Archery.Section.0=[[DARK_AQUA]]About Archery:\n[[YELLOW]]Archery is about shooting with your bow and arrow.\n[[YELLOW]]It provides various combat bonuses, such as a damage boost\n[[YELLOW]]that scales with your level and the ability to daze your\n[[YELLOW]]opponents in PvP. In addition to this, you can retrieve\n[[YELLOW]]some of your spent arrows from the corpses of your foes.\n\n\n[[DARK_AQUA]]XP GAIN:\n[[YELLOW]]To gain XP in this skill you need to shoot mobs or\n[[YELLOW]]other players. Guides.Archery.Section.1=[[DARK_AQUA]]How does Skill Shot work?\n[[YELLOW]]Skill Shot provides additional damage to your shots.\n[[YELLOW]]The bonus damage from Skill Shot increases as you\n[[YELLOW]]level in Archery.\n[[YELLOW]]With the default settings, your archery damage increases 10%\n[[YELLOW]]every 50 levels, to a maximum of 200% bonus damage. diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index a43eece7c..d7c0b3579 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -11,7 +11,7 @@ description: > in order to evaluate and balance the mechanics of mcMMO in every update. author: nossr50 -authors: [GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking, EasyMFnE] +authors: [GJ, NuclearW, bm01, Glitchfinder, TfT_02, t00thpick1, Riking] website: http://dev.bukkit.org/server-mods/mcmmo/ main: com.gmail.nossr50.mcMMO diff --git a/src/main/resources/potions.yml b/src/main/resources/potions.yml index c99d49e26..346282b20 100644 --- a/src/main/resources/potions.yml +++ b/src/main/resources/potions.yml @@ -16,7 +16,8 @@ Concoctions: - SPIDER_EYE - SUGAR - SULPHUR - - WATER_LILY # TODO: 'RAW_FISH:3' (Minecraft 1.7) + - WATER_LILY + - 'RAW_FISH:3' Tier_Two_Ingredients: - CARROT_ITEM - SLIME_BALL @@ -97,7 +98,7 @@ Potions: SPIDER_EYE: 4868 # Potion of Poison SUGAR: 258 # Potion of Swiftness WATER_LILY: 3341 # Potion of Water Breathing (Minecraft 1.6) - # 'RAW_FISH:3': 3341 # TODO: Potion of Water Breathing (Minecraft 1.7) + 'RAW_FISH:3': 3341 # Potion of Water Breathing (Minecraft 1.7) 32: # Thick Potion Children: