support for various new additions from 1.21.5

This commit is contained in:
nossr50 2025-04-12 13:23:35 -07:00
parent 35785283ee
commit 5b67aa04c4
5 changed files with 88 additions and 103 deletions

View File

@ -1,9 +1,25 @@
Version 2.2.035 Version 2.2.035
Support for new additions from Minecraft 1.21.5
Added 'Bush' to experience.yml for Herbalism
Added 'Bush' to config.yml Bonus Drops for Herbalism
Added 'Cactus_Flower' to experience.yml for Herbalism
Added 'Cactus_Flower' to config.yml Bonus Drops for Herbalism
Added 'Firefly_Bush' to experience.yml for Herbalism
Added 'Firefly_Bush' to config.yml Bonus Drops for Herbalism
Added 'Leaf_Litter' to experience.yml for Herbalism
Added 'Leaf_Litter' to config.yml Bonus Drops for Herbalism
Added 'Short_Dry_Grass' to experience.yml for Herbalism
Added 'Short_Dry_Grass' to config.yml Bonus Drops for Herbalism
Added 'Tall_Dry_Grass' to experience.yml for Herbalism
Added 'Tall_Dry_Grass' to config.yml Bonus Drops for Herbalism
Added 'Wildflowers' to experience.yml for Herbalism
Added 'Wildflowers' to config.yml Bonus Drops for Herbalism
Swords subskill Stab is now configurable in advanced.yml Swords subskill Stab is now configurable in advanced.yml
Added 'Skills.Swords.Stab.Base_Damage' to advanced.yml Added 'Skills.Swords.Stab.Base_Damage' to advanced.yml
Added 'Skills.Swords.Stab.Per_Rank_Multiplier' to advanced.yml Added 'Skills.Swords.Stab.Per_Rank_Multiplier' to advanced.yml
NOTES: NOTES:
The mob variants will use the "base" mob definition for values for now, such a a warm chicken using chicken values from experience.yml
The new config settings will be added automatically to advanced.yml The new config settings will be added automatically to advanced.yml
Version 2.2.034 Version 2.2.034

View File

