Samsuik / Sakura

13 stars 8 forks source link

(Suggestion/Patch) Optimizing Cactus farms #17

Closed IAISI closed 3 months ago

IAISI commented 5 months ago

Cactus Farms are still large part of gameplay on some servers, unfortunately they can also cause issues, even more so with plugins/special chests that auto collect drops and cancel BlockGrowEvent events.

I think one of the solutions would be to reduce block updates, I would like to share patch we're currently using to address this:

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: ChangeMe <info@change.me>
Date: Fri, 9 Feb 2024 23:40:49 +0100
Subject: [PATCH] Optimize CactusBlock

diff --git a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
index d3fdf62912d190f8b468b77230a927023c361074..e4f4597c5c92edac7e538923be5d0ef26fbd6194 100644
--- a/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
+++ b/src/main/java/io/papermc/paper/configuration/WorldConfiguration.java
@@ -546,6 +546,7 @@ public class WorldConfiguration extends ConfigurationPart {
         public boolean disableSprintInterruptionOnAttack = false;
         public int shieldBlockingDelay = 5;
         public boolean disableRelativeProjectileVelocity = false;
+        public boolean optimizeCactus = true;

         public enum RedstoneImplementation {
             VANILLA, EIGENCRAFT, ALTERNATE_CURRENT
diff --git a/src/main/java/net/minecraft/world/level/block/CactusBlock.java b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
index ba4aaf850af36a84517c70581e141157c4f15b99..29fc0409c64dcad82313652e72d55afcda20201e 100644
--- a/src/main/java/net/minecraft/world/level/block/CactusBlock.java
+++ b/src/main/java/net/minecraft/world/level/block/CactusBlock.java
@@ -21,7 +21,10 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty;
 import net.minecraft.world.level.pathfinder.PathComputationType;
 import net.minecraft.world.phys.shapes.CollisionContext;
 import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.block.CraftBlockState;
 import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit
+import org.bukkit.event.block.BlockGrowEvent;

 public class CactusBlock extends Block {

@@ -54,6 +57,41 @@ public class CactusBlock extends Block {
     public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
         BlockPos blockposition1 = pos.above();

+        // CustomSpigot - start - optimize cactus
+        if(world.paperConfig().misc.optimizeCactus) {
+
+            if (random.nextInt(16) == 0)
+            {
+                if (world.isEmptyBlock(blockposition1)) {
+                    int i;
+
+                    for (i = 1; world.getBlockState(pos.below(i)).is((Block) this); ++i) {
+                        ;
+                    }
+
+                    if (i < world.paperConfig().maxGrowthHeight.cactus) {
+                        org.bukkit.block.Block block = world.getWorld().getBlockAt(blockposition1.getX(), blockposition1.getY(), blockposition1.getZ());
+                        CraftBlockState state2 = (CraftBlockState) block.getState();
+                        state2.setData(this.defaultBlockState());
+
+                        BlockGrowEvent event = new BlockGrowEvent(block, state2);
+                        Bukkit.getPluginManager().callEvent(event);
+
+                        if (!event.isCancelled()) {
+                            state2.update(true);
+                            world.setBlock(pos, state.setValue(CactusBlock.AGE, CactusBlock.MAX_AGE), 4);
+                            BlockState iblockdata1 = (BlockState) state.setValue(CactusBlock.AGE, 0);
+                            world.setBlock(pos, iblockdata1, 4);
+                            world.neighborChanged(iblockdata1, blockposition1, this, pos, false);
+                        }
+                    }
+                }
+            }
+
+            return;
+        }
+        // CustomSpigot - end - optimize cactus
+
         if (world.isEmptyBlock(blockposition1)) {
             int i;

I do realize this is probably not the best solution but it greatly reduces lag from Cactus farms, I'm open for other ideas and feedback, would love to see this added to Sakura :)

This could probably be expanded to optimize other farmable blocks, but I don't think there are any other farms that wouldn't be taken care of by redstone limits, while 9+ chunks of cactus could generate considerable lag without any redstone (meaning capping redstone wouldn't help with lag since there isn't any).

Samsuik commented 5 months ago

I added a similar patch to the dev branch https://github.com/Samsuik/Sakura/commit/e6a141c68038622e7b8b6b7ec97e34cda3087cf3

Samsuik commented 5 months ago

Closing as the commit I referenced has been merged into the main branch

IAISI commented 3 months ago

This is a bit awkward... but we actually tested this when updating to 1.20.6 when we tried running Sakura without any of our patches and it appears this is not working as intended. Cactus growth would be bugged, as in Cacti simply won't grow at all...

I think just setting max age is the issue:

not sure why, but when making our own patch included in this issue we noticed similar behavior, I think its somehow related to setting AGE

Samsuik commented 3 months ago

Yeah, that is definitely not implemented correctly.

Samsuik commented 3 months ago

This might be fixed with the recent changes. I noticed that with the patch cactus would take 15x longer than vanilla to grow, and that cactus could grow beside a block and not break.

IAISI commented 3 months ago

It seems a bit faster compared to my patch, but yea it seems to be working now, I've just tested 1.20.6