| 
					
				 | 
			
			
				@@ -46,6 +46,18 @@ import static com.gmail.nossr50.util.ItemUtils.removeItemIncludingOffHand; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import static java.util.Objects.requireNonNull; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 public class HerbalismManager extends SkillManager { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final static HashMap<String, Integer> plantBreakLimits; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    static { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        plantBreakLimits = new HashMap<>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        plantBreakLimits.put("cactus", 3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        plantBreakLimits.put("bamboo", 20); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        plantBreakLimits.put("sugar_cane", 3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        plantBreakLimits.put("kelp", 26); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        plantBreakLimits.put("kelp_plant", 26); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        plantBreakLimits.put("chorus_plant", 22); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public HerbalismManager(McMMOPlayer mcMMOPlayer) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         super(mcMMOPlayer, PrimarySkillType.HERBALISM); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -408,6 +420,7 @@ public class HerbalismManager extends SkillManager { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public void awardXPForPlantBlocks(HashSet<Block> brokenPlants) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         int xpToReward = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        int firstXpReward = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         for(Block brokenPlantBlock : brokenPlants) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             BlockState brokenBlockNewState = brokenPlantBlock.getState(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -424,6 +437,8 @@ public class HerbalismManager extends SkillManager { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 //If its a Crop we need to reward XP when its fully grown 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (isAgeableAndFullyMature(plantData) && !isBizarreAgeable(plantData)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     xpToReward += ExperienceConfig.getInstance().getXp(PrimarySkillType.HERBALISM, brokenBlockNewState.getType()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (firstXpReward == -1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        firstXpReward = xpToReward; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 //Mark it as natural again as it is being broken 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -441,10 +456,14 @@ public class HerbalismManager extends SkillManager { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (isAgeableMature(plantAgeable) || isBizarreAgeable(plantData)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         xpToReward += ExperienceConfig.getInstance().getXp(PrimarySkillType.HERBALISM, brokenBlockNewState.getType()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (firstXpReward == -1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            firstXpReward = xpToReward; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     xpToReward += ExperienceConfig.getInstance().getXp(PrimarySkillType.HERBALISM, brokenPlantBlock.getType()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (firstXpReward == -1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        firstXpReward = xpToReward; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -455,10 +474,31 @@ public class HerbalismManager extends SkillManager { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //Reward XP 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (xpToReward > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            applyXpGain(xpToReward, XPGainReason.PVE, XPGainSource.SELF); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // get first block from hash set using stream API 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            final Block firstBlock = brokenPlants.stream().findFirst().orElse(null); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (firstBlock != null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    && firstXpReward != -1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    && ExperienceConfig.getInstance().limitXPOnTallPlants() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    && plantBreakLimits.containsKey(firstBlock.getType().getKey().getKey())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                int limit = plantBreakLimits.get(firstBlock.getType().getKey().getKey()) * firstXpReward; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Plant may be unnaturally tall, limit XP 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                applyXpGain(Math.min(xpToReward, limit), XPGainReason.PVE, XPGainSource.SELF); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                applyXpGain(xpToReward, XPGainReason.PVE, XPGainSource.SELF); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private int getNaturalGrowthLimit(Material brokenPlant) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // This is an exploit counter-measure to prevent players from growing unnaturally tall plants and reaping XP 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (plantBreakLimits.containsKey(brokenPlant.getKey().getKey())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return plantBreakLimits.get(brokenPlant.getKey().getKey()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     public boolean isAgeableMature(Ageable ageable) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return ageable.getAge() == ageable.getMaximumAge() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 && ageable.getAge() != 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -572,7 +612,8 @@ public class HerbalismManager extends SkillManager { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (isChorusBranch(brokenBlock.getType())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             brokenBlocks = getBrokenChorusBlocks(brokenBlock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            brokenBlocks = getBlocksBrokenAboveOrBelow(brokenBlock, false, mcMMO.getMaterialMapStore().isMultiBlockHangingPlant(brokenBlock.getType())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            brokenBlocks = getBlocksBrokenAboveOrBelow( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    brokenBlock, false, mcMMO.getMaterialMapStore().isMultiBlockHangingPlant(brokenBlock.getType())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return brokenBlocks; 
			 |