@ -50,9 +50,12 @@ import static java.util.Objects.requireNonNull;
public class HerbalismManager extends SkillManager { public class HerbalismManager extends SkillManager {
private final static HashMap<String, Integer> plantBreakLimits; private final static HashMap<String, Integer> plantBreakLimits;
private static final String CACTUS_STR = "cactus";
private static final String CACTUS_FLOWER_STR = "cactus_flower";
static { static {
plantBreakLimits = new HashMap<>(); plantBreakLimits = new HashMap<>();
plantBreakLimits.put("cactus", 3); plantBreakLimits.put(CACTUS_STR, 3);
plantBreakLimits.put("bamboo", 20); plantBreakLimits.put("bamboo", 20);
plantBreakLimits.put("sugar_cane", 3); plantBreakLimits.put("sugar_cane", 3);
plantBreakLimits.put("kelp", 26); plantBreakLimits.put("kelp", 26);
@ -68,10 +71,13 @@ public class HerbalismManager extends SkillManager {
if (!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.HERBALISM_GREEN_THUMB)) if (!RankUtils.hasUnlockedSubskill(getPlayer(), SubSkillType.HERBALISM_GREEN_THUMB))
return false; return false;
Player player = getPlayer(); final Player player = getPlayer();
ItemStack item = player.getInventory().getItemInMainHand(); final ItemStack item = player.getInventory().getItemInMainHand();
return item.getAmount() > 0 && item.getType() == Material.WHEAT_SEEDS && BlockUtils.canMakeMossy(blockState) && Permissions.greenThumbBlock(player, blockState.getType()); return item.getAmount() > 0
&& item.getType() == Material.WHEAT_SEEDS
&& BlockUtils.canMakeMossy(blockState.getBlock())
&& Permissions.greenThumbBlock(player, blockState.getType());
} }
public boolean canUseShroomThumb(BlockState blockState) { public boolean canUseShroomThumb(BlockState blockState) {
@ -163,10 +169,6 @@ public class HerbalismManager extends SkillManager {
return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.HERBALISM_HYLIAN_LUCK); return Permissions.isSubSkillEnabled(getPlayer(), SubSkillType.HERBALISM_HYLIAN_LUCK);
} }
public boolean canGreenTerraBlock(BlockState blockState) {
return mmoPlayer.getAbilityMode(SuperAbilityType.GREEN_TERRA) && BlockUtils.canMakeMossy(blockState);
}
public boolean canActivateAbility() { public boolean canActivateAbility() {
return mmoPlayer.getToolPreparationMode(ToolType.HOE) && Permissions.greenTerra(getPlayer()); return mmoPlayer.getToolPreparationMode(ToolType.HOE) && Permissions.greenTerra(getPlayer());
} }
@ -222,9 +224,9 @@ public class HerbalismManager extends SkillManager {
* @param blockBreakEvent The Block Break Event to process * @param blockBreakEvent The Block Break Event to process
*/ */
public void processHerbalismBlockBreakEvent(BlockBreakEvent blockBreakEvent) { public void processHerbalismBlockBreakEvent(BlockBreakEvent blockBreakEvent) {
Player player = getPlayer(); final Player player = getPlayer();
Block block = blockBreakEvent.getBlock(); final Block block = blockBreakEvent.getBlock();
if (mcMMO.p.getGeneralConfig().getHerbalismPreventAFK() && player.isInsideVehicle()) { if (mcMMO.p.getGeneralConfig().getHerbalismPreventAFK() && player.isInsideVehicle()) {
if (block.hasMetadata(MetadataConstants.METADATA_KEY_REPLANT)) { if (block.hasMetadata(MetadataConstants.METADATA_KEY_REPLANT)) {
@ -235,7 +237,7 @@ public class HerbalismManager extends SkillManager {
//Check if the plant was recently replanted //Check if the plant was recently replanted
if (block.getBlockData() instanceof Ageable ageableCrop) { if (block.getBlockData() instanceof Ageable ageableCrop) {
if (block.getMetadata(MetadataConstants.METADATA_KEY_REPLANT).size() >= 1) { if (!block.getMetadata(MetadataConstants.METADATA_KEY_REPLANT).isEmpty()) {
if (block.getMetadata(MetadataConstants.METADATA_KEY_REPLANT).get(0).asBoolean()) { if (block.getMetadata(MetadataConstants.METADATA_KEY_REPLANT).get(0).asBoolean()) {
if (isAgeableMature(ageableCrop)) { if (isAgeableMature(ageableCrop)) {
block.removeMetadata(MetadataConstants.METADATA_KEY_REPLANT, mcMMO.p); block.removeMetadata(MetadataConstants.METADATA_KEY_REPLANT, mcMMO.p);
@ -254,9 +256,9 @@ public class HerbalismManager extends SkillManager {
*/ */
//Grab all broken blocks //Grab all broken blocks
HashSet<Block> brokenBlocks = getBrokenHerbalismBlocks(blockBreakEvent); final HashSet<Block> brokenBlocks = getBrokenHerbalismBlocks(blockBreakEvent);
if (brokenBlocks.size() == 0) if (brokenBlocks.isEmpty())
return; return;
//Handle rewards, xp, ability interactions, etc //Handle rewards, xp, ability interactions, etc
@ -272,7 +274,8 @@ public class HerbalismManager extends SkillManager {
if (blockBreakEvent.isCancelled()) if (blockBreakEvent.isCancelled())
return; return;
BlockState originalBreak = blockBreakEvent.getBlock().getState(); final BlockState originalBreak = blockBreakEvent.getBlock().getState();
// TODO: Storing this boolean for no reason, refactor
boolean greenThumbActivated = false; boolean greenThumbActivated = false;
//TODO: The design of Green Terra needs to change, this is a mess //TODO: The design of Green Terra needs to change, this is a mess
@ -322,12 +325,12 @@ public class HerbalismManager extends SkillManager {
} }
//Give out XP to the non-chorus blocks //Give out XP to the non-chorus blocks
if (noDelayPlantBlocks.size() > 0) { if (!noDelayPlantBlocks.isEmpty()) {
//Note: Will contain 1 chorus block if the original block was a chorus block, this is to prevent delays for the XP bar //Note: Will contain 1 chorus block if the original block was a chorus block, this is to prevent delays for the XP bar
awardXPForPlantBlocks(noDelayPlantBlocks); awardXPForPlantBlocks(noDelayPlantBlocks);
} }
if (delayedChorusBlocks.size() > 0) { if (!delayedChorusBlocks.isEmpty()) {
//Check XP for chorus blocks //Check XP for chorus blocks
DelayedHerbalismXPCheckTask delayedHerbalismXPCheckTask = new DelayedHerbalismXPCheckTask(mmoPlayer, delayedChorusBlocks); DelayedHerbalismXPCheckTask delayedHerbalismXPCheckTask = new DelayedHerbalismXPCheckTask(mmoPlayer, delayedChorusBlocks);
@ -356,15 +359,9 @@ public class HerbalismManager extends SkillManager {
//Check for double drops //Check for double drops
if (!mcMMO.getUserBlockTracker().isIneligible(brokenPlant)) { if (!mcMMO.getUserBlockTracker().isIneligible(brokenPlant)) {
/* /*
*
* Natural Blocks * Natural Blocks
*
*
*
*/ */
//Not all things that are natural should give double drops, make sure its fully mature as well //Not all things that are natural should give double drops, make sure its fully mature as well
if (plantData instanceof Ageable ageable) { if (plantData instanceof Ageable ageable) {
@ -378,13 +375,9 @@ public class HerbalismManager extends SkillManager {
markForBonusDrops(brokenPlant); markForBonusDrops(brokenPlant);
} }
} else { } else {
/* /*
*
* Unnatural Blocks * Unnatural Blocks
*
*/ */
//If it's a crop, we need to reward XP when its fully grown //If it's a crop, we need to reward XP when its fully grown
if (isAgeableAndFullyMature(plantData) && !isBizarreAgeable(plantData)) { if (isAgeableAndFullyMature(plantData) && !isBizarreAgeable(plantData)) {
//Add metadata to mark this block for double or triple drops //Add metadata to mark this block for double or triple drops
@ -401,7 +394,7 @@ public class HerbalismManager extends SkillManager {
*/ */
public boolean isBizarreAgeable(BlockData blockData) { public boolean isBizarreAgeable(BlockData blockData) {
if (blockData instanceof Ageable) { if (blockData instanceof Ageable) {
//Catcus and Sugar Canes cannot be trusted // Cactus and Sugar Canes cannot be trusted
return switch (blockData.getMaterial()) { return switch (blockData.getMaterial()) {
case CACTUS, KELP, SUGAR_CANE, BAMBOO -> true; case CACTUS, KELP, SUGAR_CANE, BAMBOO -> true;
default -> false; default -> false;
@ -440,12 +433,8 @@ public class HerbalismManager extends SkillManager {
if (mcMMO.getUserBlockTracker().isIneligible(brokenBlockNewState)) { if (mcMMO.getUserBlockTracker().isIneligible(brokenBlockNewState)) {
/* /*
*
* Unnatural Blocks * Unnatural Blocks
*
*
*/ */
//If its a Crop we need to reward XP when its fully grown //If its a Crop we need to reward XP when its fully grown
if (isAgeableAndFullyMature(plantData) && !isBizarreAgeable(plantData)) { if (isAgeableAndFullyMature(plantData) && !isBizarreAgeable(plantData)) {
xpToReward += ExperienceConfig.getInstance().getXp(PrimarySkillType.HERBALISM, brokenBlockNewState.getType()); xpToReward += ExperienceConfig.getInstance().getXp(PrimarySkillType.HERBALISM, brokenBlockNewState.getType());
@ -457,13 +446,9 @@ public class HerbalismManager extends SkillManager {
mcMMO.getUserBlockTracker().setEligible(brokenBlockNewState); mcMMO.getUserBlockTracker().setEligible(brokenBlockNewState);
} else { } else {
/* /*
*
* Natural Blocks * Natural Blocks
*
*
*/ */
// Calculate XP
//Calculate XP
if (plantData instanceof Ageable plantAgeable) { if (plantData instanceof Ageable plantAgeable) {
if (isAgeableMature(plantAgeable) || isBizarreAgeable(plantData)) { if (isAgeableMature(plantAgeable) || isBizarreAgeable(plantData)) {
@ -481,7 +466,7 @@ public class HerbalismManager extends SkillManager {
} }
if (mmoPlayer.isDebugMode()) { if (mmoPlayer.isDebugMode()) {
mmoPlayer.getPlayer().sendMessage("Plants processed: "+brokenPlants.size()); mmoPlayer.getPlayer().sendMessage("Plants processed: " + brokenPlants.size());
} }
//Reward XP //Reward XP
@ -489,7 +474,6 @@ public class HerbalismManager extends SkillManager {
// get first block from hash set using stream API // get first block from hash set using stream API
final Block firstBlock = brokenPlants.stream().findFirst().orElse(null); final Block firstBlock = brokenPlants.stream().findFirst().orElse(null);
if (firstBlock != null if (firstBlock != null
&& firstXpReward != -1
&& ExperienceConfig.getInstance().limitXPOnTallPlants() && ExperienceConfig.getInstance().limitXPOnTallPlants()
&& plantBreakLimits.containsKey(firstBlock.getType().getKey().getKey())) { && plantBreakLimits.containsKey(firstBlock.getType().getKey().getKey())) {
int limit = plantBreakLimits.get(firstBlock.getType().getKey().getKey()) * firstXpReward; int limit = plantBreakLimits.get(firstBlock.getType().getKey().getKey()) * firstXpReward;
@ -501,16 +485,6 @@ public class HerbalismManager extends SkillManager {
} }
} }
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) { public boolean isAgeableMature(Ageable ageable) {
return ageable.getAge() == ageable.getMaximumAge() return ageable.getAge() == ageable.getMaximumAge()
&& ageable.getAge() != 0; && ageable.getAge() != 0;
@ -529,7 +503,7 @@ public class HerbalismManager extends SkillManager {
int blocksGivingXP = 0; int blocksGivingXP = 0;
for(BlockSnapshot blockSnapshot : brokenPlants) { for(BlockSnapshot blockSnapshot : brokenPlants) {
BlockState brokenBlockNewState = blockSnapshot.getBlockRef().getState(); final BlockState brokenBlockNewState = blockSnapshot.getBlockRef().getState();
//Remove metadata from the snapshot of blocks //Remove metadata from the snapshot of blocks
if (brokenBlockNewState.hasMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS)) { if (brokenBlockNewState.hasMetadata(MetadataConstants.METADATA_KEY_BONUS_DROPS)) {
@ -570,65 +544,66 @@ public class HerbalismManager extends SkillManager {
*/ */
private HashSet<Block> getBrokenHerbalismBlocks(@NotNull BlockBreakEvent blockBreakEvent) { private HashSet<Block> getBrokenHerbalismBlocks(@NotNull BlockBreakEvent blockBreakEvent) {
//Get an updated capture of this block //Get an updated capture of this block
BlockState originBlockState = blockBreakEvent.getBlock().getState(); final BlockState originBlockState = blockBreakEvent.getBlock().getState();
Material originBlockMaterial = originBlockState.getType(); final Material originBlockMaterial = originBlockState.getType();
HashSet<Block> blocksBroken = new HashSet<>(); //Blocks broken final HashSet<Block> blocksBroken = new HashSet<>(); //Blocks broken
//Add the initial block //Add the initial block
blocksBroken.add(originBlockState.getBlock()); blocksBroken.add(originBlockState.getBlock());
if (!isOneBlockPlant(originBlockMaterial)) { if (!isOneBlockPlant(originBlockMaterial)) {
//If the block is a multi-block structure, capture a set of all blocks broken and return that //If the block is a multi-block structure, capture a set of all blocks broken and return that
blocksBroken = getBrokenBlocksMultiBlockPlants(originBlockState); addBrokenBlocksMultiBlockPlants(originBlockState, blocksBroken);
} }
//Return all broken plant-blocks //Return all broken plant-blocks
return blocksBroken; return blocksBroken;
} }
private HashSet<Block> getBrokenChorusBlocks(BlockState originalBreak) { private void addChorusTreeBrokenBlocks(Block currentBlock, Set<Block> traversed) {
return grabChorusTreeBrokenBlocksRecursive(originalBreak.getBlock(), new HashSet<>());
}
private HashSet<Block> grabChorusTreeBrokenBlocksRecursive(Block currentBlock, HashSet<Block> traversed) {
if (!isChorusTree(currentBlock.getType())) if (!isChorusTree(currentBlock.getType()))
return traversed; return;
// Prevent any infinite loops, who needs more than 256 chorus anyways // Prevent any infinite loops, who needs more than 256 chorus anyways
if (traversed.size() > 256) if (traversed.size() > 256)
return traversed; return;
if (!traversed.add(currentBlock)) if (!traversed.add(currentBlock))
return traversed; return;
//Grab all Blocks in the Tree //Grab all Blocks in the Tree
for (BlockFace blockFace : new BlockFace[] { BlockFace.UP, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST ,BlockFace.WEST}) for (BlockFace blockFace : new BlockFace[] { BlockFace.UP, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST ,BlockFace.WEST})
grabChorusTreeBrokenBlocksRecursive(currentBlock.getRelative(blockFace, 1), traversed); addChorusTreeBrokenBlocks(currentBlock.getRelative(blockFace, 1), traversed);
traversed.add(currentBlock);
return traversed;
} }
/**
* Grab a set of all plant blocks that are broken as a result of this event
* The method to grab these blocks is a bit hacky and does not hook into the API
* Basically we expect the blocks to be broken if this event is not cancelled and we determine which block are broken on our end rather than any event state captures
*
* @return a set of plant-blocks broken from this event
*/
protected HashSet<Block> getBrokenBlocksMultiBlockPlants(BlockState brokenBlock) {
//Track the broken blocks
HashSet<Block> brokenBlocks;
protected void addBrokenBlocksMultiBlockPlants(BlockState brokenBlock, Set<Block> brokenBlocks) {
if (isChorusBranch(brokenBlock.getType())) { if (isChorusBranch(brokenBlock.getType())) {
brokenBlocks = getBrokenChorusBlocks(brokenBlock); addChorusTreeBrokenBlocks(brokenBlock.getBlock(), brokenBlocks);
} else if (isCactus(brokenBlock.getType())) {
addCactusBlocks(brokenBlock.getBlock(), brokenBlocks);
} else { } else {
brokenBlocks = getBlocksBrokenAboveOrBelow( addBlocksBrokenAboveOrBelow(brokenBlock.getBlock(), brokenBlocks, mcMMO.getMaterialMapStore().isMultiBlockHangingPlant(brokenBlock.getType()));
brokenBlock, false, mcMMO.getMaterialMapStore().isMultiBlockHangingPlant(brokenBlock.getType())); }
} }
return brokenBlocks; private void addCactusBlocks(Block currentBlock, Set<Block> traversed) {
if (!isCactus(currentBlock.getType()))
return;
if (traversed.size() > 4) // Max size 3 cactus + flower
return;
if (!traversed.add(currentBlock))
return;
addCactusBlocks(currentBlock.getRelative(BlockFace.UP), traversed);
addCactusBlocks(currentBlock.getRelative(BlockFace.DOWN), traversed);
}
private boolean isCactus(Material material) {
return material.getKey().getKey().equalsIgnoreCase(CACTUS_STR)
|| material.getKey().getKey().equalsIgnoreCase(CACTUS_FLOWER_STR);
} }
private boolean isChorusBranch(Material blockType) { private boolean isChorusBranch(Material blockType) {
@ -639,25 +614,7 @@ public class HerbalismManager extends SkillManager {
return blockType == Material.CHORUS_PLANT || blockType == Material.CHORUS_FLOWER; return blockType == Material.CHORUS_PLANT || blockType == Material.CHORUS_FLOWER;
} }
/** private void addBlocksBrokenAboveOrBelow(Block originBlock, Set<Block> brokenBlocks, boolean below) {
* Grabs blocks upwards from a target block
* A lot of Plants/Crops in Herbalism only break vertically from a broken block
* The vertical search returns early if it runs into anything that is not a multi-block plant
* Multi-block plants are hard-coded and kept in {@link MaterialMapStore}
*
* @param originBlock The point of the "break"
* @param inclusive Whether to include the origin block
* @param below Whether to search down instead of up.
* @return A set of blocks above the target block which can be assumed to be broken
*/
private HashSet<Block> getBlocksBrokenAboveOrBelow(BlockState originBlock, boolean inclusive, boolean below) {
HashSet<Block> brokenBlocks = new HashSet<>();
Block block = originBlock.getBlock();
//Add the initial block to the set
if (inclusive)
brokenBlocks.add(block);
//Limit our search //Limit our search
int maxHeight = 512; int maxHeight = 512;
@ -665,8 +622,7 @@ public class HerbalismManager extends SkillManager {
// Search vertically for multi-block plants, exit early if any non-multi block plants // Search vertically for multi-block plants, exit early if any non-multi block plants
for (int y = 0; y < maxHeight; y++) { for (int y = 0; y < maxHeight; y++) {
//TODO: Should this grab state? It would be more expensive.. final Block relativeBlock = originBlock.getRelative(relativeFace, y);
Block relativeBlock = block.getRelative(relativeFace, y);
//Abandon our search if the block isn't multi //Abandon our search if the block isn't multi
if (isOneBlockPlant(relativeBlock.getType())) if (isOneBlockPlant(relativeBlock.getType()))
@ -674,8 +630,6 @@ public class HerbalismManager extends SkillManager {
brokenBlocks.add(relativeBlock); brokenBlocks.add(relativeBlock);
} }
return brokenBlocks;
} }
/** /**

View File

@ -1003,6 +1003,7 @@ public class MaterialMapStore {
private void fillMultiBlockPlantSet() { private void fillMultiBlockPlantSet() {
//Multi-Block Plants //Multi-Block Plants
multiBlockPlant.add("cactus"); multiBlockPlant.add("cactus");
multiBlockPlant.add("cactus_flower");
multiBlockPlant.add("chorus_plant"); multiBlockPlant.add("chorus_plant");
multiBlockPlant.add("chorus_flower"); multiBlockPlant.add("chorus_flower");
multiBlockPlant.add("sugar_cane"); multiBlockPlant.add("sugar_cane");

View File

@ -483,6 +483,13 @@ Green_Thumb_Replanting_Crops:
### ###
Bonus_Drops: Bonus_Drops:
Herbalism: Herbalism:
Bush: true
Cactus_Flower: true
Firefly_Bush: true
Leaf_Litter: true
Short_Dry_Grass: true
Tall_Dry_Grass: true
Wildflowers: true
Eyeblossom: true Eyeblossom: true
Open_Eyeblossom: true Open_Eyeblossom: true
Closed_Eyeblossom: true Closed_Eyeblossom: true

View File

@ -330,6 +330,13 @@ Experience_Values:
Brown_Mushroom_Block: 70 Brown_Mushroom_Block: 70
Mushroom_Stem: 80 Mushroom_Stem: 80
Herbalism: Herbalism:
Bush: 11
Cactus_Flower: 60
Firefly_Bush: 15
Leaf_Litter: 2
Short_Dry_Grass: 6
Tall_Dry_Grass: 12
Wildflowers: 15
Eyeblossom: 66 Eyeblossom: 66
Open_Eyeblossom: 66 Open_Eyeblossom: 66
Closed_Eyeblossom: 66 Closed_Eyeblossom: 66