From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com> Date: Thu, 6 Apr 2023 20:53:05 -0400 Subject: [PATCH] Carpet-Fixes: Use optimized PoweredRailBlock logic Original license: MIT Original project: https://github.com/fxmorin/carpet-fixes Full Rewrite of the powered rail iteration logic. This rewrite brings a massive performance boost while keeping the vanilla order. This is achieved by running all the powered rail logic from a single rail instead of each block iterating separately. Which was not only very expensive but also completely unnecessary and with a lot of massive overhead diff --git a/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java b/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java index 7fddb6fa8fd30ef88346a59f7867aae792f13772..926dbe4ed5044d4ee06df033b873ccb09b36a2cb 100644 --- a/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java +++ b/src/main/java/net/minecraft/world/level/block/PoweredRailBlock.java @@ -1,6 +1,7 @@ package net.minecraft.world.level.block; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; @@ -11,6 +12,9 @@ import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.block.state.properties.RailShape; import org.bukkit.craftbukkit.event.CraftEventFactory; // CraftBukkit +import org.dreeam.leaf.LeafConfig; + +import java.util.HashMap; public class PoweredRailBlock extends BaseRailBlock { @@ -19,35 +23,36 @@ public class PoweredRailBlock extends BaseRailBlock { protected PoweredRailBlock(BlockBehaviour.Properties settings) { super(true, settings); - this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH)).setValue(PoweredRailBlock.POWERED, false)).setValue(PoweredRailBlock.WATERLOGGED, false)); + this.registerDefaultState(this.stateDefinition.any().setValue(PoweredRailBlock.SHAPE, RailShape.NORTH_SOUTH).setValue(PoweredRailBlock.POWERED, false).setValue(PoweredRailBlock.WATERLOGGED, false)); } - protected boolean findPoweredRailSignal(Level world, BlockPos pos, BlockState state, boolean flag, int distance) { - if (distance >= 8) { + protected boolean findPoweredRailSignal(Level world, BlockPos pos, BlockState state, boolean flag, int distance, HashMap checkedPos) { + if (distance >= LeafConfig.railPowerLimit - 1) { return false; } else { int j = pos.getX(); int k = pos.getY(); int l = pos.getZ(); boolean flag1 = true; - RailShape blockpropertytrackposition = (RailShape) state.getValue(PoweredRailBlock.SHAPE); + RailShape blockpropertytrackposition = state.getValue(PoweredRailBlock.SHAPE); + // not sure whether need blockpropertytrackposition.ordinal() switch (blockpropertytrackposition) { - case NORTH_SOUTH: + case NORTH_SOUTH -> { if (flag) { ++l; } else { --l; } - break; - case EAST_WEST: + } + case EAST_WEST -> { if (flag) { --j; } else { ++j; } - break; - case ASCENDING_EAST: + } + case ASCENDING_EAST -> { if (flag) { --j; } else { @@ -57,8 +62,8 @@ public class PoweredRailBlock extends BaseRailBlock { } blockpropertytrackposition = RailShape.EAST_WEST; - break; - case ASCENDING_WEST: + } + case ASCENDING_WEST -> { if (flag) { --j; ++k; @@ -68,8 +73,8 @@ public class PoweredRailBlock extends BaseRailBlock { } blockpropertytrackposition = RailShape.EAST_WEST; - break; - case ASCENDING_NORTH: + } + case ASCENDING_NORTH -> { if (flag) { ++l; } else { @@ -79,8 +84,8 @@ public class PoweredRailBlock extends BaseRailBlock { } blockpropertytrackposition = RailShape.NORTH_SOUTH; - break; - case ASCENDING_SOUTH: + } + case ASCENDING_SOUTH -> { if (flag) { ++l; ++k; @@ -90,44 +95,78 @@ public class PoweredRailBlock extends BaseRailBlock { } blockpropertytrackposition = RailShape.NORTH_SOUTH; + } } - return this.isSameRailWithPower(world, new BlockPos(j, k, l), flag, distance, blockpropertytrackposition) ? true : flag1 && this.isSameRailWithPower(world, new BlockPos(j, k - 1, l), flag, distance, blockpropertytrackposition); + return this.isSameRailWithPower(world, new BlockPos(j, k, l), flag, distance, blockpropertytrackposition, checkedPos) || (flag1 && this.isSameRailWithPower(world, new BlockPos(j, k - 1, l), flag, distance, blockpropertytrackposition, checkedPos)); } } - protected boolean isSameRailWithPower(Level world, BlockPos pos, boolean flag, int distance, RailShape shape) { - BlockState iblockdata = world.getBlockState(pos); + protected boolean findPoweredRailSignal(Level world, BlockPos pos, BlockState state, boolean flag, int distance) { + return false; + } - if (!iblockdata.is((Block) this)) { - return false; - } else { - RailShape blockpropertytrackposition1 = (RailShape) iblockdata.getValue(PoweredRailBlock.SHAPE); + private static final Direction[] EAST_WEST_DIR = new Direction[]{Direction.WEST, Direction.EAST}; + private static final Direction[] NORTH_SOUTH_DIR = new Direction[]{Direction.SOUTH, Direction.NORTH}; + + private static final int FORCE_PLACE = UPDATE_MOVE_BY_PISTON | UPDATE_KNOWN_SHAPE | UPDATE_CLIENTS; - return shape == RailShape.EAST_WEST && (blockpropertytrackposition1 == RailShape.NORTH_SOUTH || blockpropertytrackposition1 == RailShape.ASCENDING_NORTH || blockpropertytrackposition1 == RailShape.ASCENDING_SOUTH) ? false : (shape == RailShape.NORTH_SOUTH && (blockpropertytrackposition1 == RailShape.EAST_WEST || blockpropertytrackposition1 == RailShape.ASCENDING_EAST || blockpropertytrackposition1 == RailShape.ASCENDING_WEST) ? false : ((Boolean) iblockdata.getValue(PoweredRailBlock.POWERED) ? (world.hasNeighborSignal(pos) ? true : this.findPoweredRailSignal(world, pos, iblockdata, flag, distance + 1)) : false)); + protected boolean isSameRailWithPower(Level world, BlockPos pos, boolean flag, int distance, RailShape shape, HashMap checkedPos) { + BlockState iblockdata = world.getBlockState(pos); + boolean speedCheck = checkedPos.containsKey(pos) && checkedPos.get(pos); + if (speedCheck) { + return world.hasNeighborSignal(pos) || + this.findPoweredRailSignal(world, pos, iblockdata, flag, distance + 1, checkedPos); + } else { + if (iblockdata.is(this)) { + RailShape blockpropertytrackposition1 = iblockdata.getValue(PoweredRailBlock.SHAPE); + ; + if (shape == RailShape.EAST_WEST && ( + blockpropertytrackposition1 == RailShape.NORTH_SOUTH || + blockpropertytrackposition1 == RailShape.ASCENDING_NORTH || + blockpropertytrackposition1 == RailShape.ASCENDING_SOUTH + ) || shape == RailShape.NORTH_SOUTH && ( + blockpropertytrackposition1 == RailShape.EAST_WEST || + blockpropertytrackposition1 == RailShape.ASCENDING_EAST || + blockpropertytrackposition1 == RailShape.ASCENDING_WEST + )) { + return false; + } else if (iblockdata.getValue(PoweredRailBlock.POWERED)) { + return world.hasNeighborSignal(pos) || + this.findPoweredRailSignal(world, pos, iblockdata, flag, distance + 1, checkedPos); + } else { + return false; + } + } + return false; } } @Override protected void updateState(BlockState state, Level world, BlockPos pos, Block neighbor) { - boolean flag = (Boolean) state.getValue(PoweredRailBlock.POWERED); - boolean flag1 = world.hasNeighborSignal(pos) || this.findPoweredRailSignal(world, pos, state, true, 0) || this.findPoweredRailSignal(world, pos, state, false, 0); - - if (flag1 != flag) { - // CraftBukkit start - int power = flag ? 15 : 0; - int newPower = CraftEventFactory.callRedstoneChange(world, pos, power, 15 - power).getNewCurrent(); - if (newPower == power) { - return; - } - // CraftBukkit end - world.setBlock(pos, (BlockState) state.setValue(PoweredRailBlock.POWERED, flag1), 3); - world.updateNeighborsAt(pos.below(), this); - if (((RailShape) state.getValue(PoweredRailBlock.SHAPE)).isAscending()) { - world.updateNeighborsAt(pos.above(), this); + if (LeafConfig.optimizedPoweredRails) { + boolean flag = state.getValue(PoweredRailBlock.POWERED); + boolean flag1 = world.hasNeighborSignal(pos) || this.findPoweredRailSignal(world, pos, state, true, 0) || this.findPoweredRailSignal(world, pos, state, false, 0); + + if (flag1 != flag) { + // CraftBukkit start + int power = flag ? 15 : 0; + int newPower = CraftEventFactory.callRedstoneChange(world, pos, power, 15 - power).getNewCurrent(); + if (newPower == power) { + return; + } + // CraftBukkit end + if (state.getValue(PoweredRailBlock.SHAPE).isAscending()) { + world.setBlock(pos, state.setValue(PoweredRailBlock.POWERED, flag1), 3); + world.updateNeighborsAtExceptFromFacing(pos.below(), this, Direction.UP); + world.updateNeighborsAtExceptFromFacing(pos.above(), this, Direction.DOWN); //isAscending + } else if (flag1) { + powerLane(world, pos, state, state.getValue(PoweredRailBlock.SHAPE)); + } else { + dePowerLane(world, pos, state, state.getValue(PoweredRailBlock.SHAPE)); + } } } - } @Override @@ -258,4 +297,197 @@ public class PoweredRailBlock extends BaseRailBlock { protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(PoweredRailBlock.SHAPE, PoweredRailBlock.POWERED, PoweredRailBlock.WATERLOGGED); } + + public static void giveShapeUpdate(Level world, BlockState state, BlockPos pos, BlockPos fromPos, Direction direction) { + BlockState oldState = world.getBlockState(pos); + Block.updateOrDestroy( + oldState, + oldState.updateShape(direction.getOpposite(), state, world, pos, fromPos), + world, + pos, + Block.UPDATE_CLIENTS & -34, + 0 + ); + } + + public void powerLane(Level world, BlockPos pos, BlockState mainState, RailShape railShape) { + world.setBlock(pos, mainState.setValue(PoweredRailBlock.POWERED, true), FORCE_PLACE); + HashMap checkedPos = new HashMap<>(); + checkedPos.put(pos, true); + int[] count = new int[2]; + if (railShape == RailShape.NORTH_SOUTH) { //Order: +z, -z + for (int i = 0; i < NORTH_SOUTH_DIR.length; ++i) { + setRailPositionsPower(world, pos, checkedPos, count, i, NORTH_SOUTH_DIR[i]); + } + updateRails(false, world, pos, mainState, count); + } else if (railShape == RailShape.EAST_WEST) { //Order: -x, +x + for (int i = 0; i < EAST_WEST_DIR.length; ++i) { + setRailPositionsPower(world, pos, checkedPos, count, i, EAST_WEST_DIR[i]); + } + updateRails(true, world, pos, mainState, count); + } + } + + public void dePowerLane(Level world, BlockPos pos, BlockState mainState, RailShape railShape) { + world.setBlock(pos, mainState.setValue(PoweredRailBlock.POWERED, false), FORCE_PLACE); + int[] count = new int[2]; + if (railShape == RailShape.NORTH_SOUTH) { //Order: +z, -z + for (int i = 0; i < NORTH_SOUTH_DIR.length; ++i) { + setRailPositionsDePower(world, pos, count, i, NORTH_SOUTH_DIR[i]); + } + updateRails(false, world, pos, mainState, count); + } else if (railShape == RailShape.EAST_WEST) { //Order: -x, +x + for (int i = 0; i < EAST_WEST_DIR.length; ++i) { + setRailPositionsDePower(world, pos, count, i, EAST_WEST_DIR[i]); + } + updateRails(true, world, pos, mainState, count); + } + } + + private void setRailPositionsPower(Level world, BlockPos pos, HashMap checkedPos, + int[] count, int i, Direction direction) { + for (int z = 1; z < LeafConfig.railPowerLimit; z++) { + BlockPos newPos = pos.relative(direction, z); + BlockState state = world.getBlockState(newPos); + if (checkedPos.containsKey(newPos)) { + if (!checkedPos.get(newPos)) break; + count[i]++; + } else if (!state.is(this) || state.getValue(PoweredRailBlock.POWERED) || !( + world.hasNeighborSignal(newPos) || + this.findPoweredRailSignal(world, newPos, state, true, 0, checkedPos) || + this.findPoweredRailSignal(world, newPos, state, false, 0, checkedPos) + )) { + checkedPos.put(newPos, false); + break; + } else { + checkedPos.put(newPos, true); + world.setBlock(newPos, state.setValue(PoweredRailBlock.POWERED, true), FORCE_PLACE); + count[i]++; + } + } + } + + private void setRailPositionsDePower(Level world, BlockPos pos, int[] count, int i, Direction direction) { + for (int z = 1; z < LeafConfig.railPowerLimit; z++) { + BlockPos newPos = pos.relative(direction, z); + BlockState state = world.getBlockState(newPos); + if (!state.is(this) || !state.getValue(PoweredRailBlock.POWERED) || world.hasNeighborSignal(newPos) || + this.findPoweredRailSignal(world, newPos, state, true, 0) || + this.findPoweredRailSignal(world, newPos, state, false, 0)) break; + world.setBlock(newPos, state.setValue(PoweredRailBlock.POWERED, false), FORCE_PLACE); + count[i]++; + } + } + + private void shapeUpdateEnd(Level world, BlockPos pos, BlockState mainState, int endPos, + Direction direction, int currentPos, BlockPos blockPos) { + if (currentPos == endPos) { + BlockPos newPos = pos.relative(direction, currentPos + 1); + giveShapeUpdate(world, mainState, newPos, pos, direction); + BlockState state = world.getBlockState(blockPos); + if (state.is(this) && state.getValue(PoweredRailBlock.SHAPE).isAscending()) + giveShapeUpdate(world, mainState, newPos.above(), pos, direction); + } + } + + private void neighborUpdateEnd(Level world, BlockPos pos, int endPos, Direction direction, + Block block, int currentPos, BlockPos blockPos) { + if (currentPos == endPos) { + BlockPos newPos = pos.relative(direction, currentPos + 1); + world.neighborChanged(newPos, block, pos); + BlockState state = world.getBlockState(blockPos); + if (state.is(this) && state.getValue(PoweredRailBlock.SHAPE).isAscending()) + world.neighborChanged(newPos.above(), block, blockPos); + } + } + + private void updateRailsSectionEastWestShape(Level world, BlockPos pos, int c, BlockState mainState, + Direction dir, int[] count, int countAmt) { + BlockPos pos1 = pos.relative(dir, c); + if (c == 0 && count[1] == 0) + giveShapeUpdate(world, mainState, pos1.relative(dir.getOpposite()), pos, dir.getOpposite()); + shapeUpdateEnd(world, pos, mainState, countAmt, dir, c, pos1); + giveShapeUpdate(world, mainState, pos1.below(), pos, Direction.DOWN); + giveShapeUpdate(world, mainState, pos1.above(), pos, Direction.UP); + giveShapeUpdate(world, mainState, pos1.north(), pos, Direction.NORTH); + giveShapeUpdate(world, mainState, pos1.south(), pos, Direction.SOUTH); + } + + private void updateRailsSectionNorthSouthShape(Level world, BlockPos pos, int c, BlockState mainState, + Direction dir, int[] count, int countAmt) { + BlockPos pos1 = pos.relative(dir, c); + giveShapeUpdate(world, mainState, pos1.west(), pos, Direction.WEST); + giveShapeUpdate(world, mainState, pos1.east(), pos, Direction.EAST); + giveShapeUpdate(world, mainState, pos1.below(), pos, Direction.DOWN); + giveShapeUpdate(world, mainState, pos1.above(), pos, Direction.UP); + shapeUpdateEnd(world, pos, mainState, countAmt, dir, c, pos1); + if (c == 0 && count[1] == 0) + giveShapeUpdate( + world, mainState, pos1.relative(dir.getOpposite()), pos, dir.getOpposite() + ); + } + + private void updateRails(boolean eastWest, Level world, BlockPos pos, BlockState mainState, int[] count) { + if (eastWest) { + for (int i = 0; i < EAST_WEST_DIR.length; ++i) { + int countAmt = count[i]; + if (i == 1 && countAmt == 0) continue; + Direction dir = EAST_WEST_DIR[i]; + Block block = mainState.getBlock(); + for (int c = countAmt; c >= i; c--) { + BlockPos p = pos.relative(dir, c); + if (c == 0 && count[1] == 0) world.neighborChanged(p.relative(dir.getOpposite()), block, pos); + neighborUpdateEnd(world, pos, countAmt, dir, block, c, p); + world.neighborChanged(p.below(), block, pos); + world.neighborChanged(p.above(), block, pos); + world.neighborChanged(p.north(), block, pos); + world.neighborChanged(p.south(), block, pos); + BlockPos pos2 = pos.relative(dir, c).below(); + world.neighborChanged(pos2.below(), block, pos); + world.neighborChanged(pos2.north(), block, pos); + world.neighborChanged(pos2.south(), block, pos); + if (c == countAmt) world.neighborChanged(pos.relative(dir, c + 1).below(), block, pos); + if (c == 0 && count[1] == 0) + world.neighborChanged(p.relative(dir.getOpposite()).below(), block, pos); + } + if (LeafConfig.reIntroduceReverseRailUpdateOrder) { + for (int c = i; c <= countAmt; c++) + updateRailsSectionEastWestShape(world, pos, c, mainState, dir, count, countAmt); + } else { + for (int c = countAmt; c >= i; c--) + updateRailsSectionEastWestShape(world, pos, c, mainState, dir, count, countAmt); + } + } + } else { + for (int i = 0; i < NORTH_SOUTH_DIR.length; ++i) { + int countAmt = count[i]; + if (i == 1 && countAmt == 0) continue; + Direction dir = NORTH_SOUTH_DIR[i]; + Block block = mainState.getBlock(); + for (int c = countAmt; c >= i; c--) { + BlockPos p = pos.relative(dir, c); + world.neighborChanged(p.west(), block, pos); + world.neighborChanged(p.east(), block, pos); + world.neighborChanged(p.below(), block, pos); + world.neighborChanged(p.above(), block, pos); + neighborUpdateEnd(world, pos, countAmt, dir, block, c, p); + if (c == 0 && count[1] == 0) world.neighborChanged(p.relative(dir.getOpposite()), block, pos); + BlockPos pos2 = pos.relative(dir, c).below(); + world.neighborChanged(pos2.west(), block, pos); + world.neighborChanged(pos2.east(), block, pos); + world.neighborChanged(pos2.below(), block, pos); + if (c == countAmt) world.neighborChanged(pos.relative(dir, c + 1).below(), block, pos); + if (c == 0 && count[1] == 0) + world.neighborChanged(p.relative(dir.getOpposite()).below(), block, pos); + } + if (LeafConfig.reIntroduceReverseRailUpdateOrder) { + for (int c = i; c <= countAmt; c++) + updateRailsSectionNorthSouthShape(world, pos, c, mainState, dir, count, countAmt); + } else { + for (int c = countAmt; c >= i; c--) + updateRailsSectionNorthSouthShape(world, pos, c, mainState, dir, count, countAmt); + } + } + } + } } diff --git a/src/main/java/org/dreeam/leaf/LeafConfig.java b/src/main/java/org/dreeam/leaf/LeafConfig.java index 918631209956adae59b83dd28e7492290362311e..5d4984ce62bee757456a58cf84f24699c2a235e9 100644 --- a/src/main/java/org/dreeam/leaf/LeafConfig.java +++ b/src/main/java/org/dreeam/leaf/LeafConfig.java @@ -188,12 +188,18 @@ public class LeafConfig { public static boolean villagerLobotomizeEnabled = false; public static int villagerLobotomizeCheckInterval = 100; public static boolean useSpigotItemMergingMechanism = true; + public static int railPowerLimit = 9; + public static boolean optimizedPoweredRails = false; + public static boolean reIntroduceReverseRailUpdateOrder = false; private static void performance() { laggingThreshold = getDouble("performance.lagging-threshold", laggingThreshold); tpsCatchup = getBoolean("performance.tps-catchup", tpsCatchup); villagerLobotomizeEnabled = getBoolean("performance.villager.lobotomize.enabled", villagerLobotomizeEnabled); villagerLobotomizeCheckInterval = getInt("performance.villager.lobotomize.check-interval", villagerLobotomizeCheckInterval); useSpigotItemMergingMechanism = getBoolean("performance.use-spigot-item-merging-mechanism", useSpigotItemMergingMechanism); + railPowerLimit = getInt("performance.railPowerLimit", railPowerLimit); + optimizedPoweredRails = getBoolean("performance.optimizedPoweredRails", optimizedPoweredRails); + reIntroduceReverseRailUpdateOrder = getBoolean("performance.reIntroduceReverseRailUpdateOrder", reIntroduceReverseRailUpdateOrder); } public static String commandTPSBarOutput = "Tpsbar toggled for ";