From f8b44120497445d3da8209bf65890b5d687ab21a Mon Sep 17 00:00:00 2001 From: bm01 Date: Sun, 3 Mar 2013 16:09:41 +0100 Subject: [PATCH] Each McMMOPlayer now store its SkillManager objects Should fix a recent memory leak --- .../commands/skills/FishingCommand.java | 6 +- .../commands/skills/MiningCommand.java | 4 +- .../commands/skills/SmeltingCommand.java | 4 +- .../nossr50/datatypes/player/McMMOPlayer.java | 91 ++++++++++++- .../nossr50/datatypes/skills/SkillType.java | 53 +++++--- .../nossr50/listeners/BlockListener.java | 26 ++-- .../nossr50/listeners/EntityListener.java | 26 ++-- .../nossr50/listeners/InventoryListener.java | 7 +- .../nossr50/listeners/PlayerListener.java | 25 ++-- .../nossr50/skills/SkillManagerStore.java | 128 ------------------ .../{AxeManager.java => AxesManager.java} | 4 +- .../nossr50/util/skills/CombatUtils.java | 96 +++++++------ 12 files changed, 234 insertions(+), 236 deletions(-) delete mode 100644 src/main/java/com/gmail/nossr50/skills/SkillManagerStore.java rename src/main/java/com/gmail/nossr50/skills/axes/{AxeManager.java => AxesManager.java} (98%) diff --git a/src/main/java/com/gmail/nossr50/commands/skills/FishingCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/FishingCommand.java index 603b09203..0c1f6c1e1 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/FishingCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/FishingCommand.java @@ -3,9 +3,9 @@ package com.gmail.nossr50.commands.skills; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.locale.LocaleLoader; -import com.gmail.nossr50.skills.SkillManagerStore; import com.gmail.nossr50.skills.fishing.Fishing; import com.gmail.nossr50.util.Permissions; +import com.gmail.nossr50.util.player.UserManager; public class FishingCommand extends SkillCommand { private int lootTier; @@ -27,7 +27,7 @@ public class FishingCommand extends SkillCommand { @Override protected void dataCalculations() { - lootTier = SkillManagerStore.getInstance().getFishingManager(player.getName()).getLootTier(); + lootTier = UserManager.getPlayer(player).getFishingManager().getLootTier(); // TREASURE HUNTER double enchantChance = lootTier * AdvancedConfig.getInstance().getFishingMagicMultiplier(); @@ -42,7 +42,7 @@ public class FishingCommand extends SkillCommand { magicChanceLucky = treasureHunterStrings[1]; // SHAKE - String[] shakeStrings = calculateAbilityDisplayValues(SkillManagerStore.getInstance().getFishingManager(player.getName()).getShakeProbability()); + String[] shakeStrings = calculateAbilityDisplayValues(UserManager.getPlayer(player).getFishingManager().getShakeProbability()); shakeChance = shakeStrings[0]; shakeChanceLucky = shakeStrings[1]; diff --git a/src/main/java/com/gmail/nossr50/commands/skills/MiningCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/MiningCommand.java index 3c2a67db2..096756600 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/MiningCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/MiningCommand.java @@ -3,10 +3,10 @@ package com.gmail.nossr50.commands.skills; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.locale.LocaleLoader; -import com.gmail.nossr50.skills.SkillManagerStore; import com.gmail.nossr50.skills.mining.Mining; import com.gmail.nossr50.skills.mining.MiningManager; import com.gmail.nossr50.util.Permissions; +import com.gmail.nossr50.util.player.UserManager; public class MiningCommand extends SkillCommand { private String doubleDropChance; @@ -45,7 +45,7 @@ public class MiningCommand extends SkillCommand { doubleDropChanceLucky = doubleDropStrings[1]; // BLAST MINING - MiningManager miningManager = SkillManagerStore.getInstance().getMiningManager(player.getName()); + MiningManager miningManager = UserManager.getPlayer(player).getMiningManager(); blastMiningRank = miningManager.getBlastMiningTier(); bonusTNTDrops = miningManager.getDropMultiplier(); oreBonus = percent.format(miningManager.getOreBonus() / 30.0D); // Base received in TNT is 30% diff --git a/src/main/java/com/gmail/nossr50/commands/skills/SmeltingCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/SmeltingCommand.java index 09a647af3..c87298471 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/SmeltingCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/SmeltingCommand.java @@ -3,9 +3,9 @@ package com.gmail.nossr50.commands.skills; import com.gmail.nossr50.config.AdvancedConfig; import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.locale.LocaleLoader; -import com.gmail.nossr50.skills.SkillManagerStore; import com.gmail.nossr50.skills.smelting.Smelting; import com.gmail.nossr50.util.Permissions; +import com.gmail.nossr50.util.player.UserManager; public class SmeltingCommand extends SkillCommand { private String burnTimeModifier; @@ -41,7 +41,7 @@ public class SmeltingCommand extends SkillCommand { fluxMiningChanceLucky = fluxMiningStrings[1]; // VANILLA XP BOOST - vanillaXPModifier = SkillManagerStore.getInstance().getSmeltingManager(player.getName()).getVanillaXpMultiplier(); + vanillaXPModifier = UserManager.getPlayer(player).getSmeltingManager().getVanillaXpMultiplier(); } @Override diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java index 54a5929e2..6d436fc52 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java @@ -1,5 +1,7 @@ package com.gmail.nossr50.datatypes.player; +import java.util.HashMap; +import java.util.Map; import java.util.Set; import org.bukkit.GameMode; @@ -15,7 +17,19 @@ import com.gmail.nossr50.datatypes.spout.huds.McMMOHud; import com.gmail.nossr50.events.experience.McMMOPlayerXpGainEvent; import com.gmail.nossr50.party.PartyManager; import com.gmail.nossr50.party.ShareHandler; +import com.gmail.nossr50.skills.SkillManager; +import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager; +import com.gmail.nossr50.skills.archery.ArcheryManager; +import com.gmail.nossr50.skills.axes.AxesManager; import com.gmail.nossr50.skills.child.FamilyTree; +import com.gmail.nossr50.skills.excavation.ExcavationManager; +import com.gmail.nossr50.skills.fishing.FishingManager; +import com.gmail.nossr50.skills.herbalism.HerbalismManager; +import com.gmail.nossr50.skills.mining.MiningManager; +import com.gmail.nossr50.skills.smelting.SmeltingManager; +import com.gmail.nossr50.skills.swords.SwordsManager; +import com.gmail.nossr50.skills.taming.TamingManager; +import com.gmail.nossr50.skills.unarmed.UnarmedManager; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.ModUtils; import com.gmail.nossr50.util.Permissions; @@ -26,6 +40,15 @@ public class McMMOPlayer { private Player player; private PlayerProfile profile; + /* + * Since SkillManager isn't a "polymorphic type" we may prefer to have one field for each of our + * class inheriting from SkillManager. This would also prevent the need for casting. + * However, by using the map and the loop in the constructor + * we make sure that all class inheriting from SkillManager are instanced. + * Which solution is better, I let you decide. - bm01 + */ + private Map skillManagers = new HashMap(); + private Party party; private Party invite; @@ -43,8 +66,72 @@ public class McMMOPlayer { String playerName = player.getName(); this.player = player; - this.profile = new PlayerProfile(playerName, true); - this.party = PartyManager.getPlayerParty(playerName); + profile = new PlayerProfile(playerName, true); + party = PartyManager.getPlayerParty(playerName); + + /* + * I'm using this method because it makes code shorter and safer (we don't have to add all SkillTypes manually), + * but I actually have no idea about the performance impact, if there is any. + * If in the future someone wants to remove this, don't forget to also remove what is in the SkillType enum. - bm01 + */ + try { + for (SkillType skillType : SkillType.values()) { + Class skillManagerClass = skillType.getManagerClass(); + + // TODO: The null check is needed only because currently some SkillType doesn't have a valid skillManagerClass + if (skillManagerClass != null) { + skillManagers.put(skillType, skillManagerClass.getConstructor(McMMOPlayer.class).newInstance(this)); + } + } + } + catch (Exception e) { + e.printStackTrace(); + mcMMO.p.getPluginLoader().disablePlugin(mcMMO.p); + } + } + + public AcrobaticsManager getAcrobaticsManager() { + return (AcrobaticsManager) skillManagers.get(SkillType.ACROBATICS); + } + + public ArcheryManager getArcheryManager() { + return (ArcheryManager) skillManagers.get(SkillType.ARCHERY); + } + + public AxesManager getAxesManager() { + return (AxesManager) skillManagers.get(SkillType.AXES); + } + + public ExcavationManager getExcavationManager() { + return (ExcavationManager) skillManagers.get(SkillType.EXCAVATION); + } + + public FishingManager getFishingManager() { + return (FishingManager) skillManagers.get(SkillType.FISHING); + } + + public HerbalismManager getHerbalismManager() { + return (HerbalismManager) skillManagers.get(SkillType.HERBALISM); + } + + public MiningManager getMiningManager() { + return (MiningManager) skillManagers.get(SkillType.MINING); + } + + public SmeltingManager getSmeltingManager() { + return (SmeltingManager) skillManagers.get(SkillType.SMELTING); + } + + public SwordsManager getSwordsManager() { + return (SwordsManager) skillManagers.get(SkillType.SWORDS); + } + + public TamingManager getTamingManager() { + return (TamingManager) skillManagers.get(SkillType.TAMING); + } + + public UnarmedManager getUnarmedManager() { + return (UnarmedManager) skillManagers.get(SkillType.UNARMED); } /** 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 ecc9b55f1..565ee66de 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/SkillType.java @@ -3,36 +3,55 @@ package com.gmail.nossr50.datatypes.skills; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.config.Config; import com.gmail.nossr50.locale.LocaleLoader; +import com.gmail.nossr50.skills.SkillManager; +import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager; +import com.gmail.nossr50.skills.archery.ArcheryManager; +import com.gmail.nossr50.skills.axes.AxesManager; +import com.gmail.nossr50.skills.excavation.ExcavationManager; +import com.gmail.nossr50.skills.fishing.FishingManager; +import com.gmail.nossr50.skills.herbalism.HerbalismManager; +import com.gmail.nossr50.skills.mining.MiningManager; +import com.gmail.nossr50.skills.smelting.SmeltingManager; +import com.gmail.nossr50.skills.swords.SwordsManager; +import com.gmail.nossr50.skills.taming.TamingManager; +import com.gmail.nossr50.skills.unarmed.UnarmedManager; import com.gmail.nossr50.util.StringUtils; public enum SkillType { - ACROBATICS, - ARCHERY, - AXES(AbilityType.SKULL_SPLITTER, ToolType.AXE), - EXCAVATION(AbilityType.GIGA_DRILL_BREAKER, ToolType.SHOVEL), - FISHING, - HERBALISM(AbilityType.GREEN_TERRA, ToolType.HOE), - MINING(AbilityType.SUPER_BREAKER, ToolType.PICKAXE), - REPAIR, - SMELTING, - SWORDS(AbilityType.SERRATED_STRIKES, ToolType.SWORD), - TAMING, - UNARMED(AbilityType.BERSERK, ToolType.FISTS), - WOODCUTTING(AbilityType.TREE_FELLER, ToolType.AXE); + ACROBATICS(AcrobaticsManager.class), + ARCHERY(ArcheryManager.class), + AXES(AxesManager.class, AbilityType.SKULL_SPLITTER, ToolType.AXE), + EXCAVATION(ExcavationManager.class, AbilityType.GIGA_DRILL_BREAKER, ToolType.SHOVEL), + FISHING(FishingManager.class), + HERBALISM(HerbalismManager.class, AbilityType.GREEN_TERRA, ToolType.HOE), + MINING(MiningManager.class, AbilityType.SUPER_BREAKER, ToolType.PICKAXE), + REPAIR(null), // TODO: Create a proper RepairManager class + SMELTING(SmeltingManager.class), + SWORDS(SwordsManager.class, AbilityType.SERRATED_STRIKES, ToolType.SWORD), + TAMING(TamingManager.class), + UNARMED(UnarmedManager.class, AbilityType.BERSERK, ToolType.FISTS), + WOODCUTTING(null, AbilityType.TREE_FELLER, ToolType.AXE); // TODO: Create a proper WoodcuttingManager class + private Class managerClass; private AbilityType ability; private ToolType tool; - private SkillType() { - this.ability = null; - this.tool = null; + private SkillType(Class managerClass) { + this.managerClass = managerClass; + ability = null; + tool = null; } - private SkillType(AbilityType ability, ToolType tool) { + private SkillType(Class managerClass, AbilityType ability, ToolType tool) { + this.managerClass = managerClass; this.ability = ability; this.tool = tool; } + public Class getManagerClass() { + return managerClass; + } + public AbilityType getAbility() { return ability; } diff --git a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java index 940ccc24e..39f15e147 100644 --- a/src/main/java/com/gmail/nossr50/listeners/BlockListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/BlockListener.java @@ -31,12 +31,12 @@ import com.gmail.nossr50.events.fake.FakeBlockBreakEvent; import com.gmail.nossr50.events.fake.FakeBlockDamageEvent; import com.gmail.nossr50.events.fake.FakePlayerAnimationEvent; import com.gmail.nossr50.runnables.StickyPistonTrackerTask; -import com.gmail.nossr50.skills.SkillManagerStore; import com.gmail.nossr50.skills.excavation.ExcavationManager; import com.gmail.nossr50.skills.herbalism.HerbalismManager; import com.gmail.nossr50.skills.mining.MiningManager; import com.gmail.nossr50.skills.repair.Repair; import com.gmail.nossr50.skills.repair.Salvage; +import com.gmail.nossr50.skills.smelting.SmeltingManager; import com.gmail.nossr50.skills.unarmed.Unarmed; import com.gmail.nossr50.skills.woodcutting.Woodcutting; import com.gmail.nossr50.util.BlockUtils; @@ -152,7 +152,7 @@ public class BlockListener implements Listener { /* HERBALISM */ if (BlockUtils.affectedByGreenTerra(blockState)) { - HerbalismManager herbalismManager = SkillManagerStore.getInstance().getHerbalismManager(player.getName()); + HerbalismManager herbalismManager = UserManager.getPlayer(player).getHerbalismManager(); /* Green Terra */ if (herbalismManager.canActivateAbility()) { @@ -177,7 +177,7 @@ public class BlockListener implements Listener { /* MINING */ else if (BlockUtils.affectedBySuperBreaker(blockState) && ItemUtils.isPickaxe(heldItem) && Permissions.skillEnabled(player, SkillType.MINING) && !mcMMO.placeStore.isTrue(blockState)) { - MiningManager miningManager = SkillManagerStore.getInstance().getMiningManager(player.getName()); + MiningManager miningManager = UserManager.getPlayer(player).getMiningManager(); miningManager.miningBlockCheck(blockState); if (profile.getAbilityMode(AbilityType.SUPER_BREAKER)) { @@ -204,7 +204,7 @@ public class BlockListener implements Listener { /* EXCAVATION */ else if (BlockUtils.affectedByGigaDrillBreaker(blockState) && ItemUtils.isShovel(heldItem) && Permissions.skillEnabled(player, SkillType.EXCAVATION) && !mcMMO.placeStore.isTrue(blockState)) { - ExcavationManager excavationManager = SkillManagerStore.getInstance().getExcavationManager(player.getName()); + ExcavationManager excavationManager = UserManager.getPlayer(player).getExcavationManager(); excavationManager.excavationBlockCheck(blockState); if (profile.getAbilityMode(AbilityType.GIGA_DRILL_BREAKER)) { @@ -235,17 +235,19 @@ public class BlockListener implements Listener { return; } - String playerName = player.getName(); BlockState blockState = event.getBlock().getState(); + McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + HerbalismManager herbalismManager = mcMMOPlayer.getHerbalismManager(); + SmeltingManager smeltingManager = mcMMOPlayer.getSmeltingManager(); - if (SkillManagerStore.getInstance().getHerbalismManager(playerName).canUseHylianLuck()) { - if (SkillManagerStore.getInstance().getHerbalismManager(playerName).processHylianLuck(blockState)) { + if (herbalismManager.canUseHylianLuck()) { + if (herbalismManager.processHylianLuck(blockState)) { blockState.update(true); event.setCancelled(true); } } - else if (SkillManagerStore.getInstance().getSmeltingManager(playerName).canUseFluxMining(blockState)) { - if (SkillManagerStore.getInstance().getSmeltingManager(playerName).processFluxMining(blockState)) { + else if (smeltingManager.canUseFluxMining(blockState)) { + if (smeltingManager.processFluxMining(blockState)) { blockState.update(true); event.setCancelled(true); } @@ -335,20 +337,20 @@ public class BlockListener implements Listener { return; } - String playerName = player.getName(); McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); PlayerProfile profile = mcMMOPlayer.getProfile(); ItemStack heldItem = player.getItemInHand(); Block block = event.getBlock(); BlockState blockState = block.getState(); + HerbalismManager herbalismManager = mcMMOPlayer.getHerbalismManager(); /* * ABILITY TRIGGER CHECKS * * We don't need to check permissions here because they've already been checked for the ability to even activate. */ - if (SkillManagerStore.getInstance().getHerbalismManager(playerName).canGreenTerraBlock(blockState)) { - if (SkillManagerStore.getInstance().getHerbalismManager(playerName).processGreenTerra(blockState)) { + if (herbalismManager.canGreenTerraBlock(blockState)) { + if (herbalismManager.processGreenTerra(blockState)) { blockState.update(true); } } diff --git a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java index 1e3b460c8..b9b29071f 100644 --- a/src/main/java/com/gmail/nossr50/listeners/EntityListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/EntityListener.java @@ -33,7 +33,7 @@ import com.gmail.nossr50.events.fake.FakeEntityDamageByEntityEvent; import com.gmail.nossr50.events.fake.FakeEntityDamageEvent; import com.gmail.nossr50.party.PartyManager; import com.gmail.nossr50.runnables.skills.BleedTimerTask; -import com.gmail.nossr50.skills.SkillManagerStore; +import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager; import com.gmail.nossr50.skills.archery.Archery; import com.gmail.nossr50.skills.fishing.Fishing; import com.gmail.nossr50.skills.herbalism.Herbalism; @@ -171,8 +171,10 @@ public class EntityListener implements Listener { switch (cause) { case FALL: - if (SkillManagerStore.getInstance().getAcrobaticsManager(player.getName()).canRoll()) { - event.setDamage(SkillManagerStore.getInstance().getAcrobaticsManager(player.getName()).rollCheck(event.getDamage())); + AcrobaticsManager acrobaticsManager = mcMMOPlayer.getAcrobaticsManager(); + + if (acrobaticsManager.canRoll()) { + event.setDamage(acrobaticsManager.rollCheck(event.getDamage())); if (event.getDamage() == 0) { event.setCancelled(true); @@ -182,7 +184,7 @@ public class EntityListener implements Listener { break; case BLOCK_EXPLOSION: - MiningManager miningManager = SkillManagerStore.getInstance().getMiningManager(player.getName()); + MiningManager miningManager = mcMMOPlayer.getMiningManager(); if (miningManager.canUseDemolitionsExpertise()) { event.setDamage(miningManager.processDemolitionsExpertise(event.getDamage())); @@ -318,7 +320,8 @@ public class EntityListener implements Listener { int id = entity.getEntityId(); if (plugin.tntIsTracked(id)) { - MiningManager miningManager = SkillManagerStore.getInstance().getMiningManager(plugin.getTNTPlayer(id).getName()); + + MiningManager miningManager = UserManager.getPlayer(plugin.getTNTPlayer(id)).getMiningManager(); if (miningManager.canUseBiggerBombs()) { event.setRadius(miningManager.biggerBombs(event.getRadius())); @@ -340,7 +343,7 @@ public class EntityListener implements Listener { int id = entity.getEntityId(); if (plugin.tntIsTracked(id)) { - MiningManager miningManager = SkillManagerStore.getInstance().getMiningManager(plugin.getTNTPlayer(id).getName()); + MiningManager miningManager = UserManager.getPlayer(plugin.getTNTPlayer(id)).getMiningManager(); if (miningManager.canUseBlastMining()) { miningManager.blastMiningDropProcessing(event.getYield(), event.blockList()); @@ -387,7 +390,7 @@ public class EntityListener implements Listener { case MUSHROOM_SOUP: /* RESTORES 4 HUNGER - RESTORES 6 1/2 HUNGER @ 1000 */ case PUMPKIN_PIE: /* RESTORES 4 HUNGER - RESTORES 6 1/2 HUNGER @ 1000 */ if (Permissions.farmersDiet(player)) { - event.setFoodLevel(SkillManagerStore.getInstance().getHerbalismManager(player.getName()).farmersDiet(Herbalism.farmersDietRankLevel1, newFoodLevel)); + event.setFoodLevel(UserManager.getPlayer(player).getHerbalismManager().farmersDiet(Herbalism.farmersDietRankLevel1, newFoodLevel)); } return; @@ -396,19 +399,19 @@ public class EntityListener implements Listener { case POISONOUS_POTATO: /* RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */ case POTATO_ITEM: /* RESTORES 1/2 HUNGER - RESTORES 2 HUNGER @ 1000 */ if (Permissions.farmersDiet(player)) { - event.setFoodLevel(SkillManagerStore.getInstance().getHerbalismManager(player.getName()).farmersDiet(Herbalism.farmersDietRankLevel2, newFoodLevel)); + event.setFoodLevel(UserManager.getPlayer(player).getHerbalismManager().farmersDiet(Herbalism.farmersDietRankLevel2, newFoodLevel)); } return; case COOKED_FISH: /* RESTORES 2 1/2 HUNGER - RESTORES 5 HUNGER @ 1000 */ if (Permissions.fishermansDiet(player)) { - event.setFoodLevel(SkillManagerStore.getInstance().getFishingManager(player.getName()).handleFishermanDiet(Fishing.fishermansDietRankLevel1, newFoodLevel)); + event.setFoodLevel(UserManager.getPlayer(player).getFishingManager().handleFishermanDiet(Fishing.fishermansDietRankLevel1, newFoodLevel)); } return; case RAW_FISH: /* RESTORES 1 HUNGER - RESTORES 2 1/2 HUNGER @ 1000 */ if (Permissions.fishermansDiet(player)) { - event.setFoodLevel(SkillManagerStore.getInstance().getFishingManager(player.getName()).handleFishermanDiet(Fishing.fishermansDietRankLevel2, newFoodLevel)); + event.setFoodLevel(UserManager.getPlayer(player).getFishingManager().handleFishermanDiet(Fishing.fishermansDietRankLevel2, newFoodLevel)); } return; @@ -435,7 +438,7 @@ public class EntityListener implements Listener { LivingEntity entity = event.getEntity(); if (entity != null && !entity.hasMetadata(mcMMO.entityMetadataKey)) { - SkillManagerStore.getInstance().getTamingManager(player.getName()).awardTamingXP(entity); + UserManager.getPlayer(player).getTamingManager().awardTamingXP(entity); } } @@ -449,6 +452,7 @@ public class EntityListener implements Listener { // isFriendlyPet ensures that the Tameable is: Tamed, owned by a player, and the owner is in the same party // So we can make some assumptions here, about our casting and our check Player owner = (Player) tameable.getOwner(); + if (!(Permissions.friendlyFire(player) && Permissions.friendlyFire(owner))) { event.setCancelled(true); return; diff --git a/src/main/java/com/gmail/nossr50/listeners/InventoryListener.java b/src/main/java/com/gmail/nossr50/listeners/InventoryListener.java index 0563a0af6..ebf852a39 100644 --- a/src/main/java/com/gmail/nossr50/listeners/InventoryListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/InventoryListener.java @@ -20,7 +20,6 @@ import org.bukkit.inventory.ItemStack; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.skills.SkillType; -import com.gmail.nossr50.skills.SkillManagerStore; import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.Permissions; @@ -99,7 +98,7 @@ public class InventoryListener implements Listener { } if (Permissions.fuelEfficiency(player)) { - event.setBurnTime(SkillManagerStore.getInstance().getSmeltingManager(player.getName()).fuelEfficiency(event.getBurnTime())); + event.setBurnTime(UserManager.getPlayer(player).getSmeltingManager().fuelEfficiency(event.getBurnTime())); } } } @@ -120,7 +119,7 @@ public class InventoryListener implements Listener { } if (Permissions.skillEnabled(player, SkillType.SMELTING)) { - event.setResult(SkillManagerStore.getInstance().getSmeltingManager(player.getName()).smeltProcessing(event.getSource().getType(), event.getResult())); + event.setResult(UserManager.getPlayer(player).getSmeltingManager().smeltProcessing(event.getSource().getType(), event.getResult())); } } } @@ -137,7 +136,7 @@ public class InventoryListener implements Listener { McMMOPlayer mcMMOPlayer = UserManager.getPlayer(event.getPlayer()); if (mcMMOPlayer.getPlayer().equals(plugin.getFurnacePlayer(furnaceBlock))) { - event.setExpToDrop(SkillManagerStore.getInstance().getSmeltingManager(event.getPlayer().getName()).vanillaXPBoost(event.getExpToDrop())); + event.setExpToDrop(mcMMOPlayer.getSmeltingManager().vanillaXPBoost(event.getExpToDrop())); } } } diff --git a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java index 30858a1a9..0de27e591 100644 --- a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java @@ -36,11 +36,12 @@ import com.gmail.nossr50.datatypes.skills.SkillType; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.party.ShareHandler; import com.gmail.nossr50.runnables.skills.BleedTimerTask; -import com.gmail.nossr50.skills.SkillManagerStore; import com.gmail.nossr50.skills.fishing.FishingManager; import com.gmail.nossr50.skills.herbalism.HerbalismManager; +import com.gmail.nossr50.skills.mining.MiningManager; import com.gmail.nossr50.skills.repair.Repair; import com.gmail.nossr50.skills.repair.Salvage; +import com.gmail.nossr50.skills.taming.TamingManager; import com.gmail.nossr50.util.BlockUtils; import com.gmail.nossr50.util.ChimaeraWing; import com.gmail.nossr50.util.HardcoreManager; @@ -162,7 +163,7 @@ public class PlayerListener implements Listener { return; } - FishingManager fishingManager = SkillManagerStore.getInstance().getFishingManager(player.getName()); + FishingManager fishingManager = UserManager.getPlayer(player).getFishingManager(); switch (event.getState()) { case CAUGHT_FISH: @@ -278,6 +279,8 @@ public class PlayerListener implements Listener { Block block = event.getClickedBlock(); ItemStack heldItem = player.getItemInHand(); + McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + MiningManager miningManager = mcMMOPlayer.getMiningManager(); switch (event.getAction()) { case RIGHT_CLICK_BLOCK: @@ -285,7 +288,7 @@ public class PlayerListener implements Listener { /* REPAIR CHECKS */ if (blockID == Repair.anvilID && Permissions.skillEnabled(player, SkillType.REPAIR) && mcMMO.repairManager.isRepairable(heldItem)) { - mcMMO.repairManager.handleRepair(UserManager.getPlayer(player), heldItem); + mcMMO.repairManager.handleRepair(mcMMOPlayer, heldItem); event.setCancelled(true); player.updateInventory(); } @@ -296,12 +299,12 @@ public class PlayerListener implements Listener { player.updateInventory(); } /* BLAST MINING CHECK */ - else if (SkillManagerStore.getInstance().getMiningManager(player.getName()).canDetonate()) { + else if (miningManager.canDetonate()) { if (blockID == Material.TNT.getId()) { event.setCancelled(true); // Don't detonate the TNT if they're too close } else { - SkillManagerStore.getInstance().getMiningManager(player.getName()).remoteDetonation(); + miningManager.remoteDetonation(); } } @@ -309,8 +312,8 @@ public class PlayerListener implements Listener { case RIGHT_CLICK_AIR: /* BLAST MINING CHECK */ - if (SkillManagerStore.getInstance().getMiningManager(player.getName()).canDetonate()) { - SkillManagerStore.getInstance().getMiningManager(player.getName()).remoteDetonation(); + if (miningManager.canDetonate()) { + miningManager.remoteDetonation(); } break; @@ -334,6 +337,7 @@ public class PlayerListener implements Listener { } ItemStack heldItem = player.getItemInHand(); + McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); switch (event.getAction()) { case RIGHT_CLICK_BLOCK: @@ -359,7 +363,7 @@ public class PlayerListener implements Listener { } /* GREEN THUMB CHECK */ - HerbalismManager herbalismManager = SkillManagerStore.getInstance().getHerbalismManager(player.getName()); + HerbalismManager herbalismManager = mcMMOPlayer.getHerbalismManager(); if (herbalismManager.canGreenThumbBlock(blockState)) { player.setItemInHand(new ItemStack(Material.SEEDS, heldItem.getAmount() - 1)); @@ -401,12 +405,13 @@ public class PlayerListener implements Listener { /* CALL OF THE WILD CHECKS */ if (player.isSneaking()) { Material type = heldItem.getType(); + TamingManager tamingManager = mcMMOPlayer.getTamingManager(); if (type == Material.RAW_FISH) { - SkillManagerStore.getInstance().getTamingManager(player.getName()).summonOcelot(); + tamingManager.summonOcelot(); } else if (type == Material.BONE) { - SkillManagerStore.getInstance().getTamingManager(player.getName()).summonWolf(); + tamingManager.summonWolf(); } } diff --git a/src/main/java/com/gmail/nossr50/skills/SkillManagerStore.java b/src/main/java/com/gmail/nossr50/skills/SkillManagerStore.java deleted file mode 100644 index e8dcdcf62..000000000 --- a/src/main/java/com/gmail/nossr50/skills/SkillManagerStore.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.gmail.nossr50.skills; - -import java.util.HashMap; - -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.herbalism.HerbalismManager; -import com.gmail.nossr50.skills.mining.MiningManager; -import com.gmail.nossr50.skills.smelting.SmeltingManager; -import com.gmail.nossr50.skills.swords.SwordsManager; -import com.gmail.nossr50.skills.taming.TamingManager; -import com.gmail.nossr50.skills.unarmed.UnarmedManager; -import com.gmail.nossr50.util.player.UserManager; - -public class SkillManagerStore { - private static SkillManagerStore instance; - - private HashMap acrobaticsManagers = new HashMap(); - private HashMap archeryManagers = new HashMap(); - private HashMap axeManagers = new HashMap(); - private HashMap excavationManagers = new HashMap(); - private HashMap fishingManagers = new HashMap(); - private HashMap herbalismManagers = new HashMap(); - private HashMap miningManagers = new HashMap(); - private HashMap smeltingManagers = new HashMap(); - private HashMap swordsManagers = new HashMap(); - private HashMap tamingManagers = new HashMap(); - private HashMap unarmedManagers = new HashMap(); - - public static SkillManagerStore getInstance() { - if (instance == null) { - instance = new SkillManagerStore(); - } - - return instance; - } - - public AcrobaticsManager getAcrobaticsManager(String playerName) { - if (!acrobaticsManagers.containsKey(playerName)) { - acrobaticsManagers.put(playerName, new AcrobaticsManager(UserManager.getPlayer(playerName))); - } - - return acrobaticsManagers.get(playerName); - } - - public ArcheryManager getArcheryManager(String playerName) { - if (!archeryManagers.containsKey(playerName)) { - archeryManagers.put(playerName, new ArcheryManager(UserManager.getPlayer(playerName))); - } - - return archeryManagers.get(playerName); - } - - public AxeManager getAxeManager(String playerName) { - if (!axeManagers.containsKey(playerName)) { - axeManagers.put(playerName, new AxeManager(UserManager.getPlayer(playerName))); - } - - return axeManagers.get(playerName); - } - - public ExcavationManager getExcavationManager(String playerName) { - if (!excavationManagers.containsKey(playerName)) { - excavationManagers.put(playerName, new ExcavationManager(UserManager.getPlayer(playerName))); - } - - return excavationManagers.get(playerName); - } - - public FishingManager getFishingManager(String playerName) { - if (!fishingManagers.containsKey(playerName)) { - fishingManagers.put(playerName, new FishingManager(UserManager.getPlayer(playerName))); - } - - return fishingManagers.get(playerName); - } - - public HerbalismManager getHerbalismManager(String playerName) { - if (!herbalismManagers.containsKey(playerName)) { - herbalismManagers.put(playerName, new HerbalismManager(UserManager.getPlayer(playerName))); - } - - return herbalismManagers.get(playerName); - } - - public MiningManager getMiningManager(String playerName) { - if (!miningManagers.containsKey(playerName)) { - miningManagers.put(playerName, new MiningManager(UserManager.getPlayer(playerName))); - } - - return miningManagers.get(playerName); - } - - public SmeltingManager getSmeltingManager(String playerName) { - if (!smeltingManagers.containsKey(playerName)) { - smeltingManagers.put(playerName, new SmeltingManager(UserManager.getPlayer(playerName))); - } - - return smeltingManagers.get(playerName); - } - - public SwordsManager getSwordsManager(String playerName) { - if (!swordsManagers.containsKey(playerName)) { - swordsManagers.put(playerName, new SwordsManager(UserManager.getPlayer(playerName))); - } - - return swordsManagers.get(playerName); - } - - public TamingManager getTamingManager(String playerName) { - if (!tamingManagers.containsKey(playerName)) { - tamingManagers.put(playerName, new TamingManager(UserManager.getPlayer(playerName))); - } - - return tamingManagers.get(playerName); - } - - public UnarmedManager getUnarmedManager(String playerName) { - if (!unarmedManagers.containsKey(playerName)) { - unarmedManagers.put(playerName, new UnarmedManager(UserManager.getPlayer(playerName))); - } - - return unarmedManagers.get(playerName); - } -} diff --git a/src/main/java/com/gmail/nossr50/skills/axes/AxeManager.java b/src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java similarity index 98% rename from src/main/java/com/gmail/nossr50/skills/axes/AxeManager.java rename to src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java index 98b3027ee..b322947fe 100644 --- a/src/main/java/com/gmail/nossr50/skills/axes/AxeManager.java +++ b/src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java @@ -19,8 +19,8 @@ import com.gmail.nossr50.util.skills.CombatUtils; import com.gmail.nossr50.util.skills.ParticleEffectUtils; import com.gmail.nossr50.util.skills.SkillUtils; -public class AxeManager extends SkillManager { - public AxeManager(McMMOPlayer mcMMOPlayer) { +public class AxesManager extends SkillManager { + public AxesManager(McMMOPlayer mcMMOPlayer) { super(mcMMOPlayer, SkillType.AXES); } diff --git a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java index 3826f715d..c10caf468 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java @@ -31,10 +31,14 @@ import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.party.PartyManager; import com.gmail.nossr50.runnables.skills.AwardCombatXpTask; import com.gmail.nossr50.runnables.skills.BleedTimerTask; -import com.gmail.nossr50.skills.SkillManagerStore; -import com.gmail.nossr50.skills.axes.AxeManager; +import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager; +import com.gmail.nossr50.skills.archery.ArcheryManager; +import com.gmail.nossr50.skills.axes.AxesManager; import com.gmail.nossr50.skills.swords.Swords; +import com.gmail.nossr50.skills.swords.SwordsManager; import com.gmail.nossr50.skills.taming.Taming; +import com.gmail.nossr50.skills.taming.TamingManager; +import com.gmail.nossr50.skills.unarmed.UnarmedManager; import com.gmail.nossr50.util.ItemUtils; import com.gmail.nossr50.util.Misc; import com.gmail.nossr50.util.ModUtils; @@ -56,6 +60,7 @@ public final class CombatUtils { if (attacker instanceof Player && damager.getType() == EntityType.PLAYER) { Player player = (Player) attacker; + McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); if (Misc.isNPCEntity(player)) { return; @@ -65,7 +70,7 @@ public final class CombatUtils { if (target instanceof Tameable) { if (heldItem.getType() == Material.BONE && Permissions.beastLore(player)) { - SkillManagerStore.getInstance().getTamingManager(player.getName()).beastLore(target); + mcMMOPlayer.getTamingManager().beastLore(target); event.setCancelled(true); return; } @@ -85,21 +90,21 @@ public final class CombatUtils { } if (Permissions.skillEnabled(player, SkillType.SWORDS)) { - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); PlayerProfile profile = mcMMOPlayer.getProfile(); - String playerName = player.getName(); boolean canSerratedStrike = Permissions.serratedStrikes(player); // So we don't have to check the same permission twice if (profile.getToolPreparationMode(ToolType.SWORD) && canSerratedStrike) { SkillUtils.abilityCheck(player, SkillType.SWORDS); } + SwordsManager swordsManager = mcMMOPlayer.getSwordsManager(); + if (Permissions.bleed(player)) { - SkillManagerStore.getInstance().getSwordsManager(playerName).bleedCheck(target); + swordsManager.bleedCheck(target); } if (profile.getAbilityMode(AbilityType.SERRATED_STRIKES) && canSerratedStrike) { - SkillManagerStore.getInstance().getSwordsManager(playerName).serratedStrikes(target, event.getDamage()); + swordsManager.serratedStrikes(target, event.getDamage()); } startGainXp(mcMMOPlayer, target, SkillType.SWORDS); @@ -111,32 +116,32 @@ public final class CombatUtils { } if (Permissions.skillEnabled(player, SkillType.AXES)) { - AxeManager axeManager = SkillManagerStore.getInstance().getAxeManager(player.getName()); + AxesManager axesManager = mcMMOPlayer.getAxesManager(); - if (axeManager.canActivateAbility()) { + if (axesManager.canActivateAbility()) { SkillUtils.abilityCheck(player, SkillType.AXES); } - if (axeManager.canUseAxeMastery()) { - event.setDamage(axeManager.axeMasteryCheck(event.getDamage())); + if (axesManager.canUseAxeMastery()) { + event.setDamage(axesManager.axeMasteryCheck(event.getDamage())); } - if (axeManager.canCriticalHit(target)) { - event.setDamage(axeManager.criticalHitCheck(target, event.getDamage())); + if (axesManager.canCriticalHit(target)) { + event.setDamage(axesManager.criticalHitCheck(target, event.getDamage())); } - if (axeManager.canImpact(target)) { - axeManager.impactCheck(target); + if (axesManager.canImpact(target)) { + axesManager.impactCheck(target); } - else if (axeManager.canGreaterImpact(target)) { - event.setDamage(axeManager.greaterImpactCheck(target, event.getDamage())); + else if (axesManager.canGreaterImpact(target)) { + event.setDamage(axesManager.greaterImpactCheck(target, event.getDamage())); } - if (axeManager.canUseSkullSplitter(target)) { - axeManager.skullSplitterCheck(target, event.getDamage()); + if (axesManager.canUseSkullSplitter(target)) { + axesManager.skullSplitterCheck(target, event.getDamage()); } - startGainXp(axeManager.getMcMMOPlayer(), target, SkillType.AXES); + startGainXp(axesManager.getMcMMOPlayer(), target, SkillType.AXES); } } else if (heldItem.getType() == Material.AIR) { @@ -150,9 +155,7 @@ public final class CombatUtils { } if (Permissions.skillEnabled(player, SkillType.UNARMED)) { - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); PlayerProfile profile = mcMMOPlayer.getProfile(); - String playerName = player.getName(); boolean canBerserk = Permissions.berserk(player); // So we don't have to check the same permission twice @@ -160,19 +163,21 @@ public final class CombatUtils { SkillUtils.abilityCheck(player, SkillType.UNARMED); } + UnarmedManager unarmedManager = mcMMOPlayer.getUnarmedManager(); + if (Permissions.bonusDamage(player, SkillType.UNARMED)) { - event.setDamage(SkillManagerStore.getInstance().getUnarmedManager(playerName).ironArmCheck(event.getDamage())); + event.setDamage(unarmedManager.ironArmCheck(event.getDamage())); } if (profile.getAbilityMode(AbilityType.BERSERK) && canBerserk) { - event.setDamage(SkillManagerStore.getInstance().getUnarmedManager(playerName).berserkDamage(event.getDamage())); + event.setDamage(unarmedManager.berserkDamage(event.getDamage())); } if (target instanceof Player && Permissions.disarm(player)) { Player defender = (Player) target; if (defender.getItemInHand().getType() != Material.AIR) { - SkillManagerStore.getInstance().getUnarmedManager(playerName).disarmCheck((Player) target); + unarmedManager.disarmCheck((Player) target); } } @@ -203,18 +208,19 @@ public final class CombatUtils { if (Permissions.skillEnabled(master, SkillType.TAMING)) { McMMOPlayer mcMMOPlayer = UserManager.getPlayer(master); - int skillLevel = SkillManagerStore.getInstance().getTamingManager(master.getName()).getSkillLevel(); + TamingManager tamingManager = mcMMOPlayer.getTamingManager(); + int skillLevel = tamingManager.getSkillLevel(); if (skillLevel >= Taming.fastFoodServiceUnlockLevel && Permissions.fastFoodService(master)) { - SkillManagerStore.getInstance().getTamingManager(master.getName()).fastFoodService(wolf, event.getDamage()); + tamingManager.fastFoodService(wolf, event.getDamage()); } if (skillLevel >= Taming.sharpenedClawsUnlockLevel && Permissions.sharpenedClaws(master)) { - SkillManagerStore.getInstance().getTamingManager(master.getName()).sharpenedClaws(event); + tamingManager.sharpenedClaws(event); } if (Permissions.gore(master)) { - SkillManagerStore.getInstance().getTamingManager(master.getName()).gore(event); + tamingManager.gore(event); } startGainXp(mcMMOPlayer, target, SkillType.TAMING); @@ -254,20 +260,23 @@ public final class CombatUtils { return; } - ItemStack heldItem = player.getItemInHand(); + McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + AcrobaticsManager acrobaticsManager = mcMMOPlayer.getAcrobaticsManager(); - if (SkillManagerStore.getInstance().getAcrobaticsManager(player.getName()).canDodge(damager)) { - event.setDamage(SkillManagerStore.getInstance().getAcrobaticsManager(player.getName()).dodgeCheck(event.getDamage())); + if (acrobaticsManager.canDodge(damager)) { + event.setDamage(acrobaticsManager.dodgeCheck(event.getDamage())); } + ItemStack heldItem = player.getItemInHand(); + if (damager instanceof Player) { if (SkillType.SWORDS.getPVPEnabled() && ItemUtils.isSword(heldItem) && Permissions.counterAttack(player)) { - SkillManagerStore.getInstance().getSwordsManager(player.getName()).counterAttackChecks((LivingEntity) damager, event.getDamage()); + mcMMOPlayer.getSwordsManager().counterAttackChecks((LivingEntity) damager, event.getDamage()); } } else { if (SkillType.SWORDS.getPVEEnabled() && damager instanceof LivingEntity && ItemUtils.isSword(heldItem) && Permissions.counterAttack(player)) { - SkillManagerStore.getInstance().getSwordsManager(player.getName()).counterAttackChecks((LivingEntity) damager, event.getDamage()); + mcMMOPlayer.getSwordsManager().counterAttackChecks((LivingEntity) damager, event.getDamage()); } } } @@ -286,29 +295,30 @@ public final class CombatUtils { } if (Permissions.skillEnabled(shooter, SkillType.ARCHERY)) { - String playerName = shooter.getName(); + McMMOPlayer mcMMOPlayer = UserManager.getPlayer(shooter); + ArcheryManager archeryManager = mcMMOPlayer.getArcheryManager(); - if (SkillManagerStore.getInstance().getArcheryManager(playerName).canSkillShot()) { - event.setDamage(SkillManagerStore.getInstance().getArcheryManager(playerName).skillShotCheck(event.getDamage())); + if (archeryManager.canSkillShot()) { + event.setDamage(archeryManager.skillShotCheck(event.getDamage())); } if (target instanceof Player && SkillType.UNARMED.getPVPEnabled() && ((Player) target).getItemInHand().getType() == Material.AIR && Permissions.arrowDeflect((Player) target)) { - event.setCancelled(SkillManagerStore.getInstance().getUnarmedManager(((Player) target).getName()).deflectCheck()); + event.setCancelled(mcMMOPlayer.getUnarmedManager().deflectCheck()); if (event.isCancelled()) { return; } } - if (SkillManagerStore.getInstance().getArcheryManager(playerName).canDaze(target)) { - event.setDamage(SkillManagerStore.getInstance().getArcheryManager(playerName).dazeCheck((Player) target, event.getDamage())); + if (archeryManager.canDaze(target)) { + event.setDamage(archeryManager.dazeCheck((Player) target, event.getDamage())); } - if (SkillManagerStore.getInstance().getArcheryManager(playerName).canTrackArrows()) { - SkillManagerStore.getInstance().getArcheryManager(playerName).trackArrows(target); + if (archeryManager.canTrackArrows()) { + archeryManager.trackArrows(target); } - SkillManagerStore.getInstance().getArcheryManager(playerName).distanceXpBonus(target); + archeryManager.distanceXpBonus(target); startGainXp(UserManager.getPlayer(shooter), target, SkillType.ARCHERY); } }