Upstream Paper's upgrade to vineflower 12.0.0 (#1782)

This commit is contained in:
granny
2026-05-31 16:42:41 -07:00
committed by GitHub
parent dc4a255969
commit 3fe5edd4b5
116 changed files with 1321 additions and 1333 deletions

View File

@@ -64,7 +64,7 @@
this.generator = generator;
this.world = new CraftWorld((ServerLevel) this, worldKey, biomeProvider, environment);
@@ -2194,4 +_,14 @@
@@ -2197,4 +_,14 @@
return this.moonrise$getEntityLookup().getEntityCount(); // Paper - rewrite chunk system
}
// Paper end - allow patching this logic

View File

@@ -7,4 +7,4 @@
+ if (!((net.minecraft.world.level.LevelAccessor) level).getMinecraftWorld().purpurConfig.coralDieOutsideWater) return true; // Purpur - Config to not let coral die
if (state.getValue(WATERLOGGED)) {
return true;
} else {
}

View File

@@ -1,11 +1,11 @@
--- a/net/minecraft/world/level/block/BaseFireBlock.java
+++ b/net/minecraft/world/level/block/BaseFireBlock.java
@@ -215,7 +_,7 @@
boolean hasObsidian = false;
@@ -216,7 +_,7 @@
boolean hasObsidian = false;
for (Direction face : Direction.values()) {
- if (level.getBlockState(testPos.set(pos).move(face)).is(Blocks.OBSIDIAN)) {
+ if (PortalShape.FRAME.test(level.getBlockState(testPos.set(pos).move(face)), level, testPos)) { // Purpur - Crying obsidian valid for portal frames
hasObsidian = true;
break;
}
for (Direction face : Direction.values()) {
- if (level.getBlockState(testPos.set(pos).move(face)).is(Blocks.OBSIDIAN)) {
+ if (PortalShape.FRAME.test(level.getBlockState(testPos.set(pos).move(face)), level, testPos)) { // Purpur - Crying obsidian valid for portal frames
hasObsidian = true;
break;
}

View File

@@ -1,20 +1,20 @@
--- a/net/minecraft/world/level/block/BedBlock.java
+++ b/net/minecraft/world/level/block/BedBlock.java
@@ -100,7 +_,7 @@
}
@@ -101,7 +_,7 @@
}
Vec3 boomPos = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos), null, boomPos, 5.0F, true, Level.ExplosionInteraction.BLOCK);
+ if (level.purpurConfig.bedExplode) level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos), null, boomPos, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect); // Purpur - Implement bed explosion options
return InteractionResult.SUCCESS_SERVER;
} else if (state.getValue(OCCUPIED)) {
if (bedRule.explodes()) return this.explodeBed(state, level, pos); // Paper - check explode first
Vec3 boomPos = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos), null, boomPos, 5.0F, true, Level.ExplosionInteraction.BLOCK);
+ if (level.purpurConfig.bedExplode) level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos), null, boomPos, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect); // Purpur - Implement bed explosion options
return InteractionResult.SUCCESS_SERVER;
} else if (state.getValue(OCCUPIED)) {
if (bedRule.explodes()) return this.explodeBed(state, level, pos); // Paper - check explode first
@@ -153,7 +_,7 @@
}
Vec3 center = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(center).causingBlockSnapshot(blockState), null, center, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ if (level.purpurConfig.bedExplode) level.explode(null, level.damageSources().badRespawnPointExplosion(center).causingBlockSnapshot(blockState), null, center, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect); // CraftBukkit - add state // Purpur - Implement bed explosion options
Vec3 boomPos = pos.getCenter();
- level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos).causingBlockSnapshot(blockState), null, boomPos, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
+ if (level.purpurConfig.bedExplode) level.explode(null, level.damageSources().badRespawnPointExplosion(boomPos).causingBlockSnapshot(blockState), null, boomPos, (float) level.purpurConfig.bedExplosionPower, level.purpurConfig.bedExplosionFire, level.purpurConfig.bedExplosionEffect); // CraftBukkit - add state // Purpur - Implement bed explosion options
return InteractionResult.SUCCESS_SERVER;
}
// CraftBukkit end

View File

