mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-27 15:00:13 +01:00
Update Optimise-collision-checking, apply more updated patches
This commit is contained in:
parent
4b51927783
commit
7daedfcbc3
6 changed files with 61 additions and 62 deletions
|
@ -1,65 +1,64 @@
|
||||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
||||||
Date: Thu, 2 Jul 2020 12:02:43 -0700
|
Date: Thu, 2 Jul 2020 12:02:43 -0700
|
||||||
Subject: [PATCH] Optimise collision checking in player move packet handling
|
Subject: [PATCH] Optimise collision checking in player move packet handling
|
||||||
|
|
||||||
Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision
|
Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision
|
||||||
|
|
||||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
|
index 083585a6ab84394a2bc2de6f317c69c7b596e917..b7365e8b410a9e37257cf0a4e79a6f4f82dbbefb 100644
|
||||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
@@ -562,7 +562,7 @@ public class ServerGamePacketListenerImpl
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
- boolean flag = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D));
|
- boolean flag = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625));
|
||||||
+ AABB oldBox = entity.getBoundingBox(); // Paper - copy from player movement packet
|
+ AABB oldBox = rootVehicle.getBoundingBox(); // Paper - copy from player movement packet
|
||||||
|
d3 = d - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
|
||||||
d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
|
d4 = d1 - this.vehicleLastGoodY; // Paper - diff on change, used for checking large move vectors above
|
||||||
d7 = d4 - this.vehicleLastGoodY; // Paper - diff on change, used for checking large move vectors above
|
d5 = d2 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
|
||||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
@@ -572,6 +572,7 @@ public class ServerGamePacketListenerImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
|
rootVehicle.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
|
||||||
+ boolean didCollide = toX != entity.getX() || toY != entity.getY() || toZ != entity.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
|
+ boolean didCollide = toX != rootVehicle.getX() || toY != rootVehicle.getY() || toZ != rootVehicle.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
|
||||||
double d11 = d7;
|
d3 = d - rootVehicle.getX();
|
||||||
|
d4 = d1 - rootVehicle.getY();
|
||||||
d6 = d3 - entity.getX();
|
if (d4 > -0.5 || d4 < 0.5) {
|
||||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
@@ -582,14 +583,22 @@ public class ServerGamePacketListenerImpl
|
||||||
|
d7 = d3 * d3 + d4 * d4 + d5 * d5;
|
||||||
boolean flag2 = false;
|
boolean flag2 = false;
|
||||||
|
if (d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
|
||||||
if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
|
|
||||||
- flag2 = true;
|
- flag2 = true;
|
||||||
+ flag2 = true; // Paper - diff on change, this should be moved wrongly
|
+ flag2 = true; // Paper - diff on change, this should be moved wrongly
|
||||||
ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", new Object[]{entity.getName().getString(), this.player.getName().getString(), Math.sqrt(d10)});
|
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7));
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.absMoveTo(d3, d4, d5, f, f1);
|
rootVehicle.absMoveTo(d, d1, d2, f, f1);
|
||||||
this.player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
|
this.player.absMoveTo(d, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
|
||||||
- boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D));
|
- boolean flag3 = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625));
|
||||||
|
|
||||||
- if (flag && (flag2 || !flag3)) {
|
- if (flag && (flag2 || !flag3)) {
|
||||||
+ // Paper start - optimise out extra getCubes
|
+ // Paper start - optimise out extra getCubes
|
||||||
+ boolean teleportBack = flag2; // violating this is always a fail
|
+ boolean teleportBack = flag2; // violating this is always a fail
|
||||||
+ if (!teleportBack) {
|
+ if (!teleportBack) {
|
||||||
+ // note: only call after setLocation, or else getBoundingBox is wrong
|
+ // note: only call after setLocation, or else getBoundingBox is wrong
|
||||||
+ AABB newBox = entity.getBoundingBox();
|
+ AABB newBox = rootVehicle.getBoundingBox();
|
||||||
+ if (didCollide || !oldBox.equals(newBox)) {
|
+ if (didCollide || !oldBox.equals(newBox)) {
|
||||||
+ teleportBack = this.hasNewCollision(worldserver, entity, oldBox, newBox);
|
+ teleportBack = this.hasNewCollision(serverLevel, rootVehicle, oldBox, newBox);
|
||||||
+ } // else: no collision at all detected, why do we care?
|
+ } // else: no collision at all detected, why do we care?
|
||||||
+ }
|
+ }
|
||||||
+ if (teleportBack) { // Paper end - optimise out extra getCubes
|
+ if (teleportBack) { // Paper end - optimise out extra getCubes
|
||||||
entity.absMoveTo(d0, d1, d2, f, f1);
|
rootVehicle.absMoveTo(x, y, z, f, f1);
|
||||||
this.player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
|
this.player.absMoveTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
|
||||||
this.send(ClientboundMoveVehiclePacket.fromEntity(entity));
|
this.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle));
|
||||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
@@ -667,9 +676,32 @@ public class ServerGamePacketListenerImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean noBlocksAround(Entity entity) {
|
private boolean noBlocksAround(Entity entity) {
|
||||||
- return entity.level().getBlockStates(entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D)).allMatch(BlockBehaviour.BlockStateBase::isAir);
|
- return entity.level()
|
||||||
|
- .getBlockStates(entity.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0))
|
||||||
|
- .allMatch(BlockBehaviour.BlockStateBase::isAir);
|
||||||
+ // Paper start - stop using streams, this is already a known fixed problem in Entity#move
|
+ // Paper start - stop using streams, this is already a known fixed problem in Entity#move
|
||||||
+ AABB box = entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D);
|
+ AABB box = entity.getBoundingBox().inflate(0.0625).expandTowards(0.0, -0.55, 0.0);
|
||||||
+ int minX = Mth.floor(box.minX);
|
+ int minX = Mth.floor(box.minX);
|
||||||
+ int minY = Mth.floor(box.minY);
|
+ int minY = Mth.floor(box.minY);
|
||||||
+ int minZ = Mth.floor(box.minZ);
|
+ int minZ = Mth.floor(box.minZ);
|
||||||
|
@ -67,15 +66,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
+ int maxY = Mth.floor(box.maxY);
|
+ int maxY = Mth.floor(box.maxY);
|
||||||
+ int maxZ = Mth.floor(box.maxZ);
|
+ int maxZ = Mth.floor(box.maxZ);
|
||||||
+
|
+
|
||||||
+ Level world = entity.level();
|
+ Level level = entity.level();
|
||||||
+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
||||||
+
|
+
|
||||||
+ for (int y = minY; y <= maxY; ++y) {
|
+ for (int y = minY; y <= maxY; ++y) {
|
||||||
+ for (int z = minZ; z <= maxZ; ++z) {
|
+ for (int z = minZ; z <= maxZ; ++z) {
|
||||||
+ for (int x = minX; x <= maxX; ++x) {
|
+ for (int x = minX; x <= maxX; ++x) {
|
||||||
+ pos.set(x, y, z);
|
+ pos.set(x, y, z);
|
||||||
+ BlockState type = world.getBlockStateIfLoaded(pos);
|
+ BlockState blockState = level.getBlockStateIfLoaded(pos);
|
||||||
+ if (type != null && !type.isAir()) {
|
+ if (blockState != null && !blockState.isAir()) {
|
||||||
+ return false;
|
+ return false;
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
|
@ -87,61 +86,61 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
@@ -1361,7 +1393,7 @@ public class ServerGamePacketListenerImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- AABB axisalignedbb = this.player.getBoundingBox();
|
- AABB boundingBox = this.player.getBoundingBox();
|
||||||
+ AABB axisalignedbb = this.player.getBoundingBox(); // Paper - diff on change, should be old AABB
|
+ AABB boundingBox = this.player.getBoundingBox(); // Paper - diff on change, should be old AABB
|
||||||
|
d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
|
||||||
d6 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
|
d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
|
||||||
d7 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
|
d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
|
||||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
@@ -1400,6 +1432,7 @@ public class ServerGamePacketListenerImpl
|
||||||
|
boolean flag1 = this.player.verticalCollisionBelow;
|
||||||
this.player.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
|
this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
|
||||||
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
|
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
|
||||||
+ boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
|
+ boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
|
||||||
// Paper start - prevent position desync
|
// Paper start - prevent position desync
|
||||||
if (this.awaitingPositionFromClient != null) {
|
if (this.awaitingPositionFromClient != null) {
|
||||||
return; // ... thanks Mojang for letting move calls teleport across dimensions.
|
return; // ... thanks Mojang for letting move calls teleport across dimensions.
|
||||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
@@ -1431,7 +1464,17 @@ public class ServerGamePacketListenerImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paper start - Add fail move event
|
// Paper start - Add fail move event
|
||||||
- boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2));
|
- boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && serverLevel.noCollision(this.player, boundingBox) || this.isPlayerCollidingWithAnythingNew(serverLevel, boundingBox, d, d1, d2));
|
||||||
+ // Paper start - optimise out extra getCubes
|
+ // Paper start - optimise out extra getCubes
|
||||||
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly;
|
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly;
|
||||||
+ this.player.absMoveTo(d0, d1, d2, f, f1); // prevent desync by tping to the set position, dropped for unknown reasons by mojang
|
+ this.player.absMoveTo(d, d1, d2, f, f1); // prevent desync by tping to the set position, dropped for unknown reasons by mojang
|
||||||
+ if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) {
|
+ if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) {
|
||||||
+ AABB newBox = this.player.getBoundingBox();
|
+ AABB newBox = this.player.getBoundingBox();
|
||||||
+ if (didCollide || !axisalignedbb.equals(newBox)) {
|
+ if (didCollide || !boundingBox.equals(newBox)) {
|
||||||
+ // note: only call after setLocation, or else getBoundingBox is wrong
|
+ // note: only call after setLocation, or else getBoundingBox is wrong
|
||||||
+ teleportBack = this.hasNewCollision(worldserver, this.player, axisalignedbb, newBox);
|
+ teleportBack = this.hasNewCollision(serverLevel, this.player, boundingBox, newBox);
|
||||||
+ } // else: no collision at all detected, why do we care?
|
+ } // else: no collision at all detected, why do we care?
|
||||||
+ }
|
+ }
|
||||||
+ // Paper end - optimise out extra getCubes
|
+ // Paper end - optimise out extra getCubes
|
||||||
if (teleportBack) {
|
if (teleportBack) {
|
||||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
|
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
|
||||||
toX, toY, toZ, toYaw, toPitch, false);
|
toX, toY, toZ, toYaw, toPitch, false);
|
||||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
@@ -1567,7 +1610,7 @@ public class ServerGamePacketListenerImpl
|
||||||
|
|
||||||
private boolean updateAwaitingTeleport() {
|
private boolean updateAwaitingTeleport() {
|
||||||
if (this.awaitingPositionFromClient != null) {
|
if (this.awaitingPositionFromClient != null) {
|
||||||
- if (this.tickCount - this.awaitingTeleportTime > 20) {
|
- if (this.tickCount - this.awaitingTeleportTime > 20) {
|
||||||
+ if (false && this.tickCount - this.awaitingTeleportTime > 20) { // Paper - this will greatly screw with clients with > 1000ms RTT
|
+ if (false && this.tickCount - this.awaitingTeleportTime > 20) { // Paper - this will greatly screw with clients with > 1000ms RTT
|
||||||
this.awaitingTeleportTime = this.tickCount;
|
this.awaitingTeleportTime = this.tickCount;
|
||||||
this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot());
|
this.teleport(
|
||||||
}
|
this.awaitingPositionFromClient.x,
|
||||||
@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
@@ -1586,6 +1629,33 @@ public class ServerGamePacketListenerImpl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ // Paper start - optimise out extra getCubes
|
+ // Paper start - optimise out extra getCubes
|
||||||
+ private boolean hasNewCollision(final ServerLevel world, final Entity entity, final AABB oldBox, final AABB newBox) {
|
+ private boolean hasNewCollision(final ServerLevel level, final Entity entity, final AABB oldBox, final AABB newBox) {
|
||||||
+ final List<AABB> collisionsBB = new java.util.ArrayList<>();
|
+ final List<AABB> collisionsBB = new java.util.ArrayList<>();
|
||||||
+ final List<VoxelShape> collisionsVoxel = new java.util.ArrayList<>();
|
+ final List<VoxelShape> collisionsVoxel = new java.util.ArrayList<>();
|
||||||
+ ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.getCollisions(
|
+ ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.getCollisions(
|
||||||
+ world, entity, newBox, collisionsVoxel, collisionsBB,
|
+ level, entity, newBox, collisionsVoxel, collisionsBB,
|
||||||
+ ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS | ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_FLAG_CHECK_BORDER,
|
+ ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS | ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_FLAG_CHECK_BORDER,
|
||||||
+ null, null
|
+ null, null
|
||||||
+ );
|
+ );
|
||||||
|
@ -163,6 +162,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
|
||||||
+ return false;
|
+ return false;
|
||||||
+ }
|
+ }
|
||||||
+ // Paper end - optimise out extra getCubes
|
+ // Paper end - optimise out extra getCubes
|
||||||
private boolean isPlayerCollidingWithAnythingNew(LevelReader world, AABB box, double newX, double newY, double newZ) {
|
private boolean isPlayerCollidingWithAnythingNew(LevelReader level, AABB box, double x, double y, double z) {
|
||||||
AABB axisalignedbb1 = this.player.getBoundingBox().move(newX - this.player.getX(), newY - this.player.getY(), newZ - this.player.getZ());
|
AABB aabb = this.player.getBoundingBox().move(x - this.player.getX(), y - this.player.getY(), z - this.player.getZ());
|
||||||
Iterable<VoxelShape> iterable = world.getCollisions(this.player, axisalignedbb1.deflate(9.999999747378752E-6D));
|
Iterable<VoxelShape> collisions = level.getCollisions(this.player, aabb.deflate(1.0E-5F));
|
||||||
|
|
|
@ -2434,7 +2434,7 @@ index f02232ce97779db0d12a5d5da1d767326d78ea4c..12c9d60314c99fb65e640d255a2d0c6b
|
||||||
dropResources(state, level, pos);
|
dropResources(state, level, pos);
|
||||||
level.removeBlock(pos, false);
|
level.removeBlock(pos, false);
|
||||||
diff --git a/net/minecraft/world/level/redstone/ExperimentalRedstoneUtils.java b/net/minecraft/world/level/redstone/ExperimentalRedstoneUtils.java
|
diff --git a/net/minecraft/world/level/redstone/ExperimentalRedstoneUtils.java b/net/minecraft/world/level/redstone/ExperimentalRedstoneUtils.java
|
||||||
index 83f5da3e24834882193b9d7e3a788517e4b12b55..db7a7b091d2eb0f5b7efbe0db2b91709dee688e8 100644
|
index 83f5da3e24834882193b9d7e3a788517e4b12b55..0c50a0bbbef1229230712b7c04364fea06859674 100644
|
||||||
--- a/net/minecraft/world/level/redstone/ExperimentalRedstoneUtils.java
|
--- a/net/minecraft/world/level/redstone/ExperimentalRedstoneUtils.java
|
||||||
+++ b/net/minecraft/world/level/redstone/ExperimentalRedstoneUtils.java
|
+++ b/net/minecraft/world/level/redstone/ExperimentalRedstoneUtils.java
|
||||||
@@ -17,6 +17,11 @@ public class ExperimentalRedstoneUtils {
|
@@ -17,6 +17,11 @@ public class ExperimentalRedstoneUtils {
|
||||||
|
@ -2442,7 +2442,7 @@ index 83f5da3e24834882193b9d7e3a788517e4b12b55..db7a7b091d2eb0f5b7efbe0db2b91709
|
||||||
orientation = orientation.withFront(front);
|
orientation = orientation.withFront(front);
|
||||||
}
|
}
|
||||||
+ // Paper start - Optimize redstone (Alternate Current) - use default front instead of random
|
+ // Paper start - Optimize redstone (Alternate Current) - use default front instead of random
|
||||||
+ else if (world.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) {
|
+ else if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) {
|
||||||
+ orientation = orientation.withFront(Direction.WEST);
|
+ orientation = orientation.withFront(Direction.WEST);
|
||||||
+ }
|
+ }
|
||||||
+ // Paper end - Optimize redstone (Alternate Current)
|
+ // Paper end - Optimize redstone (Alternate Current)
|
Loading…
Reference in a new issue