diff --git a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java index e789ba304..b176fc245 100644 --- a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java @@ -404,13 +404,13 @@ public class EntityListener implements Listener { case COOKED_FISH: /* RESTORES 2 1/2 HUNGER - RESTORES 5 HUNGER @ 1000 */ if (Permissions.fishermansDiet(player)) { - event.setFoodLevel(Fishing.beginFishermansDiet(player, Fishing.fishermansDietRankLevel1, newFoodLevel)); + event.setFoodLevel(SkillManagerStore.getInstance().getFishingManager(player.getName()).handleFishermanDiet(Fishing.fishermansDietRankLevel1, newFoodLevel)); } return; case RAW_FISH: /* RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */ if (Permissions.fishermansDiet(player)) { - event.setFoodLevel(Fishing.beginFishermansDiet(player, Fishing.fishermansDietRankLevel2, newFoodLevel)); + event.setFoodLevel(SkillManagerStore.getInstance().getFishingManager(player.getName()).handleFishermanDiet(Fishing.fishermansDietRankLevel2, newFoodLevel)); } return; diff --git a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java index a039fd5a0..a4fc61d91 100644 --- a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java @@ -36,6 +36,7 @@ import com.gmail.nossr50.party.Party; import com.gmail.nossr50.party.ShareHandler; import com.gmail.nossr50.skills.SkillManagerStore; import com.gmail.nossr50.skills.fishing.Fishing; +import com.gmail.nossr50.skills.fishing.FishingManager; import com.gmail.nossr50.skills.herbalism.Herbalism; import com.gmail.nossr50.skills.mining.BlastMining; import com.gmail.nossr50.skills.repair.Repair; @@ -164,12 +165,17 @@ public class PlayerListener implements Listener { return; } + FishingManager fishingManager = SkillManagerStore.getInstance().getFishingManager(player.getName()); McMMOPlayer mcMMOPlayer = Users.getPlayer(player); int skillLevel = mcMMOPlayer.getProfile().getSkillLevel(SkillType.FISHING); switch (event.getState()) { case CAUGHT_FISH: - Fishing.beginFishing(mcMMOPlayer, skillLevel, event); + fishingManager.handleFishing((Item) event.getCaught()); + + if (Permissions.vanillaXpBoost(player, SkillType.FISHING)) { + event.setExpToDrop(fishingManager.handleVanillaXpBoost(event.getExpToDrop())); + } break; case CAUGHT_ENTITY: diff --git a/src/main/java/com/gmail/nossr50/skills/SkillManagerStore.java b/src/main/java/com/gmail/nossr50/skills/SkillManagerStore.java index c03b0a483..a0d9078ba 100644 --- a/src/main/java/com/gmail/nossr50/skills/SkillManagerStore.java +++ b/src/main/java/com/gmail/nossr50/skills/SkillManagerStore.java @@ -6,6 +6,7 @@ import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager; import com.gmail.nossr50.skills.archery.ArcheryManager; import com.gmail.nossr50.skills.axes.AxeManager; import com.gmail.nossr50.skills.excavation.ExcavationManager; +import com.gmail.nossr50.skills.fishing.FishingManager; import com.gmail.nossr50.skills.mining.MiningManager; import com.gmail.nossr50.skills.smelting.SmeltingManager; import com.gmail.nossr50.skills.swords.SwordsManager; @@ -20,6 +21,7 @@ public class SkillManagerStore { private HashMap archeryManagers = new HashMap(); private HashMap axeManagers = new HashMap(); private HashMap excavationManagers = new HashMap(); + private HashMap fishingManagers = new HashMap(); private HashMap miningManagers = new HashMap(); private HashMap smeltingManagers = new HashMap(); private HashMap swordsManagers = new HashMap(); @@ -66,6 +68,14 @@ public class SkillManagerStore { return excavationManagers.get(playerName); } + public FishingManager getFishingManager(String playerName) { + if (!fishingManagers.containsKey(playerName)) { + fishingManagers.put(playerName, new FishingManager(Users.getPlayer(playerName))); + } + + return fishingManagers.get(playerName); + } + public MiningManager getMiningManager(String playerName) { if (!miningManagers.containsKey(playerName)) { miningManagers.put(playerName, new MiningManager(Users.getPlayer(playerName))); diff --git a/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java b/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java index ae214ad49..fdd2838e3 100644 --- a/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java +++ b/src/main/java/com/gmail/nossr50/skills/excavation/ExcavationManager.java @@ -8,6 +8,7 @@ import org.bukkit.block.BlockState; import com.gmail.nossr50.datatypes.McMMOPlayer; import com.gmail.nossr50.datatypes.treasure.ExcavationTreasure; import com.gmail.nossr50.skills.SkillManager; +import com.gmail.nossr50.skills.utilities.SkillTools; import com.gmail.nossr50.skills.utilities.SkillType; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.Permissions; @@ -33,7 +34,7 @@ public class ExcavationManager extends SkillManager { Location location = blockState.getLocation(); for (ExcavationTreasure treasure : treasures) { - if (skillLevel >= treasure.getDropLevel() && Misc.getRandom().nextDouble() * activationChance <= treasure.getDropChance()) { + if (skillLevel >= treasure.getDropLevel() && SkillTools.treasureDropSuccessful(treasure.getDropChance(), activationChance)) { xp += treasure.getXp(); Misc.dropItem(location, treasure.getDrop()); } diff --git a/src/main/java/com/gmail/nossr50/skills/fishing/Fishing.java b/src/main/java/com/gmail/nossr50/skills/fishing/Fishing.java index 80403f66f..da9294989 100644 --- a/src/main/java/com/gmail/nossr50/skills/fishing/Fishing.java +++ b/src/main/java/com/gmail/nossr50/skills/fishing/Fishing.java @@ -1,28 +1,9 @@ package com.gmail.nossr50.skills.fishing; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Item; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerFishEvent; -import org.bukkit.inventory.ItemStack; import com.gmail.nossr50.config.AdvancedConfig; -import com.gmail.nossr50.config.Config; -import com.gmail.nossr50.config.TreasuresConfig; -import com.gmail.nossr50.datatypes.McMMOPlayer; -import com.gmail.nossr50.datatypes.treasure.FishingTreasure; -import com.gmail.nossr50.locale.LocaleLoader; -import com.gmail.nossr50.skills.utilities.PerksUtils; -import com.gmail.nossr50.skills.utilities.SkillTools; -import com.gmail.nossr50.skills.utilities.SkillType; -import com.gmail.nossr50.util.ItemChecks; -import com.gmail.nossr50.util.Misc; -import com.gmail.nossr50.util.Permissions; public final class Fishing { // The order of the values is extremely important, a few methods depend on it to work properly @@ -67,20 +48,10 @@ public final class Fishing { public static int fishermansDietRankLevel1 = AdvancedConfig.getInstance().getFishermanDietRankChange(); public static int fishermansDietRankLevel2 = fishermansDietRankLevel1 * 2; public static int fishermansDietMaxLevel = fishermansDietRankLevel1 * 5; + public static final double STORM_MODIFIER = 0.909; private Fishing() {} - /** - * Begins Fisherman's Diet ability - * - * @param player Player using the ability - * @param rankChange ??? - * @param event Event to process - */ - public static int beginFishermansDiet(Player player, int rankChange, int eventFoodLevel) { - return SkillTools.handleFoodSkills(player, SkillType.FISHING, eventFoodLevel, fishermansDietRankLevel1, fishermansDietMaxLevel, rankChange); - } - /** * Begins Shake Mob ability * @@ -91,173 +62,4 @@ public final class Fishing { public static void beginShakeMob(Player player, LivingEntity mob, int skillLevel) { ShakeMob.process(player, mob, skillLevel); } - - /** - * Begins Fishing - * - * @param mcMMOPlayer Player fishing - * @param skillLevel Fishing level of the player - * @param event Event to process - */ - public static void beginFishing(McMMOPlayer mcMMOPlayer, int skillLevel, PlayerFishEvent event) { - int treasureXp = 0; - Player player = mcMMOPlayer.getPlayer(); - FishingTreasure treasure = checkForTreasure(player, skillLevel); - - if (treasure != null) { - player.sendMessage(LocaleLoader.getString("Fishing.ItemFound")); - - treasureXp = treasure.getXp(); - ItemStack treasureDrop = treasure.getDrop(); - - if (Permissions.magicHunter(player) && beginMagicHunter(player, skillLevel, treasureDrop, player.getWorld().hasStorm())) { - player.sendMessage(LocaleLoader.getString("Fishing.MagicFound")); - } - - // Drop the original catch at the feet of the player and set the treasure as the real catch - Item caught = (Item) event.getCaught(); - Misc.dropItem(player.getEyeLocation(), caught.getItemStack()); - caught.setItemStack(treasureDrop); - } - - mcMMOPlayer.beginXpGain(SkillType.FISHING, Config.getInstance().getFishingBaseXP() + treasureXp); - if (Permissions.vanillaXpBoost(player, SkillType.FISHING)) { - event.setExpToDrop(event.getExpToDrop() * getVanillaXpMultiplier(skillLevel)); - } - } - - /** - * Checks for treasure - * - * @param player Player fishing - * @param skillLevel Fishing level of the player - * @return Chosen treasure - */ - private static FishingTreasure checkForTreasure(Player player, int skillLevel) { - if (!Config.getInstance().getFishingDropsEnabled() || !Permissions.fishingTreasureHunter(player)) { - return null; - } - - List rewards = new ArrayList(); - - for (FishingTreasure treasure : TreasuresConfig.getInstance().fishingRewards) { - int maxLevel = treasure.getMaxLevel(); - - if (treasure.getDropLevel() <= skillLevel && (maxLevel >= skillLevel || maxLevel <= 0)) { - rewards.add(treasure); - } - } - - if (rewards.isEmpty()) { - return null; - } - - FishingTreasure treasure = rewards.get(Misc.getRandom().nextInt(rewards.size())); - ItemStack treasureDrop = treasure.getDrop(); - int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.FISHING); - - if (Misc.getRandom().nextDouble() * activationChance > treasure.getDropChance()) { - return null; - } - - short maxDurability = treasureDrop.getType().getMaxDurability(); - - if (maxDurability > 0) { - treasureDrop.setDurability((short) (Misc.getRandom().nextInt(maxDurability))); - } - - return treasure; - } - - /** - * Processes for treasure - * - * @param player Player fishing - * @param skillLevel Fishing level of the player - * @param itemStack ItemStack to enchant - * @param storm World's weather - * @return True if the ItemStack has been enchanted - */ - private static boolean beginMagicHunter(Player player, int skillLevel, ItemStack itemStack, boolean storm) { - if (!ItemChecks.isEnchantable(itemStack)) { - return false; - } - - int activationChance = PerksUtils.handleLuckyPerks(player, SkillType.FISHING); - - if (storm) { - activationChance = (int) (activationChance * 0.909); - } - - if (Misc.getRandom().nextInt(activationChance) > getLootTier(skillLevel) * AdvancedConfig.getInstance().getFishingMagicMultiplier()) { - return false; - } - - List possibleEnchantments = new ArrayList(); - - for (Enchantment enchantment : Enchantment.values()) { - if (enchantment.canEnchantItem(itemStack)) { - possibleEnchantments.add(enchantment); - } - } - - // This make sure that the order isn't always the same, for example previously Unbreaking had a lot more chance to be used than any other enchant - Collections.shuffle(possibleEnchantments, Misc.getRandom()); - - boolean enchanted = false; - int specificChance = 1; - - for (Enchantment possibleEnchantment : possibleEnchantments) { - boolean conflicts = false; - - for (Enchantment currentEnchantment : itemStack.getEnchantments().keySet()) { - conflicts = currentEnchantment.conflictsWith(possibleEnchantment); - - if (conflicts) { - break; - } - } - - if (!conflicts && Misc.getRandom().nextInt(specificChance) == 0) { - itemStack.addEnchantment(possibleEnchantment, Misc.getRandom().nextInt(possibleEnchantment.getMaxLevel()) + 1); - - specificChance++; - enchanted = true; - } - } - - return enchanted; - } - - /** - * Gets the loot tier for a given skill level - * - * @param skillLevel Fishing skill level - * @return Loot tier - */ - public static int getLootTier(int skillLevel) { - for (Tier tier : Tier.values()) { - if (skillLevel >= tier.getLevel()) { - return tier.toNumerical(); - } - } - - return 0; - } - - /** - * Gets the vanilla xp multiplier for a given skill level - * - * @param skillLevel Fishing skill level - * @return Shake Mob probability - */ - public static int getVanillaXpMultiplier(int skillLevel) { - for (Tier tier : Tier.values()) { - if (skillLevel >= tier.getLevel()) { - return tier.getVanillaXPBoostModifier(); - } - } - - return 0; - } } diff --git a/src/main/java/com/gmail/nossr50/skills/fishing/FishingCommand.java b/src/main/java/com/gmail/nossr50/skills/fishing/FishingCommand.java index 858341503..3b0731670 100644 --- a/src/main/java/com/gmail/nossr50/skills/fishing/FishingCommand.java +++ b/src/main/java/com/gmail/nossr50/skills/fishing/FishingCommand.java @@ -3,6 +3,7 @@ package com.gmail.nossr50.skills.fishing; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.skills.SkillCommand; +import com.gmail.nossr50.skills.SkillManagerStore; import com.gmail.nossr50.skills.utilities.SkillType; import com.gmail.nossr50.util.Permissions; @@ -26,7 +27,7 @@ public class FishingCommand extends SkillCommand { @Override protected void dataCalculations() { - lootTier = Fishing.getLootTier((int) skillValue); + lootTier = SkillManagerStore.getInstance().getFishingManager(player.getName()).getLootTier(); //TREASURE HUNTER double enchantChance = lootTier * AdvancedConfig.getInstance().getFishingMagicMultiplier(); diff --git a/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java b/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java new file mode 100644 index 000000000..caba1abcb --- /dev/null +++ b/src/main/java/com/gmail/nossr50/skills/fishing/FishingManager.java @@ -0,0 +1,210 @@ +package com.gmail.nossr50.skills.fishing; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import com.gmail.nossr50.config.AdvancedConfig; +import com.gmail.nossr50.config.Config; +import com.gmail.nossr50.config.TreasuresConfig; +import com.gmail.nossr50.datatypes.McMMOPlayer; +import com.gmail.nossr50.datatypes.treasure.FishingTreasure; +import com.gmail.nossr50.locale.LocaleLoader; +import com.gmail.nossr50.skills.SkillManager; +import com.gmail.nossr50.skills.fishing.Fishing.Tier; +import com.gmail.nossr50.skills.utilities.SkillTools; +import com.gmail.nossr50.skills.utilities.SkillType; +import com.gmail.nossr50.util.ItemChecks; +import com.gmail.nossr50.util.Misc; +import com.gmail.nossr50.util.Permissions; + +public class FishingManager extends SkillManager { + + public FishingManager(McMMOPlayer mcMMOPlayer) { + super(mcMMOPlayer, SkillType.FISHING); + } + + /** + * Handle the Fisherman's Diet ability + * + * @param rankChange The # of levels to change rank for the food + * @param eventFoodLevel The initial change in hunger from the event + * @return the modified change in hunger for the event + */ + public int handleFishermanDiet(int rankChange, int eventFoodLevel) { + return SkillTools.handleFoodSkills(getPlayer(), skill, eventFoodLevel, Fishing.fishermansDietRankLevel1, Fishing.fishermansDietMaxLevel, rankChange); + } + + /** + * Process the results from a successful fishing trip + * + * @param fishingCatch The {@link Item} initially caught + */ + public void handleFishing(Item fishingCatch) { + int treasureXp = 0; + Player player = getPlayer(); + FishingTreasure treasure = null; + + if (Config.getInstance().getFishingDropsEnabled() && Permissions.fishingTreasureHunter(player)) { + treasure = getFishingTreasure(); + } + + if (treasure != null) { + player.sendMessage(LocaleLoader.getString("Fishing.ItemFound")); + + treasureXp = treasure.getXp(); + ItemStack treasureDrop = treasure.getDrop(); + + if (Permissions.magicHunter(player) && ItemChecks.isEnchantable(treasureDrop) && handleMagicHunter(treasureDrop)) { + player.sendMessage(LocaleLoader.getString("Fishing.MagicFound")); + } + + // Drop the original catch at the feet of the player and set the treasure as the real catch + Misc.dropItem(player.getEyeLocation(), fishingCatch.getItemStack()); + fishingCatch.setItemStack(treasureDrop); + } + + applyXpGain(Config.getInstance().getFishingBaseXP() + treasureXp); + } + + /** + * Handle the vanilla XP boost for Fishing + * + * @param experience The amount of experience initially awarded by the event + * @return the modified event damage + */ + public int handleVanillaXpBoost(int experience) { + return experience * getVanillaXpMultiplier(); + } + + /** + * Process the Treasure Hunter ability for Fishing + * + * @return The {@link FishingTreasure} found, or null if no treasure was found. + */ + private FishingTreasure getFishingTreasure() { + List rewards = new ArrayList(); + int skillLevel = getSkillLevel(); + + for (FishingTreasure treasure : TreasuresConfig.getInstance().fishingRewards) { + int maxLevel = treasure.getMaxLevel(); + + if (treasure.getDropLevel() <= skillLevel && (maxLevel >= skillLevel || maxLevel <= 0)) { + rewards.add(treasure); + } + } + + if (rewards.isEmpty()) { + return null; + } + + FishingTreasure treasure = rewards.get(Misc.getRandom().nextInt(rewards.size())); + ItemStack treasureDrop = treasure.getDrop(); + + if (!SkillTools.treasureDropSuccessful(treasure.getDropChance(), skillLevel)) { + return null; + } + + short maxDurability = treasureDrop.getType().getMaxDurability(); + + if (maxDurability > 0) { + treasureDrop.setDurability((short) (Misc.getRandom().nextInt(maxDurability))); + } + + return treasure; + } + + /** + * Process the Magic Hunter ability + * + * @param treasureDrop The {@link ItemStack} to enchant + * @return true if the item has been enchanted + */ + private boolean handleMagicHunter(ItemStack treasureDrop) { + Player player = getPlayer(); + int activationChance = this.activationChance; + + if (player.getWorld().hasStorm()) { + activationChance *= Fishing.STORM_MODIFIER; + } + + if (Misc.getRandom().nextInt(activationChance) > getLootTier() * AdvancedConfig.getInstance().getFishingMagicMultiplier()) { + return false; + } + + List possibleEnchantments = new ArrayList(); + + for (Enchantment enchantment : Enchantment.values()) { + if (enchantment.canEnchantItem(treasureDrop)) { + possibleEnchantments.add(enchantment); + } + } + + // This make sure that the order isn't always the same, for example previously Unbreaking had a lot more chance to be used than any other enchant + Collections.shuffle(possibleEnchantments, Misc.getRandom()); + + boolean enchanted = false; + int specificChance = 1; + + for (Enchantment possibleEnchantment : possibleEnchantments) { + boolean conflicts = false; + + for (Enchantment currentEnchantment : treasureDrop.getEnchantments().keySet()) { + conflicts = currentEnchantment.conflictsWith(possibleEnchantment); + + if (conflicts) { + break; + } + } + + if (!conflicts && Misc.getRandom().nextInt(specificChance) == 0) { + treasureDrop.addEnchantment(possibleEnchantment, Misc.getRandom().nextInt(possibleEnchantment.getMaxLevel()) + 1); + + specificChance++; + enchanted = true; + } + } + + return enchanted; + } + + /** + * Gets the loot tier + * + * @return the loot tier + */ + public int getLootTier() { + int skillLevel = getSkillLevel(); + + for (Tier tier : Tier.values()) { + if (skillLevel >= tier.getLevel()) { + return tier.toNumerical(); + } + } + + return 0; + } + + + /** + * Gets the vanilla XP multiplier + * + * @return the vanilla XP multiplier + */ + private int getVanillaXpMultiplier() { + int skillLevel = getSkillLevel(); + + for (Tier tier : Tier.values()) { + if (skillLevel >= tier.getLevel()) { + return tier.getVanillaXPBoostModifier(); + } + } + + return 0; + } +} diff --git a/src/main/java/com/gmail/nossr50/skills/utilities/SkillTools.java b/src/main/java/com/gmail/nossr50/skills/utilities/SkillTools.java index d90a0eb42..f57b81962 100644 --- a/src/main/java/com/gmail/nossr50/skills/utilities/SkillTools.java +++ b/src/main/java/com/gmail/nossr50/skills/utilities/SkillTools.java @@ -616,4 +616,8 @@ public class SkillTools { public static boolean unlockLevelReached(Player player, SkillType skill, int unlockLevel) { return Users.getPlayer(player).getProfile().getSkillLevel(skill) > unlockLevel; } + + public static boolean treasureDropSuccessful(double dropChance, int activationChance) { + return dropChance > Misc.getRandom().nextDouble() * activationChance; + } } diff --git a/src/main/java/com/gmail/nossr50/spout/SpoutListener.java b/src/main/java/com/gmail/nossr50/spout/SpoutListener.java index 3e7532389..07972fae0 100644 --- a/src/main/java/com/gmail/nossr50/spout/SpoutListener.java +++ b/src/main/java/com/gmail/nossr50/spout/SpoutListener.java @@ -29,7 +29,7 @@ public class SpoutListener implements Listener { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onSpoutCraftEnable(SpoutCraftEnableEvent event) { SpoutPlayer spoutPlayer = event.getPlayer(); - McMMOPlayer mcMMOPlayer = Users.getPlayer(event.getPlayer().getPlayer()); + McMMOPlayer mcMMOPlayer = Users.getPlayer(spoutPlayer); PlayerProfile profile = mcMMOPlayer.getProfile(); //TODO: Add custom titles based on skills