@@ -11,7 +11,7 @@
// Paper start - Protect Bedrock and End Portal/Frames from being destroyed
public final boolean isDestroyable() {
return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits ||
@@ -411,7 +_,7 @@
@@ -415,7 +_,7 @@
event.setExpToDrop(block.getExpDrop(state, serverLevel, pos, net.minecraft.world.item.ItemStack.EMPTY, true)); // Paper - Properly handle xp dropping
event.callEvent();
for (org.bukkit.inventory.ItemStack drop : event.getDrops()) {
@@ -20,7 +20,7 @@
}
state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, false); // Paper - Properly handle xp dropping
block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping
@@ -429,7 +_,7 @@
@@ -433,7 +_,7 @@
public static void dropResources(final BlockState state, final LevelAccessor level, final BlockPos pos, final @Nullable BlockEntity blockEntity) {
if (level instanceof ServerLevel serverLevel) {
@@ -29,7 +29,7 @@
state.spawnAfterBreak(serverLevel, pos, ItemStack.EMPTY, true);
}
}
@@ -450,11 +_,30 @@
@@ -454,11 +_,30 @@
, final boolean dropExperience // Paper - Properly handle xp dropping
) {
if (level instanceof ServerLevel serverLevel) {
@@ -61,7 +61,7 @@
public static void popResource(final Level level, final BlockPos pos, final ItemStack itemStack) {
double halfHeight = EntityType.ITEM.getHeight() / 2.0;
RandomSource random = level.getRandom();
@@ -544,7 +_,15 @@
@@ -548,7 +_,15 @@
}
public void setPlacedBy(final Level level, final BlockPos pos, final BlockState state, final @Nullable LivingEntity by, final ItemStack itemStack) {
@@ -78,7 +78,7 @@
public boolean isPossibleToRespawnInThis(final BlockState state) {
return !state.isSolid() && !state.liquid();
@@ -555,7 +_,7 @@
@@ -559,7 +_,7 @@
}
public void fallOn(final Level level, final BlockState state, final BlockPos pos, final Entity entity, final double fallDistance) {

View File

@@ -1,10 +1,10 @@
--- a/net/minecraft/world/level/block/CakeBlock.java
+++ b/net/minecraft/world/level/block/CakeBlock.java
@@ -118,6 +_,7 @@
org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel);
@@ -119,6 +_,7 @@
org.bukkit.event.entity.FoodLevelChangeEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callFoodLevelChangeEvent(player, 2 + oldFoodLevel);
if (!event.isCancelled()) {
+ if (player.level().purpurConfig.playerBurpWhenFull && event.getFoodLevel() == 20 && oldFoodLevel < 20) player.burpDelay = player.level().purpurConfig.playerBurpDelay; // Purpur - Burp after eating food fills hunger bar completely
player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F);
}
if (!event.isCancelled()) {
+ if (player.level().purpurConfig.playerBurpWhenFull && event.getFoodLevel() == 20 && oldFoodLevel < 20) player.burpDelay = player.level().purpurConfig.playerBurpDelay; // Purpur - Burp after eating food fills hunger bar completely
player.getFoodData().eat(event.getFoodLevel() - oldFoodLevel, 0.1F);
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/ChestBlock.java
+++ b/net/minecraft/world/level/block/ChestBlock.java
@@ -352,6 +_,7 @@
@@ -347,6 +_,7 @@
}
public static boolean isBlockedChestByBlock(final BlockGetter level, final BlockPos pos) {

View File

@@ -1,13 +1,14 @@
--- a/net/minecraft/world/level/block/DoorBlock.java
+++ b/net/minecraft/world/level/block/DoorBlock.java
@@ -200,6 +_,7 @@
@@ -200,7 +_,7 @@
protected InteractionResult useWithoutItem(BlockState state, final Level level, final BlockPos pos, final Player player, final BlockHitResult hitResult) {
if (!this.type.canOpenByHand()) {
return InteractionResult.PASS;
+ } else if (requiresRedstone(level, state, pos)) { return InteractionResult.CONSUME; // Purpur - Option to make doors require redstone
} else {
state = state.cycle(OPEN);
level.setBlock(pos, state, Block.UPDATE_CLIENTS | Block.UPDATE_IMMEDIATE);
- }
+ } else if (requiresRedstone(level, state, pos)) { return InteractionResult.CONSUME; } // Purpur - Option to make doors require redstone
state = state.cycle(OPEN);
level.setBlock(pos, state, Block.UPDATE_CLIENTS | Block.UPDATE_IMMEDIATE);
@@ -280,4 +_,18 @@
public static boolean isWoodenDoor(final BlockState state) {
return state.getBlock() instanceof DoorBlock door && door.type().canOpenByHand();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/PointedDripstoneBlock.java
+++ b/net/minecraft/world/level/block/PointedDripstoneBlock.java
@@ -194,20 +_,20 @@
@@ -196,20 +_,20 @@
@VisibleForTesting
public static void maybeTransferFluid(final BlockState state, final ServerLevel level, final BlockPos pos, final float randomValue) {

View File

@@ -7,5 +7,5 @@
- if (searchDepth >= 8) {
+ if (searchDepth >= level.purpurConfig.railActivationRange) { // Purpur - Config for powered rail activation distance
return false;
} else {
int x = pos.getX();
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/RespawnAnchorBlock.java
+++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java
@@ -180,7 +_,7 @@
@@ -176,7 +_,7 @@
}
};
Vec3 boomPos = pos.getCenter();

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/AbstractFurnaceBlockEntity.java
@@ -195,6 +_,21 @@
@@ -190,6 +_,21 @@
}
ItemStack fuel = entity.items.get(1);
@@ -22,7 +22,7 @@
ItemStack ingredient = entity.items.get(0);
boolean hasIngredient = !ingredient.isEmpty();
boolean hasFuel = !fuel.isEmpty();
@@ -273,6 +_,8 @@
@@ -268,6 +_,8 @@
if (changed) {
setChanged(level, pos, state);
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BeaconBlockEntity.java
@@ -142,6 +_,16 @@
@@ -138,6 +_,16 @@
public double getEffectRange() {
if (this.effectRange < 0) {
@@ -17,7 +17,7 @@
return this.levels * 10 + 10;
} else {
return effectRange;
@@ -170,6 +_,7 @@
@@ -166,6 +_,7 @@
int y = pos.getY();
int z = pos.getZ();
BlockPos checkPos;
@@ -25,7 +25,7 @@
if (entity.lastCheckY < y) {
checkPos = pos;
entity.checkingBeamSections = Lists.newArrayList();
@@ -199,11 +_,15 @@
@@ -195,11 +_,15 @@
}
}
} else {
@@ -42,7 +42,7 @@
lastBeamSection.increaseHeight();
}
@@ -214,11 +_,11 @@
@@ -210,11 +_,11 @@
int previousLevels = entity.levels;
if (level.getGameTime() % 80L == 0L) {

View File

@@ -9,7 +9,7 @@
private static final int MIN_TICKS_BEFORE_REENTERING_HIVE = 400;
private static final int MIN_OCCUPATION_TICKS_NECTAR = 2400;
public static final int MIN_OCCUPATION_TICKS_NECTARLESS = 600;
@@ -157,11 +_,33 @@
@@ -157,10 +_,32 @@
return spawned;
}
@@ -33,24 +33,12 @@
public int getOccupantCount() {
return this.stored.size();
}
+
+ // Purpur start - Stored Bee API
+ public List<BeeData> getStored() {
+ return stored;
+ }
+ // Purpur end - Stored Bee API
+
// Paper start - Add EntityBlockStorage clearEntities
public void clearBees() {
this.stored.clear();
@@ -400,8 +_,8 @@
registration.register(DebugSubscriptions.BEE_HIVES, () -> DebugHiveInfo.pack(this));
}
- private static class BeeData {
- private final BeehiveBlockEntity.Occupant occupant;
+ public static class BeeData { // Purpur - make public - Stored Bee API
+ public final BeehiveBlockEntity.Occupant occupant; // Purpur - make public - Stored Bee API
private int exitTickCounter; // Paper - Fix bees aging inside hives; separate counter for checking if bee should exit to reduce exit attempts
private int ticksInHive;

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -108,6 +_,10 @@
@@ -107,6 +_,10 @@
input.read("PublicBukkitValues", CompoundTag.CODEC)
.ifPresent(this.persistentDataContainer::putAll);
// Paper end - read persistent data container
@@ -11,7 +11,7 @@
}
public final void loadWithComponents(final ValueInput input) {
@@ -120,6 +_,11 @@
@@ -119,6 +_,11 @@
}
protected void saveAdditional(final ValueOutput output) {
@@ -23,7 +23,7 @@
}
public final CompoundTag saveWithFullMetadata(final HolderLookup.Provider registries) {
@@ -414,4 +_,16 @@
@@ -395,4 +_,16 @@
return this.blockEntity.getNameForReporting() + "@" + this.blockEntity.getBlockPos();
}
}

View File

@@ -1,7 +1,7 @@
--- a/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/ConduitBlockEntity.java
@@ -150,7 +_,7 @@
BlockPos testPos = worldPosition.offset(ox, oy, ozx);
@@ -151,7 +_,7 @@
BlockPos testPos = worldPosition.offset(ox, oy, oz);
BlockState testBlock = level.getBlockState(testPos);
- for (Block type : VALID_BLOCKS) {
@@ -9,7 +9,7 @@
if (testBlock.is(type)) {
effectBlocks.add(testPos);
}
@@ -165,13 +_,13 @@
@@ -166,13 +_,13 @@
private static void applyEffects(final Level level, final BlockPos worldPosition, final List<BlockPos> effectBlocks) {
// CraftBukkit start
@@ -26,7 +26,7 @@
// CraftBukkit start
return effectRange;
}
@@ -204,7 +_,7 @@
@@ -205,7 +_,7 @@
EntityReference<LivingEntity> newDestroyTarget = updateDestroyTarget(entity.destroyTarget, level, worldPosition, isActive);
LivingEntity targetEntity = EntityReference.getLivingEntity(newDestroyTarget, level);
if (damageTarget && targetEntity != null) { // CraftBukkit
@@ -35,13 +35,12 @@
level.playSound(
null, targetEntity.getX(), targetEntity.getY(), targetEntity.getZ(), SoundEvents.CONDUIT_ATTACK_TARGET, SoundSource.BLOCKS, 1.0F, 1.0F
);
@@ -225,19 +_,25 @@
return selectNewTarget(level, pos);
} else {
LivingEntity targetEntity = EntityReference.getLivingEntity(target, level);
- return targetEntity != null && targetEntity.isAlive() && pos.closerThan(targetEntity.blockPosition(), 8.0) ? target : null;
+ return targetEntity != null && targetEntity.isAlive() && pos.closerThan(targetEntity.blockPosition(), level.purpurConfig.conduitDamageDistance) ? target : null; // Purpur - Conduit behavior configuration
@@ -229,18 +_,24 @@
}
LivingEntity targetEntity = EntityReference.getLivingEntity(target, level);
- return targetEntity != null && targetEntity.isAlive() && pos.closerThan(targetEntity.blockPosition(), 8.0) ? target : null;
+ return targetEntity != null && targetEntity.isAlive() && pos.closerThan(targetEntity.blockPosition(), level.purpurConfig.conduitDamageDistance) ? target : null; // Purpur - Conduit behavior configuration
}
private static @Nullable EntityReference<LivingEntity> selectNewTarget(final ServerLevel level, final BlockPos pos) {

View File

@@ -35,7 +35,7 @@
);
}
}
@@ -309,6 +_,27 @@
@@ -310,6 +_,27 @@
commandSource, Vec3.atCenterOf(pos), Vec2.ZERO, level, LevelBasedPermissionSet.GAMEMASTER, textName, displayName, level.getServer(), player // Paper - Fix commands from signs not firing command events
);
}

View File

@@ -1,29 +1,29 @@
--- a/net/minecraft/world/level/block/piston/PistonStructureResolver.java
+++ b/net/minecraft/world/level/block/piston/PistonStructureResolver.java
@@ -81,7 +_,7 @@
return true;
} else {
int blockCount = 1;
- if (blockCount + this.toPush.size() > 12) {
+ if (blockCount + this.toPush.size() > this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
@@ -90,7 +_,7 @@
}
int blockCount = 1;
- if (blockCount + this.toPush.size() > 12) {
+ if (blockCount + this.toPush.size() > this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
return false;
}
@@ -105,7 +_,7 @@
break;
}
- if (++blockCount + this.toPush.size() > 12) {
+ if (++blockCount + this.toPush.size() > this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
return false;
} else {
while (isSticky(nextState)) {
@@ -95,7 +_,7 @@
break;
}
}
}
@@ -149,7 +_,7 @@
return true;
}
- if (++blockCount + this.toPush.size() > 12) {
+ if (++blockCount + this.toPush.size() > this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
return false;
}
}
@@ -139,7 +_,7 @@
return true;
}
- if (this.toPush.size() >= 12) {
+ if (this.toPush.size() >= this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
return false;
}
- if (this.toPush.size() >= 12) {
+ if (this.toPush.size() >= this.level.purpurConfig.pistonBlockPushLimit) { // Purpur - Configurable piston push limit
return false;
}

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/chunk/storage/EntityStorage.java
+++ b/net/minecraft/world/level/chunk/storage/EntityStorage.java
@@ -108,6 +_,7 @@
@@ -105,6 +_,7 @@
}
// Paper end - Entity load/save limit per chunk
TagValueOutput output = TagValueOutput.createWithContext(reporter.forChild(e.problemPath()), e.registryAccess());

View File

@@ -4,8 +4,8 @@
// Paper start
private static void printOversizedLog(String msg, Path file, int x, int z) {
- org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.");
+ org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PURPUR - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); // Purpur - Rebrand
- LOGGER.error("{} ({} - {},{}) Go clean it up to remove this message. /minecraft:tp {} 128 {} - DO NOT REPORT THIS TO PAPER - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.", msg, file.toString().replaceAll(".+[\\\\/]", ""), x, z, x << 4, z << 4);
+ LOGGER.error("{} ({} - {},{}) Go clean it up to remove this message. /minecraft:tp {} 128 {} - DO NOT REPORT THIS TO PURPUR - You may ask for help on Discord, but do not file an issue. These error messages can not be removed.", msg, file.toString().replaceAll(".+[\\\\/]", ""), x, z, x << 4, z << 4); // Purpur - Rebrand
}
private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {

View File

@@ -1,6 +1,6 @@
--- a/net/minecraft/world/level/material/FlowingFluid.java
+++ b/net/minecraft/world/level/material/FlowingFluid.java
@@ -235,7 +_,7 @@
@@ -234,7 +_,7 @@
}
}
@@ -9,7 +9,7 @@
BlockState belowState = level.getBlockState(mutablePos.setWithOffset(pos, Direction.DOWN));
FluidState belowFluid = belowState.getFluidState();
if (belowState.isSolid() || this.isSourceBlockOfThisType(belowFluid)) {
@@ -321,6 +_,12 @@
@@ -320,6 +_,12 @@
}
protected abstract boolean canConvertToSource(ServerLevel level);

