diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch index f2fdcb6c2..9671040f3 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch @@ -109,6 +109,42 @@ skeletonHorse.setAge(0); skeletonHorse.setPos(blockPos.getX(), blockPos.getY(), blockPos.getZ()); this.addFreshEntity(skeletonHorse, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit +@@ -984,9 +_,35 @@ + if (blockState.is(Blocks.SNOW)) { + int layersValue = blockState.getValue(SnowLayerBlock.LAYERS); + if (layersValue < Math.min(_int, 8)) { ++ // Purpur start - Smooth snow accumulation ++ boolean canSnow = true; ++ // Ensure snow doesn't get more than N layers taller than its neighbors ++ // We only need to check blocks that are taller than the minimum step height ++ if (org.purpurmc.purpur.PurpurConfig.smoothSnowAccumulationStep > 0 && layersValue >= org.purpurmc.purpur.PurpurConfig.smoothSnowAccumulationStep) { ++ int layersValueMin = layersValue - org.purpurmc.purpur.PurpurConfig.smoothSnowAccumulationStep; ++ for (Direction direction : Direction.Plane.HORIZONTAL) { ++ BlockPos blockPosNeighbor = heightmapPos.relative(direction); ++ BlockState blockStateNeighbor = this.getBlockState(blockPosNeighbor); ++ if (blockStateNeighbor.is(Blocks.SNOW)) { ++ // Special check for snow layers, if neighbors are too short, don't accumulate ++ int layersValueNeighbor = blockStateNeighbor.getValue(SnowLayerBlock.LAYERS); ++ if (layersValueNeighbor <= layersValueMin) { ++ canSnow = false; ++ break; ++ } ++ } else if (!Block.isFaceFull(blockStateNeighbor.getCollisionShape(this, blockPosNeighbor), direction.getOpposite())) { ++ // Since our layer is tall enough already, if we have a non-full neighbor block, don't accumulate ++ canSnow = false; ++ break; ++ } ++ } ++ } ++ if (canSnow) { ++ // Purpur end - Smooth snow accumulation + BlockState blockState1 = blockState.setValue(SnowLayerBlock.LAYERS, layersValue + 1); + Block.pushEntitiesUp(blockState, blockState1, this, heightmapPos); + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, blockState1, 3, null); // CraftBukkit ++ } // Purpur - Smooth snow accumulation + } + } else { + org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, heightmapPos, Blocks.SNOW.defaultBlockState(), 3, null); // CraftBukkit @@ -1007,7 +_,7 @@ pointOfInterestType -> pointOfInterestType.is(PoiTypes.LIGHTNING_ROD), blockPos -> blockPos.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, blockPos.getX(), blockPos.getZ()) - 1, diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch index e8b905a8b..7dd50302a 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/block/GrowingPlantHeadBlock.java.patch @@ -5,7 +5,7 @@ @Override public BlockState getStateForPlacement(RandomSource random) { - return this.defaultBlockState().setValue(AGE, random.nextInt(25)); -+ return this.defaultBlockState().setValue(AGE, random.nextInt(getMaxGrowthAge())); // Purpur - kelp, cave, weeping, and twisting configurable max growth age ++ return this.defaultBlockState().setValue(AGE, getMaxGrowthAge() == 0 ? 0 : random.nextInt(getMaxGrowthAge())); // Purpur - kelp, cave, weeping, and twisting configurable max growth age } @Override diff --git a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurConfig.java b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurConfig.java index f5adfffd2..282057126 100644 --- a/purpur-server/src/main/java/org/purpurmc/purpur/PurpurConfig.java +++ b/purpur-server/src/main/java/org/purpurmc/purpur/PurpurConfig.java @@ -332,6 +332,7 @@ public class PurpurConfig { public static boolean cryingObsidianValidForPortalFrame = false; public static int beeInsideBeeHive = 3; public static boolean anvilCumulativeCost = true; + public static int smoothSnowAccumulationStep = 0; public static int lightningRodRange = 128; public static Set grindstoneIgnoredEnchants = new HashSet<>(); public static boolean grindstoneRemoveAttributes = false; @@ -375,6 +376,16 @@ public class PurpurConfig { cryingObsidianValidForPortalFrame = getBoolean("settings.blocks.crying_obsidian.valid-for-portal-frame", cryingObsidianValidForPortalFrame); beeInsideBeeHive = getInt("settings.blocks.beehive.max-bees-inside", beeInsideBeeHive); anvilCumulativeCost = getBoolean("settings.blocks.anvil.cumulative-cost", anvilCumulativeCost); + smoothSnowAccumulationStep = getInt("settings.blocks.snow.smooth-accumulation-step", smoothSnowAccumulationStep); + if (smoothSnowAccumulationStep > 7) { + smoothSnowAccumulationStep = 7; + log(Level.WARNING, "blocks.snow.smooth-accumulation-step is set to above maximum allowed value of 7"); + log(Level.WARNING, "Using value of 7 to prevent issues"); + } else if (smoothSnowAccumulationStep < 0) { + smoothSnowAccumulationStep = 0; + log(Level.WARNING, "blocks.snow.smooth-accumulation-step is set to below minimum allowed value of 0"); + log(Level.WARNING, "Using value of 0 to prevent issues"); + } lightningRodRange = getInt("settings.blocks.lightning_rod.range", lightningRodRange); ArrayList defaultCurses = new ArrayList<>(){{ add("minecraft:binding_curse");