View File

@@ -1,20 +1,20 @@
--- a/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
+++ b/net/minecraft/world/level/pathfinder/WalkNodeEvaluator.java
@@ -249,7 +_,7 @@
if ((best == null || best.costMalus < 0.0F)
&& jumpSize > 0
&& (pathType != PathType.FENCE || this.canWalkOverFences())
- && pathType != PathType.UNPASSABLE_RAIL
+ && (this.mob.level().purpurConfig.mobsIgnoreRails || pathType != PathType.UNPASSABLE_RAIL) // Purpur - Config to allow mobs to pathfind over rails
&& pathType != PathType.TRAPDOOR
&& pathType != PathType.POWDER_SNOW) {
best = this.tryJumpOn(x, y, z, jumpSize, nodeHeight, travelDirection, blockPathTypeCurrent, reusablePos);
@@ -517,7 +_,7 @@
return PathType.TRAPDOOR;
} else if (blockState.is(Blocks.POWDER_SNOW)) {
@@ -252,7 +_,7 @@
if ((best == null || best.costMalus < 0.0F)
&& jumpSize > 0
&& (pathType != PathType.FENCE || this.canWalkOverFences())
- && pathType != PathType.UNPASSABLE_RAIL
+ && (this.mob.level().purpurConfig.mobsIgnoreRails || pathType != PathType.UNPASSABLE_RAIL) // Purpur - Config to allow mobs to pathfind over rails
&& pathType != PathType.TRAPDOOR
&& pathType != PathType.POWDER_SNOW) {
best = this.tryJumpOn(x, y, z, jumpSize, nodeHeight, travelDirection, blockPathTypeCurrent, reusablePos);
@@ -533,7 +_,7 @@
return PathType.POWDER_SNOW;
- } else if (blockState.is(Blocks.CACTUS) || blockState.is(Blocks.SWEET_BERRY_BUSH)) {
+ } else if (blockState.is(Blocks.CACTUS) || blockState.is(Blocks.SWEET_BERRY_BUSH) || blockState.is(Blocks.STONECUTTER)) { // Purpur - Stonecutter damage
}
- if (blockState.is(Blocks.CACTUS) || blockState.is(Blocks.SWEET_BERRY_BUSH)) {
+ if (blockState.is(Blocks.CACTUS) || blockState.is(Blocks.SWEET_BERRY_BUSH) || blockState.is(Blocks.STONECUTTER)) { // Purpur - Stonecutter damage
return PathType.DAMAGING;
} else if (blockState.is(Blocks.HONEY_BLOCK)) {
return PathType.STICKY_HONEY;
}