Mirror von
https://github.com/PaperMC/Paper.git
synchronisiert 2024-11-15 04:20:04 +01:00
More more patches, including hopper optimization patch
Dieser Commit ist enthalten in:
Ursprung
c9907c650f
Commit
2debcaff9d
@ -5,12 +5,12 @@ Subject: [PATCH] Use Velocity compression and cipher natives
|
||||
|
||||
|
||||
diff --git a/build.gradle.kts b/build.gradle.kts
|
||||
index f9056ee057a22a11288405cd42cd0ba4c9d120c3..bcfe59b6efb628ee1e7f9d60667360d4d885fb6a 100644
|
||||
index 2fb342f9d86e169571070b2b40538633f4b0d7cf..e2e3abe6a4b837fcef96ce7da6679b14afba0519 100644
|
||||
--- a/build.gradle.kts
|
||||
+++ b/build.gradle.kts
|
||||
@@ -40,6 +40,11 @@ dependencies {
|
||||
runtimeOnly("org.xerial:sqlite-jdbc:3.42.0.1")
|
||||
runtimeOnly("com.mysql:mysql-connector-j:8.2.0")
|
||||
@@ -38,6 +38,11 @@ dependencies {
|
||||
implementation("org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT") // Paper - config files
|
||||
implementation("commons-lang:commons-lang:2.6")
|
||||
runtimeOnly("com.lmax:disruptor:3.4.4") // Paper
|
||||
+ // Paper start - Use Velocity cipher
|
||||
+ implementation("com.velocitypowered:velocity-native:3.1.2-SNAPSHOT") {
|
||||
@ -102,14 +102,14 @@ index 0f3d502a9680006bcdcd7d272240a2e5c3b46790..ffa1c48585fbbc1d30826d435043527f
|
||||
+ // Paper end - Use Velocity cipher
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/network/CompressionDecoder.java b/src/main/java/net/minecraft/network/CompressionDecoder.java
|
||||
index 5927c928b27f64bd3973e95d5867b59f67476d41..76aeebe60ac321ed604661a0ec969bb25210643f 100644
|
||||
index 5927c928b27f64bd3973e95d5867b59f67476d41..ba3619b03ea73e4ea55ae2eb79d3b6cd1f48a191 100644
|
||||
--- a/src/main/java/net/minecraft/network/CompressionDecoder.java
|
||||
+++ b/src/main/java/net/minecraft/network/CompressionDecoder.java
|
||||
@@ -13,13 +13,20 @@ public class CompressionDecoder extends ByteToMessageDecoder {
|
||||
public static final int MAXIMUM_COMPRESSED_LENGTH = 2097152;
|
||||
public static final int MAXIMUM_UNCOMPRESSED_LENGTH = 8388608;
|
||||
private final Inflater inflater;
|
||||
+ private final com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper - Use Velocity cipher
|
||||
+ private com.velocitypowered.natives.compression.VelocityCompressor compressor; // Paper - Use Velocity cipher
|
||||
private int threshold;
|
||||
private boolean validateDecompressed;
|
||||
|
||||
@ -170,11 +170,20 @@ index 5927c928b27f64bd3973e95d5867b59f67476d41..76aeebe60ac321ed604661a0ec969bb2
|
||||
private void setupInflaterInput(ByteBuf buf) {
|
||||
ByteBuffer byteBuffer;
|
||||
if (buf.nioBufferCount() > 0) {
|
||||
@@ -82,7 +117,7 @@ public class CompressionDecoder extends ByteToMessageDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
- public void setThreshold(int compressionThreshold, boolean rejectsBadPackets) {
|
||||
+ public void setThreshold(com.velocitypowered.natives.compression.VelocityCompressor compressor, int compressionThreshold, boolean rejectsBadPackets) { // Paper - Use Velocity cipher
|
||||
this.threshold = compressionThreshold;
|
||||
this.validateDecompressed = rejectsBadPackets;
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/network/CompressionEncoder.java b/src/main/java/net/minecraft/network/CompressionEncoder.java
|
||||
index 11a466558c77b43969b8e4be3a3470f84c7fcb1a..ae6e8ab9c1afa31d808f1fce2654a8b95bee6c31 100644
|
||||
index 34a80d2f34555663ab1b394972957089214cb337..ec30c291188ac3bba7f1c3bc397576d1edb0a57f 100644
|
||||
--- a/src/main/java/net/minecraft/network/CompressionEncoder.java
|
||||
+++ b/src/main/java/net/minecraft/network/CompressionEncoder.java
|
||||
@@ -6,21 +6,37 @@ import io.netty.handler.codec.MessageToByteEncoder;
|
||||
@@ -6,16 +6,31 @@ import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
@ -207,7 +216,9 @@ index 11a466558c77b43969b8e4be3a3470f84c7fcb1a..ae6e8ab9c1afa31d808f1fce2654a8b9
|
||||
- protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) {
|
||||
+ protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, ByteBuf byteBuf2) throws Exception { // Paper - Use Velocity cipher
|
||||
int i = byteBuf.readableBytes();
|
||||
if (i < this.threshold) {
|
||||
if (i > 8388608) {
|
||||
throw new IllegalArgumentException("Packet too big (is " + i + ", should be less than 8388608)");
|
||||
@@ -24,6 +39,7 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
VarInt.write(byteBuf2, 0);
|
||||
byteBuf2.writeBytes(byteBuf);
|
||||
} else {
|
||||
@ -215,7 +226,7 @@ index 11a466558c77b43969b8e4be3a3470f84c7fcb1a..ae6e8ab9c1afa31d808f1fce2654a8b9
|
||||
byte[] bs = new byte[i];
|
||||
byteBuf.readBytes(bs);
|
||||
VarInt.write(byteBuf2, bs.length);
|
||||
@@ -33,6 +49,43 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
@@ -36,10 +52,47 @@ public class CompressionEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
}
|
||||
|
||||
this.deflater.reset();
|
||||
@ -224,15 +235,16 @@ index 11a466558c77b43969b8e4be3a3470f84c7fcb1a..ae6e8ab9c1afa31d808f1fce2654a8b9
|
||||
+ }
|
||||
+
|
||||
+ VarInt.write(byteBuf2, i);
|
||||
+ ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf);
|
||||
+ final ByteBuf compatibleIn = com.velocitypowered.natives.util.MoreByteBufUtils.ensureCompatible(channelHandlerContext.alloc(), this.compressor, byteBuf);
|
||||
+ try {
|
||||
+ this.compressor.deflate(compatibleIn, byteBuf2);
|
||||
+ } finally {
|
||||
+ compatibleIn.release();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ @Override
|
||||
+ protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect) throws Exception{
|
||||
+ if (this.compressor != null) {
|
||||
@ -244,7 +256,7 @@ index 11a466558c77b43969b8e4be3a3470f84c7fcb1a..ae6e8ab9c1afa31d808f1fce2654a8b9
|
||||
+ // size the compressed size will ever be is the input size minus one.
|
||||
+ // - Uncompressed
|
||||
+ // This is fairly obvious - we will then have one more than the uncompressed size.
|
||||
+ int initialBufferSize = msg.readableBytes() + 1;
|
||||
+ final int initialBufferSize = msg.readableBytes() + 1;
|
||||
+ return com.velocitypowered.natives.util.MoreByteBufUtils.preferredBuffer(ctx.alloc(), this.compressor, initialBufferSize);
|
||||
+ }
|
||||
+
|
||||
@ -256,14 +268,17 @@ index 11a466558c77b43969b8e4be3a3470f84c7fcb1a..ae6e8ab9c1afa31d808f1fce2654a8b9
|
||||
+ if (this.compressor != null) {
|
||||
+ this.compressor.close();
|
||||
+ // Paper end - Use Velocity cipher
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
public int getThreshold() {
|
||||
return this.threshold;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index 16eb94eb1f40485daef2713f740f6e0beeb1463f..fae2a57570a4007b67b9949b9b16504da36a9886 100644
|
||||
index f94458d4270042062b9ae18931cc8179ef1fb420..63066dfde00569833546da01cd580434f8be6593 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -735,11 +735,28 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -763,11 +763,28 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
return networkmanager;
|
||||
}
|
||||
|
||||
@ -296,28 +311,32 @@ index 16eb94eb1f40485daef2713f740f6e0beeb1463f..fae2a57570a4007b67b9949b9b16504d
|
||||
|
||||
public boolean isEncrypted() {
|
||||
return this.encrypted;
|
||||
@@ -772,16 +789,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -800,12 +817,13 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
|
||||
public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) {
|
||||
if (compressionThreshold >= 0) {
|
||||
+ com.velocitypowered.natives.compression.VelocityCompressor compressor = com.velocitypowered.natives.util.Natives.compress.get().create(io.papermc.paper.configuration.GlobalConfiguration.get().misc.compressionLevel.or(-1)); // Paper - Use Velocity cipher
|
||||
if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) {
|
||||
((CompressionDecoder) this.channel.pipeline().get("decompress")).setThreshold(compressionThreshold, rejectsBadPackets);
|
||||
} else {
|
||||
- this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressionThreshold, rejectsBadPackets));
|
||||
+ this.channel.pipeline().addBefore("decoder", "decompress", new CompressionDecoder(compressor, compressionThreshold, rejectsBadPackets)); // Paper - Use Velocity cipher
|
||||
}
|
||||
ChannelHandler channelhandler = this.channel.pipeline().get("decompress");
|
||||
|
||||
if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) {
|
||||
((CompressionEncoder) this.channel.pipeline().get("compress")).setThreshold(compressionThreshold);
|
||||
if (channelhandler instanceof CompressionDecoder) {
|
||||
CompressionDecoder packetdecompressor = (CompressionDecoder) channelhandler;
|
||||
|
||||
- packetdecompressor.setThreshold(compressionThreshold, rejectsBadPackets);
|
||||
+ packetdecompressor.setThreshold(compressor, compressionThreshold, rejectsBadPackets); // Paper - Use Velocity cipher
|
||||
} else {
|
||||
- this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressionThreshold));
|
||||
+ this.channel.pipeline().addBefore("encoder", "compress", new CompressionEncoder(compressor, compressionThreshold)); // Paper - Use Velocity cipher
|
||||
this.channel.pipeline().addAfter("splitter", "decompress", new CompressionDecoder(compressionThreshold, rejectsBadPackets));
|
||||
}
|
||||
@@ -816,7 +834,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
|
||||
packetcompressor.setThreshold(compressionThreshold);
|
||||
} else {
|
||||
- this.channel.pipeline().addAfter("prepender", "compress", new CompressionEncoder(compressionThreshold));
|
||||
+ this.channel.pipeline().addAfter("prepender", "compress", new CompressionEncoder(compressor, compressionThreshold)); // Paper - Use Velocity cipher
|
||||
}
|
||||
this.channel.pipeline().fireUserEventTriggered(io.papermc.paper.network.ConnectionEvent.COMPRESSION_THRESHOLD_SET); // Paper - Add Channel initialization listeners
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
index a4a29a7ea0035ecf4c61ee8547a9eb24acb667d0..586521a2cbb1d4dcfb912029f65e4363ec7674a7 100644
|
||||
index a08d9aa6e420f691795df9b627a9cd5b5c0112c5..52f537b7bfbdeaad9d17c0e88a1ed1c8925a833f 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java
|
||||
@@ -106,6 +106,11 @@ public class ServerConnectionListener {
|
||||
@ -331,12 +350,12 @@ index a4a29a7ea0035ecf4c61ee8547a9eb24acb667d0..586521a2cbb1d4dcfb912029f65e4363
|
||||
+
|
||||
this.channels.add(((ServerBootstrap) ((ServerBootstrap) (new ServerBootstrap()).channel(oclass)).childHandler(new ChannelInitializer<Channel>() {
|
||||
protected void initChannel(Channel channel) {
|
||||
Connection.setInitialProtocolAttributes(channel);
|
||||
try {
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
index b8d8f14c30786321949901ca5184c43bee716355..c5fa9f4d28f9a7f64a50a902ee5e631bfc00119c 100644
|
||||
index 21d97c2b533a6528dd73c4e514d49273c120e171..cb25d42ba40bd0901bbe0d8399e5d8e87988706f 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerLoginPacketListenerImpl.java
|
||||
@@ -235,12 +235,14 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
@@ -274,12 +274,14 @@ public class ServerLoginPacketListenerImpl implements ServerLoginPacketListener,
|
||||
}
|
||||
|
||||
SecretKey secretkey = packet.getSecretKey(privatekey);
|
@ -7,28 +7,28 @@ Subject: [PATCH] Detail more information in watchdog dumps
|
||||
- Dump player name, player uuid, position, and world for packet handling
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
|
||||
index fae2a57570a4007b67b9949b9b16504da36a9886..a536ebcf29d8ef0ed32863bd8d5e70f7a0636e8d 100644
|
||||
index 63066dfde00569833546da01cd580434f8be6593..7fb162fa031fd76aa9a94f5fdaa3e32ceb9b9abc 100644
|
||||
--- a/src/main/java/net/minecraft/network/Connection.java
|
||||
+++ b/src/main/java/net/minecraft/network/Connection.java
|
||||
@@ -587,7 +587,13 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
@@ -607,7 +607,13 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
|
||||
if (!(this.packetListener instanceof net.minecraft.server.network.ServerLoginPacketListenerImpl loginPacketListener)
|
||||
|| loginPacketListener.state != net.minecraft.server.network.ServerLoginPacketListenerImpl.State.VERIFYING
|
||||
|| Connection.joinAttemptsThisTick++ < MAX_PER_TICK) {
|
||||
+ // Paper start - detailed watchdog information
|
||||
+ net.minecraft.network.protocol.PacketUtils.packetProcessing.push(this.packetListener);
|
||||
+ try { // Paper end - detailed watchdog information
|
||||
+ try {
|
||||
tickablepacketlistener.tick();
|
||||
+ } finally { // Paper start - detailed watchdog information
|
||||
+ } finally {
|
||||
+ net.minecraft.network.protocol.PacketUtils.packetProcessing.pop();
|
||||
+ } // Paper end - detailed watchdog information
|
||||
} // Paper end - Buffer joins to world
|
||||
}
|
||||
// Paper end - Buffer joins to world
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
|
||||
index b7ffab0284b0bccd79775b8d03c8b2e088f91d1d..83302c252f54481f239522e5c6861ccfe233070a 100644
|
||||
index e161ad0f53a21a68e8c78575ba5d3cdbdb11fca0..57e76b53e5e314c3e6b8856010f7a84188121582 100644
|
||||
--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
|
||||
+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
|
||||
@@ -18,6 +18,24 @@ public class PacketUtils {
|
||||
@@ -19,6 +19,24 @@ public class PacketUtils {
|
||||
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
@ -53,7 +53,7 @@ index b7ffab0284b0bccd79775b8d03c8b2e088f91d1d..83302c252f54481f239522e5c6861ccf
|
||||
public PacketUtils() {}
|
||||
|
||||
public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, ServerLevel world) throws RunningOnDifferentThreadException {
|
||||
@@ -27,6 +45,8 @@ public class PacketUtils {
|
||||
@@ -28,6 +46,8 @@ public class PacketUtils {
|
||||
public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, BlockableEventLoop<?> engine) throws RunningOnDifferentThreadException {
|
||||
if (!engine.isSameThread()) {
|
||||
engine.executeIfPossible(() -> {
|
||||
@ -62,7 +62,7 @@ index b7ffab0284b0bccd79775b8d03c8b2e088f91d1d..83302c252f54481f239522e5c6861ccf
|
||||
if (listener instanceof ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // CraftBukkit - Don't handle sync packets for kicked players
|
||||
if (listener.shouldHandleMessage(packet)) {
|
||||
co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings
|
||||
@@ -64,6 +84,12 @@ public class PacketUtils {
|
||||
@@ -47,6 +67,12 @@ public class PacketUtils {
|
||||
} else {
|
||||
PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet);
|
||||
}
|
||||
@ -76,10 +76,10 @@ index b7ffab0284b0bccd79775b8d03c8b2e088f91d1d..83302c252f54481f239522e5c6861ccf
|
||||
});
|
||||
throw RunningOnDifferentThreadException.RUNNING_ON_DIFFERENT_THREAD;
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 9d18da228c6709e7665ba8babb6ee6d0b36b5dc5..af9f58328c09dddb2875f79128f906b8b276ab88 100644
|
||||
index 16d24e70072e3846b3c35d331c3f474238a8def2..98fded81545a96deb6a05df713a5b69e27189cf4 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -1239,7 +1239,26 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
@@ -1245,7 +1245,26 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
|
||||
}
|
||||
|
||||
@ -106,7 +106,7 @@ index 9d18da228c6709e7665ba8babb6ee6d0b36b5dc5..af9f58328c09dddb2875f79128f906b8
|
||||
++TimingHistory.entityTicks; // Paper - timings
|
||||
// Spigot start
|
||||
co.aikar.timings.Timing timer; // Paper
|
||||
@@ -1279,7 +1298,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
@@ -1285,7 +1304,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
this.tickPassenger(entity, entity1);
|
||||
}
|
||||
// } finally { timer.stopTiming(); } // Paper - timings - move up
|
||||
@ -122,10 +122,10 @@ index 9d18da228c6709e7665ba8babb6ee6d0b36b5dc5..af9f58328c09dddb2875f79128f906b8
|
||||
|
||||
private void tickPassenger(Entity vehicle, Entity passenger) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index ab8a736bd8da140c48e6bd66449d7aa3b4f29a16..9a01eff5a93c68edd45f98e9a6f8d24656650fb6 100644
|
||||
index 257943b4c984d6faee29eca17c8f951e7f43168b..0fbcf60a994f67bdd81d40e4a8bf38f0cbb8993d 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -1063,8 +1063,43 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
@@ -1074,8 +1074,43 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
return this.onGround;
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ index ab8a736bd8da140c48e6bd66449d7aa3b4f29a16..9a01eff5a93c68edd45f98e9a6f8d246
|
||||
if (this.noPhysics) {
|
||||
this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z);
|
||||
} else {
|
||||
@@ -1234,6 +1269,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
@@ -1245,6 +1280,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
this.level().getProfiler().pop();
|
||||
}
|
||||
}
|
||||
@ -183,7 +183,7 @@ index ab8a736bd8da140c48e6bd66449d7aa3b4f29a16..9a01eff5a93c68edd45f98e9a6f8d246
|
||||
}
|
||||
|
||||
private boolean isStateClimbable(BlockState state) {
|
||||
@@ -4379,7 +4421,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
@@ -4405,7 +4447,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
public void setDeltaMovement(Vec3 velocity) {
|
||||
@ -193,7 +193,7 @@ index ab8a736bd8da140c48e6bd66449d7aa3b4f29a16..9a01eff5a93c68edd45f98e9a6f8d246
|
||||
}
|
||||
|
||||
public void addDeltaMovement(Vec3 velocity) {
|
||||
@@ -4482,7 +4526,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
@@ -4508,7 +4552,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
// Paper end - Fix MC-4
|
||||
if (this.position.x != x || this.position.y != y || this.position.z != z) {
|
||||
@ -204,7 +204,7 @@ index ab8a736bd8da140c48e6bd66449d7aa3b4f29a16..9a01eff5a93c68edd45f98e9a6f8d246
|
||||
int j = Mth.floor(y);
|
||||
int k = Mth.floor(z);
|
||||
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
index 0234555978d1b13051f876a257e47bafad37b0f8..9e638f72f180ff5ef63ec3dd6cf548c53f7bd4a5 100644
|
||||
index 577f29519156f33b49ee319a64a52249630e28d8..6db566e3111ec08a99aa429624979cb83a85e272 100644
|
||||
--- a/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
|
||||
@@ -22,6 +22,78 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
|
@ -2153,10 +2153,10 @@ index 0000000000000000000000000000000000000000..1f42bdfdb052056e62a939ab0d1944f8
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java
|
||||
index 75694cfd7d8adde6b9246518c20fe75774297a57..84a760fdc50bdafc9150f977e9c5d557a30ee220 100644
|
||||
index 03c45ee77276462818a6f774b5945b25924aa3f0..ab289a6ca85459e03acb2089c6b9e931caa9c873 100644
|
||||
--- a/src/main/java/net/minecraft/core/Direction.java
|
||||
+++ b/src/main/java/net/minecraft/core/Direction.java
|
||||
@@ -53,6 +53,21 @@ public enum Direction implements StringRepresentable {
|
||||
@@ -60,6 +60,21 @@ public enum Direction implements StringRepresentable {
|
||||
private final int adjY;
|
||||
private final int adjZ;
|
||||
// Paper end - Perf: Inline shift direction fields
|
||||
@ -2176,13 +2176,13 @@ index 75694cfd7d8adde6b9246518c20fe75774297a57..84a760fdc50bdafc9150f977e9c5d557
|
||||
+ }
|
||||
+ // Paper end - optimise collisions
|
||||
|
||||
private Direction(int id, int idOpposite, int idHorizontal, String name, Direction.AxisDirection direction, Direction.Axis axis, Vec3i vector) {
|
||||
this.data3d = id;
|
||||
private Direction(
|
||||
final int id,
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
index acc1751324f040accc4fc18914ed281e572358eb..17a6d43685f35a6978c2d941876a1f8a9a2c8b42 100644
|
||||
index e06b9b0c7b1c3a200b89819e0e521f1c88dc981b..ed42a78aebeda86b77f27cba4fcefbc6c17f86fc 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
|
||||
@@ -496,7 +496,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -512,7 +512,7 @@ public class ServerPlayer extends Player {
|
||||
|
||||
if (blockposition1 != null) {
|
||||
this.moveTo(blockposition1, world.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored
|
||||
@ -2191,7 +2191,7 @@ index acc1751324f040accc4fc18914ed281e572358eb..17a6d43685f35a6978c2d941876a1f8a
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -504,7 +504,7 @@ public class ServerPlayer extends Player {
|
||||
@@ -520,7 +520,7 @@ public class ServerPlayer extends Player {
|
||||
} else {
|
||||
this.moveTo(blockposition, world.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored
|
||||
|
||||
@ -2201,10 +2201,10 @@ index acc1751324f040accc4fc18914ed281e572358eb..17a6d43685f35a6978c2d941876a1f8a
|
||||
}
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 594cb6ce4bfa6c42212000a1ed983ea95ee2c4bf..97b0119ac71284b3a223c089bec26d87a01d3b25 100644
|
||||
index 3e3bca13578ab9e5b6ca0159383bee0b2a60a86e..c83ec24c0bf54f8699caa2d37bfe82d273f7b16c 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -936,7 +936,7 @@ public abstract class PlayerList {
|
||||
@@ -935,7 +935,7 @@ public abstract class PlayerList {
|
||||
entityplayer1.forceSetPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
|
||||
worldserver1.getChunkSource().addRegionTicket(net.minecraft.server.level.TicketType.POST_TELEPORT, new net.minecraft.world.level.ChunkPos(location.getBlockX() >> 4, location.getBlockZ() >> 4), 1, entityplayer.getId()); // Paper
|
||||
@ -2214,10 +2214,10 @@ index 594cb6ce4bfa6c42212000a1ed983ea95ee2c4bf..97b0119ac71284b3a223c089bec26d87
|
||||
entityplayer1.setPos(entityplayer1.getX(), entityplayer1.getY() + 1.0D, entityplayer1.getZ());
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 9a01eff5a93c68edd45f98e9a6f8d24656650fb6..7992375dc55492aeb6defb204b28dd267be4a6e7 100644
|
||||
index 0fbcf60a994f67bdd81d40e4a8bf38f0cbb8993d..8ad2d17615ff489b2fbbb13480dd0b217a42d805 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -1250,9 +1250,44 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
@@ -1261,9 +1261,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
float f = this.getBlockSpeedFactor();
|
||||
|
||||
this.setDeltaMovement(this.getDeltaMovement().multiply((double) f, 1.0D, (double) f));
|
||||
@ -2265,7 +2265,7 @@ index 9a01eff5a93c68edd45f98e9a6f8d24656650fb6..7992375dc55492aeb6defb204b28dd26
|
||||
if (this.remainingFireTicks <= 0) {
|
||||
this.setRemainingFireTicks(-this.getFireImmuneTicks());
|
||||
}
|
||||
@@ -1432,32 +1467,82 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
@@ -1443,32 +1478,82 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
}
|
||||
|
||||
private Vec3 collide(Vec3 movement) {
|
||||
@ -2364,8 +2364,8 @@ index 9a01eff5a93c68edd45f98e9a6f8d24656650fb6..7992375dc55492aeb6defb204b28dd26
|
||||
}
|
||||
|
||||
public static Vec3 collideBoundingBox(@Nullable Entity entity, Vec3 movement, AABB entityBoundingBox, Level world, List<VoxelShape> collisions) {
|
||||
@@ -2707,11 +2792,70 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
|
||||
float f = this.dimensions.width * 0.8F;
|
||||
@@ -2735,11 +2820,70 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
float f = this.dimensions.width() * 0.8F;
|
||||
AABB axisalignedbb = AABB.ofSize(this.getEyePosition(), (double) f, 1.0E-6D, (double) f);
|
||||
|
||||
- return BlockPos.betweenClosedStream(axisalignedbb).anyMatch((blockposition) -> {
|
||||
@ -2440,10 +2440,10 @@ index 9a01eff5a93c68edd45f98e9a6f8d24656650fb6..7992375dc55492aeb6defb204b28dd26
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
index bbe299afd361a107e3936c8ea1a62067fcac9b7e..eadcebd7845ee716e33c0ac0544502da1a6c5941 100644
|
||||
index 2ed6845f16fab175e2e9e96e76391e63ab4a43e2..c2bd2e303f956d390319f6bbbe9a6492ebec5154 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/decoration/ArmorStand.java
|
||||
@@ -354,7 +354,7 @@ public class ArmorStand extends LivingEntity {
|
||||
@@ -360,7 +360,7 @@ public class ArmorStand extends LivingEntity {
|
||||
@Override
|
||||
protected void pushEntities() {
|
||||
if (!this.level().paperConfig().entities.armorStands.doCollisionEntityLookups) return; // Paper - Option to prevent armor stands from doing entity lookups
|
||||
@ -2453,10 +2453,10 @@ index bbe299afd361a107e3936c8ea1a62067fcac9b7e..eadcebd7845ee716e33c0ac0544502da
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/monster/Spider.java b/src/main/java/net/minecraft/world/entity/monster/Spider.java
|
||||
index ffa4f34d964fbcc53e2dfe11677832db21a6eb93..7618364e5373fe17cfe45a5a4ee9ab25e591581c 100644
|
||||
index f0127f1b55999aa4a841341ad02cbcde45702b50..ef8911f7bcf6a97496675abb4689bb09cf322e85 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/monster/Spider.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/monster/Spider.java
|
||||
@@ -86,7 +86,7 @@ public class Spider extends Monster {
|
||||
@@ -82,7 +82,7 @@ public class Spider extends Monster {
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (!this.level().isClientSide) {
|
||||
@ -2479,7 +2479,7 @@ index cd89623a44f02d7db77f0d0f87545cf80841f403..48710a60561824a3670ebef3601f284d
|
||||
}
|
||||
} else {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/ClipContext.java b/src/main/java/net/minecraft/world/level/ClipContext.java
|
||||
index 86a4f30c8784c602436ecf1c78efb0bdca4b7089..b0bea28e9261767c60d30fb0e76f4f3af8a5634e 100644
|
||||
index 3fa2964b979053ecbefc946c7fe76828de86d8f1..2634ba06147c936b0fae08a190c7820c832e6b23 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/ClipContext.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/ClipContext.java
|
||||
@@ -17,8 +17,8 @@ public class ClipContext {
|
||||
@ -2616,10 +2616,10 @@ index 9a28912f52824acdc80a62243b136e6f365bf567..21843501355a0c0c8d594e3e5312e978
|
||||
|
||||
// Paper start - Affects Spawning API
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index 47e83adf64df673bc40077335baf786f865411e8..bb57f97dbc2fcc7c28ebfb54ff00796fc7f51efe 100644
|
||||
index 5b3143723e1637c2ab44363b208cd26b659d70cc..ae569a4837dc82bbc390d281d774179706772959 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -294,6 +294,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -288,6 +288,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
this.entityLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.entityMaxTickTime);
|
||||
this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime);
|
||||
this.chunkPacketBlockController = this.paperConfig().anticheat.antiXray.enabled ? new com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) : com.destroystokyo.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray
|
||||
@ -2630,7 +2630,7 @@ index 47e83adf64df673bc40077335baf786f865411e8..bb57f97dbc2fcc7c28ebfb54ff00796f
|
||||
}
|
||||
|
||||
// Paper start - Cancel hit for vanished players
|
||||
@@ -335,6 +339,366 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -329,6 +333,366 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
return true;
|
||||
}
|
||||
// Paper end - Cancel hit for vanished players
|
||||
@ -2997,7 +2997,7 @@ index 47e83adf64df673bc40077335baf786f865411e8..bb57f97dbc2fcc7c28ebfb54ff00796f
|
||||
@Override
|
||||
public boolean isClientSide() {
|
||||
return this.isClientSide;
|
||||
@@ -958,7 +1322,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -950,7 +1314,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@Override
|
||||
public boolean noCollision(@Nullable Entity entity, AABB box) {
|
||||
if (entity instanceof net.minecraft.world.entity.decoration.ArmorStand && !entity.level().paperConfig().entities.armorStands.doCollisionEntityLookups) return false;
|
||||
@ -3017,10 +3017,10 @@ index 47e83adf64df673bc40077335baf786f865411e8..bb57f97dbc2fcc7c28ebfb54ff00796f
|
||||
// Paper end - Option to prevent armor stands from doing entity lookups
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
index b60a52788e73de3dcb086c1a4628466b25c9d3ef..22036ed3ea0629bc12981a8d91a03e55cc2117d6 100644
|
||||
index 054593fc0b8d13f6bf449cc20a1f7ddfd5f1d1f0..cf8b8c8efd1c9c81eb5f02d75bd75875eb66771f 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
|
||||
@@ -284,7 +284,7 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
@@ -280,7 +280,7 @@ public class Block extends BlockBehaviour implements ItemLike {
|
||||
}
|
||||
|
||||
public static boolean isShapeFullBlock(VoxelShape shape) {
|
||||
@ -3028,12 +3028,12 @@ index b60a52788e73de3dcb086c1a4628466b25c9d3ef..22036ed3ea0629bc12981a8d91a03e55
|
||||
+ return shape.isFullBlock(); // Paper - optimise collisions
|
||||
}
|
||||
|
||||
public boolean propagatesSkylightDown(BlockState state, BlockGetter world, BlockPos pos) {
|
||||
public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
index e493b34aa8726ed48f8e5db2ae8ea561cc5b1f75..2892e586146cbc560f0bcf4b9af6d0575cb0a82e 100644
|
||||
index f863f3a553e26af1fb656622da052505e6ef1c01..d3c0e767758aa791d51e708d4ec6efad726741e8 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
||||
@@ -882,6 +882,10 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
@@ -813,6 +813,10 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
this.instrument = blockbase_info.instrument;
|
||||
this.replaceable = blockbase_info.replaceable;
|
||||
this.conditionallyFullOpaque = this.canOcclude & this.useShapeForLightOcclusion; // Paper
|
||||
@ -3044,7 +3044,7 @@ index e493b34aa8726ed48f8e5db2ae8ea561cc5b1f75..2892e586146cbc560f0bcf4b9af6d057
|
||||
}
|
||||
// Paper start - Perf: impl cached craft block data, lazy load to fix issue with loading at the wrong time
|
||||
private org.bukkit.craftbukkit.block.data.CraftBlockData cachedCraftBlockData;
|
||||
@@ -930,6 +934,52 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
@@ -861,6 +865,52 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
return this.conditionallyFullOpaque;
|
||||
}
|
||||
// Paper end - starlight
|
||||
@ -3097,7 +3097,7 @@ index e493b34aa8726ed48f8e5db2ae8ea561cc5b1f75..2892e586146cbc560f0bcf4b9af6d057
|
||||
|
||||
public void initCache() {
|
||||
this.fluidState = ((Block) this.owner).getFluidState(this.asState());
|
||||
@@ -941,6 +991,39 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
@@ -872,6 +922,39 @@ public abstract class BlockBehaviour implements FeatureElement {
|
||||
this.opacityIfCached = this.cache == null || this.isConditionallyFullOpaque() ? -1 : this.cache.lightBlock; // Paper - starlight - cache opacity for light
|
||||
|
||||
this.legacySolid = this.calculateSolid();
|
||||
@ -3138,7 +3138,7 @@ index e493b34aa8726ed48f8e5db2ae8ea561cc5b1f75..2892e586146cbc560f0bcf4b9af6d057
|
||||
|
||||
public Block getBlock() {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
index eb05c01e85825cbd5b7cf43bc6d261db0b871b92..796bbef3544e06b8e7aac7e8ac5f740a2613f4bd 100644
|
||||
index 8cd6c1d838e0332125fde3fc36475034aa4effa0..a2a5aef769ee8bb638a5a9f3da9812fa4a85dda5 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunkSection.java
|
||||
@@ -26,6 +26,22 @@ public class LevelChunkSection {
|
||||
@ -3194,9 +3194,9 @@ index eb05c01e85825cbd5b7cf43bc6d261db0b871b92..796bbef3544e06b8e7aac7e8ac5f740a
|
||||
+ // Paper end - optimise collisions
|
||||
});
|
||||
}
|
||||
// Paper end
|
||||
// Paper end - unfuck this
|
||||
diff --git a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
index a98ab20814cc29a25e9d29adfbb7e70d46768df2..6d8ff6c06af5545634f255ed17dc1e489ece2548 100644
|
||||
index 1c0712295695727ee9c4d430d4157b8e17cbd71f..c2943d892b067b3f1fb3b93301a092e912d71f08 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/material/FlowingFluid.java
|
||||
@@ -240,6 +240,17 @@ public abstract class FlowingFluid extends Fluid {
|
||||
@ -3276,7 +3276,7 @@ index fc7f986812bdf74e0aea3bd09a1d53ba6def697f..0583d40a235aaecd9d6081486bbfb735
|
||||
+
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/phys/shapes/BitSetDiscreteVoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/BitSetDiscreteVoxelShape.java
|
||||
index 31b570517c1047e8e1cd5280baf80977af2b6121..d8b80632f6186641ee2ddaef9eba7ba998b09136 100644
|
||||
index e8f3307727e7e3da9a7629cafc6e1ee53790b75d..a71421947b161697d43bd8602e2af95aa272ed3f 100644
|
||||
--- a/src/main/java/net/minecraft/world/phys/shapes/BitSetDiscreteVoxelShape.java
|
||||
+++ b/src/main/java/net/minecraft/world/phys/shapes/BitSetDiscreteVoxelShape.java
|
||||
@@ -4,13 +4,13 @@ import java.util.BitSet;
|
||||
@ -3308,22 +3308,11 @@ index 31b570517c1047e8e1cd5280baf80977af2b6121..d8b80632f6186641ee2ddaef9eba7ba9
|
||||
+ // Paper start - optimise collisions
|
||||
+ // called with the shape of a VoxelShape, so we can expect the cache to exist
|
||||
+ final io.papermc.paper.util.collisions.CachedShapeData cache = voxelSet.getOrCreateCachedShapeData();
|
||||
|
||||
- for (int i = 0; i < bitSetDiscreteVoxelShape.ySize; i++) {
|
||||
- for (int j = 0; j < bitSetDiscreteVoxelShape.xSize; j++) {
|
||||
- int k = -1;
|
||||
+
|
||||
+ final int sizeX = cache.sizeX();
|
||||
+ final int sizeY = cache.sizeY();
|
||||
+ final int sizeZ = cache.sizeZ();
|
||||
|
||||
- for (int l = 0; l <= bitSetDiscreteVoxelShape.zSize; l++) {
|
||||
- if (bitSetDiscreteVoxelShape.isFullWide(j, i, l)) {
|
||||
- if (coalesce) {
|
||||
- if (k == -1) {
|
||||
- k = l;
|
||||
- }
|
||||
- } else {
|
||||
- callback.consume(j, i, l, j + 1, i + 1, l + 1);
|
||||
+
|
||||
+ int indexX;
|
||||
+ int indexY = 0;
|
||||
+ int indexZ;
|
||||
@ -3353,10 +3342,21 @@ index 31b570517c1047e8e1cd5280baf80977af2b6121..d8b80632f6186641ee2ddaef9eba7ba9
|
||||
+ } else {
|
||||
+ // same notes about loop order as the above
|
||||
+ // this branch is actually important to optimise, as it affects uncached toAabbs() (which affects optimize())
|
||||
+
|
||||
|
||||
- for (int i = 0; i < bitSetDiscreteVoxelShape.ySize; i++) {
|
||||
- for (int j = 0; j < bitSetDiscreteVoxelShape.xSize; j++) {
|
||||
- int k = -1;
|
||||
+ // only clone when we may write to it
|
||||
+ bitset = bitset.clone();
|
||||
+
|
||||
|
||||
- for (int l = 0; l <= bitSetDiscreteVoxelShape.zSize; l++) {
|
||||
- if (bitSetDiscreteVoxelShape.isFullWide(j, i, l)) {
|
||||
- if (coalesce) {
|
||||
- if (k == -1) {
|
||||
- k = l;
|
||||
- }
|
||||
- } else {
|
||||
- callback.consume(j, i, l, j + 1, i + 1, l + 1);
|
||||
+ for (int y = 0; y < sizeY; ++y, indexY += incY) {
|
||||
+ indexX = indexY;
|
||||
+ for (int x = 0; x < sizeX; ++x, indexX += incX) {
|
||||
@ -3365,6 +3365,11 @@ index 31b570517c1047e8e1cd5280baf80977af2b6121..d8b80632f6186641ee2ddaef9eba7ba9
|
||||
+
|
||||
+ if (firstSetZ == -1) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ int lastSetZ = io.papermc.paper.util.collisions.FlatBitsetUtil.firstClear(bitset, firstSetZ, endIndex);
|
||||
+ if (lastSetZ == -1) {
|
||||
+ lastSetZ = endIndex;
|
||||
}
|
||||
- } else if (k != -1) {
|
||||
- int m = j;
|
||||
@ -3375,14 +3380,6 @@ index 31b570517c1047e8e1cd5280baf80977af2b6121..d8b80632f6186641ee2ddaef9eba7ba9
|
||||
- bitSetDiscreteVoxelShape.clearZStrip(k, l, m + 1, i);
|
||||
- m++;
|
||||
+
|
||||
+ int lastSetZ = io.papermc.paper.util.collisions.FlatBitsetUtil.firstClear(bitset, firstSetZ, endIndex);
|
||||
+ if (lastSetZ == -1) {
|
||||
+ lastSetZ = endIndex;
|
||||
}
|
||||
|
||||
- while (bitSetDiscreteVoxelShape.isXZRectangleFull(j, m + 1, k, l, n + 1)) {
|
||||
- for (int o = j; o <= m; o++) {
|
||||
- bitSetDiscreteVoxelShape.clearZStrip(k, l, o, n + 1);
|
||||
+ io.papermc.paper.util.collisions.FlatBitsetUtil.clearRange(bitset, firstSetZ, lastSetZ);
|
||||
+
|
||||
+ // try to merge neighbouring on the X axis
|
||||
@ -3393,8 +3390,11 @@ index 31b570517c1047e8e1cd5280baf80977af2b6121..d8b80632f6186641ee2ddaef9eba7ba9
|
||||
+
|
||||
+ ++endX;
|
||||
+ io.papermc.paper.util.collisions.FlatBitsetUtil.clearRange(bitset, neighbourIdxStart, neighbourIdxEnd);
|
||||
+ }
|
||||
+
|
||||
}
|
||||
|
||||
- while (bitSetDiscreteVoxelShape.isXZRectangleFull(j, m + 1, k, l, n + 1)) {
|
||||
- for (int o = j; o <= m; o++) {
|
||||
- bitSetDiscreteVoxelShape.clearZStrip(k, l, o, n + 1);
|
||||
+ // try to merge neighbouring on the Y axis
|
||||
+
|
||||
+ int endY; // exclusive
|
||||
@ -3446,7 +3446,7 @@ index 32632368f06b79f53342fde060bbcd1b7c64767a..b9af1d14c7815c99273bce8165cf384d
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/phys/shapes/DiscreteVoxelShape.java b/src/main/java/net/minecraft/world/phys/shapes/DiscreteVoxelShape.java
|
||||
index 87a8f12dc3d47fb093115030e0222f065f1dcb1c..44b62f1f6685084c0cff02bd31eb5a7c2ef9eead 100644
|
||||
index 01693ba050b12b9debcdaefceeff9cbcd503b369..a7af766f1c28f2c9ca2a430808ac4c07fe24df68 100644
|
||||
--- a/src/main/java/net/minecraft/world/phys/shapes/DiscreteVoxelShape.java
|
||||
+++ b/src/main/java/net/minecraft/world/phys/shapes/DiscreteVoxelShape.java
|
||||
@@ -9,6 +9,71 @@ public abstract class DiscreteVoxelShape {
|
@ -8,10 +8,10 @@ Move collision logic to just the hasNewCollision call instead of getCubes + hasN
|
||||
CHECK ME
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 33560f75dd76f946203faa34ca5d10f213cd62c9..d0ae2c485b0e37406633c79043bd833a8a6b3e2d 100644
|
||||
index 6061f7104dd2094e316739a1b0e541475aed40b0..88fc56fa521c36accd807ca1704136f29733e52f 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -552,7 +552,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
@@ -578,7 +578,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
return;
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ index 33560f75dd76f946203faa34ca5d10f213cd62c9..d0ae2c485b0e37406633c79043bd833a
|
||||
|
||||
d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
|
||||
d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above
|
||||
@@ -568,6 +568,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
@@ -594,6 +594,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
|
||||
entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
|
||||
@ -28,7 +28,7 @@ index 33560f75dd76f946203faa34ca5d10f213cd62c9..d0ae2c485b0e37406633c79043bd833a
|
||||
double d11 = d7;
|
||||
|
||||
d6 = d3 - entity.getX();
|
||||
@@ -581,15 +582,23 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
@@ -607,15 +608,23 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
boolean flag2 = false;
|
||||
|
||||
if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
|
||||
@ -55,7 +55,7 @@ index 33560f75dd76f946203faa34ca5d10f213cd62c9..d0ae2c485b0e37406633c79043bd833a
|
||||
entity.absMoveTo(d0, d1, d2, f, f1);
|
||||
this.player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
|
||||
this.send(new ClientboundMoveVehiclePacket(entity));
|
||||
@@ -668,7 +677,32 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
@@ -694,7 +703,32 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
|
||||
private boolean noBlocksAround(Entity entity) {
|
||||
@ -89,7 +89,7 @@ index 33560f75dd76f946203faa34ca5d10f213cd62c9..d0ae2c485b0e37406633c79043bd833a
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1282,7 +1316,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
@@ -1289,7 +1323,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
|
||||
if (this.awaitingPositionFromClient != null) {
|
||||
@ -98,7 +98,7 @@ index 33560f75dd76f946203faa34ca5d10f213cd62c9..d0ae2c485b0e37406633c79043bd833a
|
||||
this.awaitingTeleportTime = this.tickCount;
|
||||
this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot());
|
||||
}
|
||||
@@ -1389,7 +1423,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
@@ -1398,7 +1432,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ index 33560f75dd76f946203faa34ca5d10f213cd62c9..d0ae2c485b0e37406633c79043bd833a
|
||||
|
||||
d6 = d0 - this.lastGoodX; // 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
|
||||
@@ -1431,6 +1465,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
@@ -1440,6 +1474,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
|
||||
this.player.move(MoverType.PLAYER, new Vec3(d6, d7, d8));
|
||||
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
|
||||
@ -115,10 +115,10 @@ index 33560f75dd76f946203faa34ca5d10f213cd62c9..d0ae2c485b0e37406633c79043bd833a
|
||||
// Paper start - prevent position desync
|
||||
if (this.awaitingPositionFromClient != null) {
|
||||
return; // ... thanks Mojang for letting move calls teleport across dimensions.
|
||||
@@ -1459,7 +1494,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
@@ -1470,7 +1505,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
|
||||
// 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));
|
||||
+ // Paper start - optimise out extra getCubes
|
||||
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly;
|
||||
@ -134,7 +134,7 @@ index 33560f75dd76f946203faa34ca5d10f213cd62c9..d0ae2c485b0e37406633c79043bd833a
|
||||
if (teleportBack) {
|
||||
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
|
||||
toX, toY, toZ, toYaw, toPitch, false);
|
||||
@@ -1559,6 +1604,33 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
@@ -1576,6 +1621,33 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ Subject: [PATCH] Fix tripwire disarming not working as intended
|
||||
Fixes MC-129055
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
index d9b3877257b31ca1b5acc4a47fbf5b993de69ae0..efd8d77a441fd334ea4c09c5e31c6d946c1ae0b7 100644
|
||||
index 8614fad5b3df7a6030384b108b1689bf6b9f1209..76aca266d3f3222502ff4c196228f08fcd88c5f8 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java
|
||||
@@ -201,9 +201,8 @@ public class TripWireHookBlock extends Block {
|
||||
@@ -202,9 +202,8 @@ public class TripWireHookBlock extends Block {
|
||||
BlockState iblockdata4 = aiblockdata[l];
|
||||
|
||||
if (iblockdata4 != null) {
|
@ -10,10 +10,10 @@ when if this was fixed on the client, that wouldn't be needed.
|
||||
Mojira Issue: https://bugs.mojang.com/browse/MC-235045
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/commands/CommandSourceStack.java b/src/main/java/net/minecraft/commands/CommandSourceStack.java
|
||||
index faa375f2722793a86265248a4be4fa14736d9818..f341813e9713e39bfe142ca34b751de3d8efd25b 100644
|
||||
index 3c0d2332207ba638faaaa4280bce18c334a01271..e6c7f62ed379a78645933670299e4fcda8540ed1 100644
|
||||
--- a/src/main/java/net/minecraft/commands/CommandSourceStack.java
|
||||
+++ b/src/main/java/net/minecraft/commands/CommandSourceStack.java
|
||||
@@ -466,4 +466,20 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
|
||||
@@ -462,4 +462,20 @@ public class CommandSourceStack implements ExecutionCommandSource<CommandSourceS
|
||||
return this.source.getBukkitSender(this);
|
||||
}
|
||||
// CraftBukkit end
|
||||
@ -35,10 +35,10 @@ index faa375f2722793a86265248a4be4fa14736d9818..f341813e9713e39bfe142ca34b751de3
|
||||
+ // Paper end - tell clients to ask server for suggestions for EntityArguments
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/commands/Commands.java b/src/main/java/net/minecraft/commands/Commands.java
|
||||
index df06c28c778255cb2d8d5e14960bd38a2af9ad22..b7f338e982d0dcab99137ab6dc200b82ac6b7cba 100644
|
||||
index 60406cb01c5a409ba6fe98677a5cc332effaebea..a0702dccbb07c79febe2e65a2ff82c4436c09f12 100644
|
||||
--- a/src/main/java/net/minecraft/commands/Commands.java
|
||||
+++ b/src/main/java/net/minecraft/commands/Commands.java
|
||||
@@ -522,6 +522,7 @@ public class Commands {
|
||||
@@ -525,6 +525,7 @@ public class Commands {
|
||||
private void fillUsableCommands(CommandNode<CommandSourceStack> tree, CommandNode<SharedSuggestionProvider> result, CommandSourceStack source, Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> resultNodes) {
|
||||
Iterator iterator = tree.getChildren().iterator();
|
||||
|
||||
@ -46,7 +46,7 @@ index df06c28c778255cb2d8d5e14960bd38a2af9ad22..b7f338e982d0dcab99137ab6dc200b82
|
||||
while (iterator.hasNext()) {
|
||||
CommandNode<CommandSourceStack> commandnode2 = (CommandNode) iterator.next();
|
||||
// Paper start - Brigadier API
|
||||
@@ -548,6 +549,12 @@ public class Commands {
|
||||
@@ -551,6 +552,12 @@ public class Commands {
|
||||
|
||||
if (requiredargumentbuilder.getSuggestionsProvider() != null) {
|
||||
requiredargumentbuilder.suggests(SuggestionProviders.safelySwap(requiredargumentbuilder.getSuggestionsProvider()));
|
||||
@ -60,10 +60,10 @@ index df06c28c778255cb2d8d5e14960bd38a2af9ad22..b7f338e982d0dcab99137ab6dc200b82
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/commands/arguments/EntityArgument.java b/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
|
||||
index 8e008e752c5b11781088e2b4b5ba180bacb59326..8d79cfa371546996ef65f94232c1d344e7c590ec 100644
|
||||
index 2043001c16b3530c2d3f52efda10bcad424881c0..7976885b902a6ce7d80f31e49448c99452eb9765 100644
|
||||
--- a/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
|
||||
+++ b/src/main/java/net/minecraft/commands/arguments/EntityArgument.java
|
||||
@@ -132,7 +132,7 @@ public class EntityArgument implements ArgumentType<EntitySelector> {
|
||||
@@ -131,7 +131,7 @@ public class EntityArgument implements ArgumentType<EntitySelector> {
|
||||
final boolean permission = object instanceof CommandSourceStack stack
|
||||
? stack.bypassSelectorPermissions || stack.hasPermission(2, "minecraft.command.selector")
|
||||
: icompletionprovider.hasPermission(2);
|
||||
@ -72,7 +72,7 @@ index 8e008e752c5b11781088e2b4b5ba180bacb59326..8d79cfa371546996ef65f94232c1d344
|
||||
// Paper end - Fix EntityArgument suggestion permissions
|
||||
|
||||
try {
|
||||
@@ -142,7 +142,19 @@ public class EntityArgument implements ArgumentType<EntitySelector> {
|
||||
@@ -141,7 +141,19 @@ public class EntityArgument implements ArgumentType<EntitySelector> {
|
||||
}
|
||||
|
||||
return argumentparserselector.fillSuggestions(suggestionsbuilder, (suggestionsbuilder1) -> {
|
||||
@ -118,10 +118,10 @@ index 3d897ec6920eff6176ddac9f0442a997b9ef14fd..abaf1ea340c69c8bee80e64567b44b5c
|
||||
this.level = MinMaxBounds.Ints.ANY;
|
||||
this.rotX = WrappedMinMaxBounds.ANY;
|
||||
diff --git a/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java b/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
|
||||
index 0ed0679af07445f0ba241c791f15dcc2b6731b12..01ec7813cd7abe94cb87927c4c2324c8be6c3a56 100644
|
||||
index 44982ff2cdd6e03f0b9ce8c3cc87561ef183ef06..626fe7a45c2edba68eb201974e9f8f5eebf75cc0 100644
|
||||
--- a/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
|
||||
+++ b/src/main/java/net/minecraft/commands/arguments/selector/options/EntitySelectorOptions.java
|
||||
@@ -75,6 +75,19 @@ public class EntitySelectorOptions {
|
||||
@@ -76,6 +76,19 @@ public class EntitySelectorOptions {
|
||||
public static final DynamicCommandExceptionType ERROR_ENTITY_TYPE_INVALID = new DynamicCommandExceptionType(
|
||||
entity -> Component.translatableEscape("argument.entity.options.type.invalid", entity)
|
||||
);
|
||||
@ -141,7 +141,7 @@ index 0ed0679af07445f0ba241c791f15dcc2b6731b12..01ec7813cd7abe94cb87927c4c2324c8
|
||||
|
||||
private static void register(String id, EntitySelectorOptions.Modifier handler, Predicate<EntitySelectorParser> condition, Component description) {
|
||||
OPTIONS.put(id, new EntitySelectorOptions.Option(handler, condition, description));
|
||||
@@ -296,6 +309,12 @@ public class EntitySelectorOptions {
|
||||
@@ -297,6 +310,12 @@ public class EntitySelectorOptions {
|
||||
|
||||
if (reader.isTag()) {
|
||||
TagKey<EntityType<?>> tagKey = TagKey.create(Registries.ENTITY_TYPE, ResourceLocation.read(reader.getReader()));
|
@ -2009,10 +2009,10 @@ index 0000000000000000000000000000000000000000..33cd90c30c22200a4e1ae64f40a0bf78
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index af9f58328c09dddb2875f79128f906b8b276ab88..c9405cbea1202e5603dde42637cf2a78592b92e1 100644
|
||||
index 98fded81545a96deb6a05df713a5b69e27189cf4..a2a5a43c5e73ba2cccbec4e1ac563f692ae901b5 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -223,6 +223,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
@@ -228,6 +228,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
public final UUID uuid;
|
||||
public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
|
||||
public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
|
||||
@ -2020,7 +2020,7 @@ index af9f58328c09dddb2875f79128f906b8b276ab88..c9405cbea1202e5603dde42637cf2a78
|
||||
|
||||
public LevelChunk getChunkIfLoaded(int x, int z) {
|
||||
return this.chunkSource.getChunkAtIfLoadedImmediately(x, z); // Paper - Use getChunkIfLoadedImmediately
|
||||
@@ -2593,6 +2594,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
@@ -2560,6 +2561,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
|
||||
return crashreportsystemdetails;
|
||||
}
|
||||
|
||||
@ -2035,10 +2035,10 @@ index af9f58328c09dddb2875f79128f906b8b276ab88..c9405cbea1202e5603dde42637cf2a78
|
||||
|
||||
EntityCallbacks() {}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
||||
index bb57f97dbc2fcc7c28ebfb54ff00796fc7f51efe..a09017e74d972a12d0b88b4ade9a3532ce0ecd08 100644
|
||||
index ae569a4837dc82bbc390d281d774179706772959..68746df814aa1a8714e199ff887cad9f8bfa283c 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/Level.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
||||
@@ -1887,4 +1887,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
@@ -1882,4 +1882,14 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
||||
return ret;
|
||||
}
|
||||
// Paper end
|
||||
@ -2054,10 +2054,10 @@ index bb57f97dbc2fcc7c28ebfb54ff00796fc7f51efe..a09017e74d972a12d0b88b4ade9a3532
|
||||
+ // Paper end - optimize redstone (Alternate Current)
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
index c80af964a2b4026f738aecd2058a7e99d225cce0..b5a71fd4e2f55bf036c2c697da5d50cc90fc657c 100644
|
||||
index 7ec3b0f9488b732c51cd1b02fb0dfe3c45aec2a4..f6c1e40001af507b4eed8f46a9ed4e4704b48d72 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/RedStoneWireBlock.java
|
||||
@@ -259,7 +259,7 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -258,7 +258,7 @@ public class RedStoneWireBlock extends Block {
|
||||
return floor.isFaceSturdy(world, pos, Direction.UP) || floor.is(Blocks.HOPPER);
|
||||
}
|
||||
|
||||
@ -2066,9 +2066,9 @@ index c80af964a2b4026f738aecd2058a7e99d225cce0..b5a71fd4e2f55bf036c2c697da5d50cc
|
||||
// The bulk of the new functionality is found in RedstoneWireTurbo.java
|
||||
com.destroystokyo.paper.util.RedstoneWireTurbo turbo = new com.destroystokyo.paper.util.RedstoneWireTurbo(this);
|
||||
|
||||
@@ -461,7 +461,13 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -460,7 +460,13 @@ public class RedStoneWireBlock extends Block {
|
||||
@Override
|
||||
public void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
|
||||
protected void onPlace(BlockState state, Level world, BlockPos pos, BlockState oldState, boolean notify) {
|
||||
if (!oldState.is(state.getBlock()) && !world.isClientSide) {
|
||||
- this.updateSurroundingRedstone(world, pos, state, null); // Paper - Optimize redstone
|
||||
+ // Paper start - optimize redstone - replace call to updatePowerStrength
|
||||
@ -2081,7 +2081,7 @@ index c80af964a2b4026f738aecd2058a7e99d225cce0..b5a71fd4e2f55bf036c2c697da5d50cc
|
||||
Iterator iterator = Direction.Plane.VERTICAL.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
@@ -488,7 +494,13 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -487,7 +493,13 @@ public class RedStoneWireBlock extends Block {
|
||||
world.updateNeighborsAt(pos.relative(enumdirection), this);
|
||||
}
|
||||
|
||||
@ -2096,9 +2096,9 @@ index c80af964a2b4026f738aecd2058a7e99d225cce0..b5a71fd4e2f55bf036c2c697da5d50cc
|
||||
this.updateNeighborsOfNeighboringWires(world, pos);
|
||||
}
|
||||
}
|
||||
@@ -522,8 +534,14 @@ public class RedStoneWireBlock extends Block {
|
||||
@@ -521,8 +533,14 @@ public class RedStoneWireBlock extends Block {
|
||||
@Override
|
||||
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
|
||||
protected void neighborChanged(BlockState state, Level world, BlockPos pos, Block sourceBlock, BlockPos sourcePos, boolean notify) {
|
||||
if (!world.isClientSide) {
|
||||
+ // Paper start - optimize redstone (Alternate Current)
|
||||
+ // Alternate Current handles breaking of redstone wires in the WireHandler.
|
@ -5,10 +5,10 @@ Subject: [PATCH] optimize dirt and snow spreading
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
|
||||
index 4e2e80006bd4edae227af7be5ca8e3284b7494f6..f3003a3832deff7724d28b4b3a091f4802a4cb29 100644
|
||||
index 5a39e8d359dc13383711e49ffb2d1294dad26192..b7165ec19bef1a07f6618fc0429d86cda1b08da4 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/SpreadingSnowyDirtBlock.java
|
||||
@@ -19,8 +19,13 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
|
||||
@@ -18,8 +18,13 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
|
||||
}
|
||||
|
||||
private static boolean canBeGrass(BlockState state, LevelReader world, BlockPos pos) {
|
||||
@ -23,7 +23,7 @@ index 4e2e80006bd4edae227af7be5ca8e3284b7494f6..f3003a3832deff7724d28b4b3a091f48
|
||||
|
||||
if (iblockdata1.is(Blocks.SNOW) && (Integer) iblockdata1.getValue(SnowLayerBlock.LAYERS) == 1) {
|
||||
return true;
|
||||
@@ -37,15 +42,27 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
|
||||
@@ -36,15 +41,27 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
|
||||
protected abstract MapCodec<? extends SpreadingSnowyDirtBlock> codec();
|
||||
|
||||
private static boolean canPropagate(BlockState state, LevelReader world, BlockPos pos) {
|
||||
@ -40,11 +40,11 @@ index 4e2e80006bd4edae227af7be5ca8e3284b7494f6..f3003a3832deff7724d28b4b3a091f48
|
||||
}
|
||||
|
||||
@Override
|
||||
public void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
|
||||
if (this instanceof GrassBlock && world.paperConfig().tickRates.grassSpread != 1 && (world.paperConfig().tickRates.grassSpread < 1 || (MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper - Configurable random tick rates for blocks
|
||||
protected void randomTick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
|
||||
if (this instanceof GrassBlock && world.paperConfig().tickRates.grassSpread != 1 && (world.paperConfig().tickRates.grassSpread < 1 || (net.minecraft.server.MinecraftServer.currentTick + pos.hashCode()) % world.paperConfig().tickRates.grassSpread != 0)) { return; } // Paper - Configurable random tick rates for blocks
|
||||
- if (!SpreadingSnowyDirtBlock.canBeGrass(state, world, pos)) {
|
||||
+ // Paper start - Perf: optimize dirt and snow spreading
|
||||
+ net.minecraft.world.level.chunk.ChunkAccess cachedBlockChunk = world.getChunkIfLoaded(pos);
|
||||
+ final net.minecraft.world.level.chunk.ChunkAccess cachedBlockChunk = world.getChunkIfLoaded(pos);
|
||||
+ if (cachedBlockChunk == null) { // Is this needed?
|
||||
+ return;
|
||||
+ }
|
||||
@ -53,7 +53,7 @@ index 4e2e80006bd4edae227af7be5ca8e3284b7494f6..f3003a3832deff7724d28b4b3a091f48
|
||||
// CraftBukkit start
|
||||
if (org.bukkit.craftbukkit.event.CraftEventFactory.callBlockFadeEvent(world, pos, Blocks.DIRT.defaultBlockState()).isCancelled()) {
|
||||
return;
|
||||
@@ -58,9 +75,19 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
|
||||
@@ -57,9 +74,19 @@ public abstract class SpreadingSnowyDirtBlock extends SnowyDirtBlock {
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
BlockPos blockposition1 = pos.offset(random.nextInt(3) - 1, random.nextInt(5) - 3, random.nextInt(3) - 1);
|
337
patches/server/1025-Properly-resend-entities.patch
Normale Datei
337
patches/server/1025-Properly-resend-entities.patch
Normale Datei
@ -0,0 +1,337 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Wed, 7 Dec 2022 17:25:19 -0500
|
||||
Subject: [PATCH] Properly resend entities
|
||||
|
||||
This resolves some issues which caused entities to not be resent correctly.
|
||||
Entities that are interacted with need to be resent to the client, so we resend all the entity
|
||||
data to the player whilst making sure not to clear dirty entries from the tracker. This makes
|
||||
sure that values will be correctly updated to other players.
|
||||
|
||||
This also adds utilities to aid in further preventing entity desyncs.
|
||||
|
||||
This also also fixes the bug causing cancelling PlayerInteractEvent to cause items to continue
|
||||
to be used despite being cancelled on the server.
|
||||
|
||||
For example, items being consumed but never finishing, shields being put up, etc.
|
||||
The underlying issue of this is that the client modifies their synced data values,
|
||||
and so we have to (forcibly) resend them in order for the client to reset their using item state.
|
||||
|
||||
See: https://github.com/PaperMC/Paper/pull/1896
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.server.level.ChunkMap$TrackedEntity serverEntity
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
index 02bf2705ca1c99023a83a22d92e1962181102297..0f99733660f91280e4c6262cf75b3c9cae86f65a 100644
|
||||
--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
+++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
@@ -50,7 +50,7 @@ public class SynchedEntityData {
|
||||
}
|
||||
}
|
||||
|
||||
- private <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> key) {
|
||||
+ public <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> key) { // Paper - public
|
||||
return (SynchedEntityData.DataItem<T>) this.itemsById[key.id()]; // CraftBukkit - decompile error
|
||||
}
|
||||
|
||||
@@ -151,6 +151,20 @@ public class SynchedEntityData {
|
||||
}
|
||||
}
|
||||
|
||||
+ // Paper start
|
||||
+ // We need to pack all as we cannot rely on "non default values" or "dirty" ones.
|
||||
+ // Because these values can possibly be desynced on the client.
|
||||
+ @Nullable
|
||||
+ public List<SynchedEntityData.DataValue<?>> packAll() {
|
||||
+ final List<SynchedEntityData.DataValue<?>> list = new ArrayList<>();
|
||||
+ for (final DataItem<?> dataItem : this.itemsById) {
|
||||
+ list.add(dataItem.value());
|
||||
+ }
|
||||
+
|
||||
+ return list;
|
||||
+ }
|
||||
+ // Paper end
|
||||
+
|
||||
public static class DataItem<T> {
|
||||
|
||||
final EntityDataAccessor<T> accessor;
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
index abb9a86cd42a34cf722a312068134e820ac21956..3b6ebe8f9575783a1607eb6667554ca66de94271 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -556,6 +556,7 @@ public class ServerPlayerGameMode {
|
||||
}
|
||||
// Paper end - extend Player Interact cancellation
|
||||
player.getBukkitEntity().updateInventory(); // SPIGOT-2867
|
||||
+ this.player.resyncUsingItem(this.player); // Paper - Properly cancel usable items
|
||||
return (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS;
|
||||
} else if (this.gameModeForPlayer == GameType.SPECTATOR) {
|
||||
MenuProvider itileinventory = iblockdata.getMenuProvider(world, blockposition);
|
||||
@@ -609,6 +610,11 @@ public class ServerPlayerGameMode {
|
||||
} else {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
+ // Paper start - Properly cancel usable items; Cancel only if cancelled + if the interact result is different from default response
|
||||
+ else if (this.interactResult && this.interactResult != cancelledItem) {
|
||||
+ this.player.resyncUsingItem(this.player);
|
||||
+ }
|
||||
+ // Paper end - Properly cancel usable items
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index 88fc56fa521c36accd807ca1704136f29733e52f..32076a765d48d59b339d600f69afa85edbcf833c 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -45,7 +45,6 @@ import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.ConnectionProtocol;
|
||||
import net.minecraft.network.TickablePacketListener;
|
||||
-import net.minecraft.network.chat.ChatDecorator;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.LastSeenMessages;
|
||||
@@ -63,7 +62,6 @@ import net.minecraft.network.protocol.PacketUtils;
|
||||
import net.minecraft.network.protocol.common.ServerboundClientInformationPacket;
|
||||
import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket;
|
||||
import net.minecraft.network.protocol.configuration.ConfigurationProtocols;
|
||||
-import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockChangedAckPacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ClientboundCommandSuggestionsPacket;
|
||||
@@ -185,7 +183,6 @@ import net.minecraft.world.level.block.entity.CrafterBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.JigsawBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.SignBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.StructureBlockEntity;
|
||||
-import net.minecraft.world.level.block.state.BlockBehaviour;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
@@ -216,7 +213,6 @@ import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||
import org.bukkit.craftbukkit.inventory.CraftItemType;
|
||||
-import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
|
||||
import org.bukkit.craftbukkit.util.LazyPlayerSet;
|
||||
import org.bukkit.craftbukkit.util.Waitable;
|
||||
@@ -231,8 +227,6 @@ import org.bukkit.event.inventory.InventoryCreativeEvent;
|
||||
import org.bukkit.event.inventory.InventoryType.SlotType;
|
||||
import org.bukkit.event.inventory.SmithItemEvent;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
-import org.bukkit.event.player.PlayerAnimationEvent;
|
||||
-import org.bukkit.event.player.PlayerAnimationType;
|
||||
import org.bukkit.event.player.PlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
@@ -2010,6 +2004,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
|
||||
if (cancelled) {
|
||||
+ this.player.resyncUsingItem(this.player); // Paper - Properly cancel usable items
|
||||
this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524
|
||||
return;
|
||||
}
|
||||
@@ -2794,7 +2789,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
|
||||
// Entity in bucket - SPIGOT-4048 and SPIGOT-6859a
|
||||
if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem)) {
|
||||
- ServerGamePacketListenerImpl.this.send(new ClientboundAddEntityPacket(entity));
|
||||
+ entity.getEntityData().resendPossiblyDesyncedEntityData(player); // Paper - The entire mob gets deleted, so resend it.
|
||||
ServerGamePacketListenerImpl.this.player.containerMenu.sendAllDataToRemote();
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index c83ec24c0bf54f8699caa2d37bfe82d273f7b16c..dd628c8190704505fde543a8853d5b4dbc8252d5 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -393,7 +393,7 @@ public abstract class PlayerList {
|
||||
((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - Fire PlayerJoinEvent when Player is actually ready; track entity now
|
||||
// CraftBukkit end
|
||||
|
||||
- player.refreshEntityData(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
|
||||
+ //player.refreshEntityData(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn // Paper - THIS IS NOT NEEDED ANYMORE
|
||||
|
||||
this.sendLevelInfo(player, worldserver1);
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 8ad2d17615ff489b2fbbb13480dd0b217a42d805..130ad5dc8ef5cfe1cfc0a166eba2cf67d424ff69 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -6,6 +6,7 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
import com.mojang.logging.LogUtils;
|
||||
+import io.papermc.paper.util.MCUtil;
|
||||
import it.unimi.dsi.fastutil.objects.Object2DoubleArrayMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2DoubleMap;
|
||||
import java.util.Arrays;
|
||||
@@ -59,7 +60,6 @@ import net.minecraft.network.syncher.SyncedDataHolder;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
-import io.papermc.paper.util.MCUtil;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@@ -129,28 +129,22 @@ import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
import net.minecraft.world.scores.ScoreHolder;
|
||||
import net.minecraft.world.scores.Team;
|
||||
-import org.slf4j.Logger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
-import org.bukkit.Server;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.command.CommandSender;
|
||||
-import org.bukkit.craftbukkit.event.CraftPortalEvent;
|
||||
-import org.bukkit.entity.Hanging;
|
||||
-import org.bukkit.entity.LivingEntity;
|
||||
-import org.bukkit.entity.Vehicle;
|
||||
-import org.bukkit.event.entity.EntityCombustByEntityEvent;
|
||||
-import org.bukkit.event.hanging.HangingBreakByEntityEvent;
|
||||
-import org.bukkit.event.vehicle.VehicleBlockCollisionEvent;
|
||||
-import org.bukkit.event.vehicle.VehicleEnterEvent;
|
||||
-import org.bukkit.event.vehicle.VehicleExitEvent;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.event.CraftEventFactory;
|
||||
+import org.bukkit.craftbukkit.event.CraftPortalEvent;
|
||||
import org.bukkit.craftbukkit.util.CraftLocation;
|
||||
+import org.bukkit.entity.Hanging;
|
||||
+import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Pose;
|
||||
+import org.bukkit.entity.Vehicle;
|
||||
import org.bukkit.event.entity.EntityAirChangeEvent;
|
||||
+import org.bukkit.event.entity.EntityCombustByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityCombustEvent;
|
||||
import org.bukkit.event.entity.EntityDismountEvent;
|
||||
import org.bukkit.event.entity.EntityDropItemEvent;
|
||||
@@ -158,8 +152,13 @@ import org.bukkit.event.entity.EntityMountEvent;
|
||||
import org.bukkit.event.entity.EntityPortalEvent;
|
||||
import org.bukkit.event.entity.EntityPoseChangeEvent;
|
||||
import org.bukkit.event.entity.EntityRemoveEvent;
|
||||
+import org.bukkit.event.hanging.HangingBreakByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
+import org.bukkit.event.vehicle.VehicleBlockCollisionEvent;
|
||||
+import org.bukkit.event.vehicle.VehicleEnterEvent;
|
||||
+import org.bukkit.event.vehicle.VehicleExitEvent;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
+import org.slf4j.Logger;
|
||||
// CraftBukkit end
|
||||
|
||||
public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess, CommandSource, ScoreHolder {
|
||||
@@ -704,13 +703,44 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
|
||||
|
||||
// CraftBukkit start
|
||||
public void refreshEntityData(ServerPlayer to) {
|
||||
- List<SynchedEntityData.DataValue<?>> list = this.getEntityData().getNonDefaultValues();
|
||||
+ List<SynchedEntityData.DataValue<?>> list = this.entityData.packAll(); // Paper - Update EVERYTHING not just not default
|
||||
|
||||
- if (list != null) {
|
||||
+ if (list != null && to.getBukkitEntity().canSee(this.getBukkitEntity())) { // Paper
|
||||
to.connection.send(new ClientboundSetEntityDataPacket(this.getId(), list));
|
||||
}
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start
|
||||
+ // This method should only be used if the data of an entity could have become desynced
|
||||
+ // due to interactions on the client.
|
||||
+ public void resendPossiblyDesyncedEntityData(net.minecraft.server.level.ServerPlayer player) {
|
||||
+ if (this.tracker == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (player.getBukkitEntity().canSee(this.getBukkitEntity())) {
|
||||
+ final net.minecraft.server.level.ServerEntity serverEntity = this.tracker.serverEntity;
|
||||
+ final List<net.minecraft.network.protocol.Packet<? super net.minecraft.network.protocol.game.ClientGamePacketListener>> list = new java.util.ArrayList<>();
|
||||
+ serverEntity.sendPairingData(player, list::add);
|
||||
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundBundlePacket(list));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // This method allows you to specifically resend certain data accessor keys to the client
|
||||
+ public void resendPossiblyDesyncedDataValues(List<EntityDataAccessor<?>> keys, ServerPlayer to) {
|
||||
+ if (!to.getBukkitEntity().canSee(this.getBukkitEntity())) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ final List<SynchedEntityData.DataValue<?>> values = new java.util.ArrayList<>(keys.size());
|
||||
+ for (final EntityDataAccessor<?> key : keys) {
|
||||
+ final SynchedEntityData.DataItem<?> synchedValue = this.entityData.getItem(key);
|
||||
+ values.add(synchedValue.value());
|
||||
+ }
|
||||
+
|
||||
+ to.connection.send(new ClientboundSetEntityDataPacket(this.id, values));
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public boolean equals(Object object) {
|
||||
return object instanceof Entity ? ((Entity) object).id == this.id : false;
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 75e01c1e01e0782fc8af48777bbe4716d37aeafa..9ff43ff4076c658b8561c5a7abd067423830f964 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3828,6 +3828,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND;
|
||||
}
|
||||
|
||||
+ // Paper start - Properly cancel usable items
|
||||
+ public void resyncUsingItem(ServerPlayer serverPlayer) {
|
||||
+ this.getEntityData().resendPossiblyDesyncedDataValues(java.util.List.of(DATA_LIVING_ENTITY_FLAGS), serverPlayer);
|
||||
+ }
|
||||
+ // Paper end - Properly cancel usable items
|
||||
private void updatingUsingItem() {
|
||||
if (this.isUsingItem()) {
|
||||
if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bucketable.java b/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
|
||||
index cb4a6439e9774bbec07e69b13df8dddd395b9ece..cfe37b4f5e33795ee717d824d86e3a0919129cf5 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
|
||||
@@ -109,8 +109,7 @@ public interface Bucketable {
|
||||
itemstack1 = CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket());
|
||||
if (playerBucketFishEvent.isCancelled()) {
|
||||
((ServerPlayer) player).containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket
|
||||
- ((ServerPlayer) player).connection.send(new ClientboundAddEntityPacket(entity)); // We need to play out these packets as the client assumes the fish is gone
|
||||
- entity.refreshEntityData((ServerPlayer) player); // Need to send data such as the display name to client
|
||||
+ entity.resendPossiblyDesyncedEntityData((ServerPlayer) player); // Paper
|
||||
return Optional.of(InteractionResult.FAIL);
|
||||
}
|
||||
entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 3ab04c4bdbe26ff7f6f54eb9cdd58376c592fa05..f949514cf68d0ae2db754576e46f5bfc14ffdff4 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -1010,7 +1010,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
return;
|
||||
}
|
||||
|
||||
- entityTracker.broadcast(this.getHandle().getAddEntityPacket());
|
||||
+ // Paper start, resend possibly desynced entity instead of add entity packet
|
||||
+ for (ServerPlayerConnection playerConnection : entityTracker.seenBy) {
|
||||
+ this.getHandle().getEntityData().resendPossiblyDesyncedEntityData(playerConnection.getPlayer());
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
private static PermissibleBase getPermissibleBase() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java
|
||||
index 0801bcdee8fcff0d388d302387e4f1d587e0a283..2fcd9b836d42e3549a3b6b921c57a4c103146dff 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java
|
||||
@@ -39,9 +39,11 @@ public class CraftItemFrame extends CraftHanging implements ItemFrame {
|
||||
protected void update() {
|
||||
super.update();
|
||||
|
||||
+ // Paper start, don't mark as dirty as this is handled in super.update()
|
||||
// mark dirty, so that the client gets updated with item and rotation
|
||||
- this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ITEM);
|
||||
- this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ROTATION);
|
||||
+ //this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ITEM);
|
||||
+ //this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ROTATION);
|
||||
+ // Paper end
|
||||
|
||||
// update redstone
|
||||
if (!this.getHandle().generation) {
|
@ -50,22 +50,22 @@ index 0000000000000000000000000000000000000000..5c42823726e70ce6c9d0121d07431548
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
index 636ad032f9b6b20557327e7d0b0aefff7780d1f3..2f263ef5120982b3167ab008a0e22b8cbc9b9fdd 100644
|
||||
index 88549de2768149885c4eabbaaa71a38341453aed..1adcbfb16ea1fe3378cde7c53e8868840eade963 100644
|
||||
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
||||
@@ -1692,6 +1692,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
@@ -1756,6 +1756,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
||||
ServerLevel worldserver = (ServerLevel) iterator.next();
|
||||
worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
|
||||
worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
|
||||
+ net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers
|
||||
|
||||
this.profiler.push(() -> {
|
||||
return worldserver + " " + worldserver.dimension().location();
|
||||
String s = String.valueOf(worldserver);
|
||||
diff --git a/src/main/java/net/minecraft/world/item/ItemStack.java b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
index 06dc04a1fbb91a5a20d662aeee168b6a319551d0..1ad126d992d95062a3db08374db7a927f23a0cac 100644
|
||||
index 9510558d03faf5b704a763456c5f2d4f28bca6e8..8e5d8e146ae045797e07260e4108ba5f1e4d976d 100644
|
||||
--- a/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
+++ b/src/main/java/net/minecraft/world/item/ItemStack.java
|
||||
@@ -752,10 +752,16 @@ public final class ItemStack {
|
||||
@@ -795,7 +795,13 @@ public final class ItemStack implements DataComponentHolder {
|
||||
}
|
||||
|
||||
public ItemStack copy() {
|
||||
@ -79,16 +79,12 @@ index 06dc04a1fbb91a5a20d662aeee168b6a319551d0..1ad126d992d95062a3db08374db7a927
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
return ItemStack.EMPTY;
|
||||
} else {
|
||||
- ItemStack itemstack = new ItemStack(this.getItem(), this.count);
|
||||
+ ItemStack itemstack = new ItemStack(originalItem ? this.item : this.getItem(), this.count); // Paper - Perf: Optimize Hoppers
|
||||
|
||||
itemstack.setPopTime(this.getPopTime());
|
||||
if (this.tag != null) {
|
||||
ItemStack itemstack = new ItemStack(this.getItem(), this.count, this.components.copy());
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
index 20201430ee8f28245aa845acb172d0f5d80458ff..9ea74d37cd951e0dc76d20ed8234b5871035566c 100644
|
||||
index a7dfad2696e7145af1355a5db132af14d09a6f30..b0421823684ff6b9474b81675742d2ee3b17edf7 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java
|
||||
@@ -26,6 +26,7 @@ import co.aikar.timings.MinecraftTimings; // Paper
|
||||
@@ -37,6 +37,7 @@ import co.aikar.timings.MinecraftTimings; // Paper
|
||||
import co.aikar.timings.Timing; // Paper
|
||||
|
||||
public abstract class BlockEntity {
|
||||
@ -96,7 +92,7 @@ index 20201430ee8f28245aa845acb172d0f5d80458ff..9ea74d37cd951e0dc76d20ed8234b587
|
||||
|
||||
public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper
|
||||
// CraftBukkit start - data containers
|
||||
@@ -161,6 +162,7 @@ public abstract class BlockEntity {
|
||||
@@ -210,6 +211,7 @@ public abstract class BlockEntity {
|
||||
|
||||
public void setChanged() {
|
||||
if (this.level != null) {
|
||||
@ -105,10 +101,10 @@ index 20201430ee8f28245aa845acb172d0f5d80458ff..9ea74d37cd951e0dc76d20ed8234b587
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
index e3b6f2bf93710ea695b0c25c0b6968a8f24f0829..cdb739df2a285032d25d84f4464f202a7a3fa578 100644
|
||||
index 43ee9017fbbe0a5485a281712f76c23b059a849b..57dc38e39a11fa51f0d27830b709fe5b7ae9dc8b 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/HopperBlockEntity.java
|
||||
@@ -152,6 +152,43 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -156,6 +156,43 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
}
|
||||
|
||||
@ -152,15 +148,14 @@ index e3b6f2bf93710ea695b0c25c0b6968a8f24f0829..cdb739df2a285032d25d84f4464f202a
|
||||
private static boolean tryMoveItems(Level world, BlockPos pos, BlockState state, HopperBlockEntity blockEntity, BooleanSupplier booleansupplier) {
|
||||
if (world.isClientSide) {
|
||||
return false;
|
||||
@@ -159,11 +196,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -163,11 +200,12 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
if (!blockEntity.isOnCooldown() && (Boolean) state.getValue(HopperBlock.ENABLED)) {
|
||||
boolean flag = false;
|
||||
|
||||
- if (!blockEntity.isEmpty()) {
|
||||
+ int fullState = getFullState(blockEntity); // Paper - Perf: Optimize Hoppers
|
||||
+
|
||||
+ if (fullState != HOPPER_EMPTY) { // Paper - Perf: Optimize Hopperss
|
||||
flag = HopperBlockEntity.ejectItems(world, pos, state, (Container) blockEntity, blockEntity); // CraftBukkit
|
||||
+ final int fullState = getFullState(blockEntity); // Paper - Perf: Optimize Hoppers
|
||||
+ if (fullState != HOPPER_EMPTY) { // Paper - Perf: Optimize Hoppers
|
||||
flag = HopperBlockEntity.ejectItems(world, pos, blockEntity);
|
||||
}
|
||||
|
||||
- if (!blockEntity.inventoryFull()) {
|
||||
@ -168,7 +163,7 @@ index e3b6f2bf93710ea695b0c25c0b6968a8f24f0829..cdb739df2a285032d25d84f4464f202a
|
||||
flag |= booleansupplier.getAsBoolean();
|
||||
}
|
||||
|
||||
@@ -194,6 +233,202 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -198,6 +236,202 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -368,181 +363,119 @@ index e3b6f2bf93710ea695b0c25c0b6968a8f24f0829..cdb739df2a285032d25d84f4464f202a
|
||||
+ private static final java.util.function.BiPredicate<ItemStack, Integer> IS_EMPTY_TEST = (itemstack, i) -> itemstack.isEmpty();
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
+
|
||||
private static boolean ejectItems(Level world, BlockPos blockposition, BlockState iblockdata, Container iinventory, HopperBlockEntity hopper) { // CraftBukkit
|
||||
Container iinventory1 = HopperBlockEntity.getAttachedContainer(world, blockposition, iblockdata);
|
||||
private static boolean ejectItems(Level world, BlockPos pos, HopperBlockEntity blockEntity) {
|
||||
Container iinventory = HopperBlockEntity.getAttachedContainer(world, pos, blockEntity);
|
||||
|
||||
@@ -205,46 +440,49 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
if (HopperBlockEntity.isFullContainer(iinventory1, enumdirection)) {
|
||||
@@ -209,47 +443,50 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
if (HopperBlockEntity.isFullContainer(iinventory, enumdirection)) {
|
||||
return false;
|
||||
} else {
|
||||
- for (int i = 0; i < iinventory.getContainerSize(); ++i) {
|
||||
- if (!iinventory.getItem(i).isEmpty()) {
|
||||
- ItemStack itemstack = iinventory.getItem(i).copy();
|
||||
- // ItemStack itemstack1 = addItem(iinventory, iinventory1, iinventory.removeItem(i, 1), enumdirection);
|
||||
- for (int i = 0; i < blockEntity.getContainerSize(); ++i) {
|
||||
- ItemStack itemstack = blockEntity.getItem(i);
|
||||
-
|
||||
- if (!itemstack.isEmpty()) {
|
||||
- int j = itemstack.getCount();
|
||||
- // CraftBukkit start - Call event when pushing items into other inventories
|
||||
- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot
|
||||
- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(blockEntity.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot
|
||||
-
|
||||
- Inventory destinationInventory;
|
||||
- // Have to special case large chests as they work oddly
|
||||
- if (iinventory1 instanceof CompoundContainer) {
|
||||
- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory1);
|
||||
- } else if (iinventory1.getOwner() != null) {
|
||||
- destinationInventory = iinventory1.getOwner().getInventory();
|
||||
- if (iinventory instanceof CompoundContainer) {
|
||||
- destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory);
|
||||
- } else if (iinventory.getOwner() != null) {
|
||||
- destinationInventory = iinventory.getOwner().getInventory();
|
||||
- } else {
|
||||
- destinationInventory = new CraftInventory(iinventory);
|
||||
- }
|
||||
-
|
||||
- InventoryMoveItemEvent event = new InventoryMoveItemEvent(iinventory.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true);
|
||||
- InventoryMoveItemEvent event = new InventoryMoveItemEvent(iinventory.getOwner().getInventory(), oitemstack, destinationInventory, true);
|
||||
- world.getCraftServer().getPluginManager().callEvent(event);
|
||||
- if (event.isCancelled()) {
|
||||
- hopper.setItem(i, itemstack);
|
||||
- hopper.setCooldown(world.spigotConfig.hopperTransfer); // Spigot
|
||||
- blockEntity.setItem(i, itemstack);
|
||||
- blockEntity.setCooldown(world.spigotConfig.hopperTransfer); // Delay hopper checks // Spigot
|
||||
- return false;
|
||||
- }
|
||||
- int origCount = event.getItem().getAmount(); // Spigot
|
||||
- ItemStack itemstack1 = HopperBlockEntity.addItem(iinventory, iinventory1, CraftItemStack.asNMSCopy(event.getItem()), enumdirection);
|
||||
+ // Paper start - replace logic; MAKE SURE TO CHECK FOR DIFFS ON UPDATES
|
||||
+ return hopperPush(world, iinventory1, enumdirection, hopper);
|
||||
+ // for (int i = 0; i < iinventory.getContainerSize(); ++i) {
|
||||
+ // if (!iinventory.getItem(i).isEmpty()) {
|
||||
+ // ItemStack itemstack = iinventory.getItem(i).copy();
|
||||
+ // // ItemStack itemstack1 = addItem(iinventory, iinventory1, iinventory.removeItem(i, 1), enumdirection);
|
||||
- ItemStack itemstack1 = HopperBlockEntity.addItem(blockEntity, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection);
|
||||
- // CraftBukkit end
|
||||
-
|
||||
- if (itemstack1.isEmpty()) {
|
||||
- iinventory.setChanged();
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- itemstack.setCount(j);
|
||||
- if (j == 1) {
|
||||
- blockEntity.setItem(i, itemstack);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return false;
|
||||
+ // Paper start - Perf: Optimize Hoppers
|
||||
+ return hopperPush(world, iinventory, enumdirection, blockEntity);
|
||||
+ //for (int i = 0; i < blockEntity.getContainerSize(); ++i) {
|
||||
+ // ItemStack itemstack = blockEntity.getItem(i);
|
||||
+
|
||||
+ // if (!itemstack.isEmpty()) {
|
||||
+ // int j = itemstack.getCount();
|
||||
+ // // CraftBukkit start - Call event when pushing items into other inventories
|
||||
+ // CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot
|
||||
+ // CraftItemStack oitemstack = CraftItemStack.asCraftMirror(blockEntity.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot
|
||||
+
|
||||
+ // Inventory destinationInventory;
|
||||
+ // // Have to special case large chests as they work oddly
|
||||
+ // if (iinventory1 instanceof CompoundContainer) {
|
||||
+ // destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory1);
|
||||
+ // } else if (iinventory1.getOwner() != null) {
|
||||
+ // destinationInventory = iinventory1.getOwner().getInventory();
|
||||
+ // if (iinventory instanceof CompoundContainer) {
|
||||
+ // destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((CompoundContainer) iinventory);
|
||||
+ // } else if (iinventory.getOwner() != null) {
|
||||
+ // destinationInventory = iinventory.getOwner().getInventory();
|
||||
+ // } else {
|
||||
+ // destinationInventory = new CraftInventory(iinventory);
|
||||
+ // }
|
||||
+
|
||||
+ // InventoryMoveItemEvent event = new InventoryMoveItemEvent(iinventory.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true);
|
||||
+ // InventoryMoveItemEvent event = new InventoryMoveItemEvent(iinventory.getOwner().getInventory(), oitemstack, destinationInventory, true);
|
||||
+ // world.getCraftServer().getPluginManager().callEvent(event);
|
||||
+ // if (event.isCancelled()) {
|
||||
+ // hopper.setItem(i, itemstack);
|
||||
+ // hopper.setCooldown(world.spigotConfig.hopperTransfer); // Spigot
|
||||
+ // blockEntity.setItem(i, itemstack);
|
||||
+ // blockEntity.setCooldown(world.spigotConfig.hopperTransfer); // Delay hopper checks // Spigot
|
||||
+ // return false;
|
||||
+ // }
|
||||
+ // int origCount = event.getItem().getAmount(); // Spigot
|
||||
+ // ItemStack itemstack1 = HopperBlockEntity.addItem(iinventory, iinventory1, CraftItemStack.asNMSCopy(event.getItem()), enumdirection);
|
||||
// CraftBukkit end
|
||||
|
||||
- if (itemstack1.isEmpty()) {
|
||||
- iinventory1.setChanged();
|
||||
- return true;
|
||||
- }
|
||||
+ // ItemStack itemstack1 = HopperBlockEntity.addItem(blockEntity, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection);
|
||||
+ // // CraftBukkit end
|
||||
+
|
||||
+ // if (itemstack1.isEmpty()) {
|
||||
+ // iinventory1.setChanged();
|
||||
+ // iinventory.setChanged();
|
||||
+ // return true;
|
||||
+ // }
|
||||
|
||||
- itemstack.shrink(origCount - itemstack1.getCount()); // Spigot
|
||||
- iinventory.setItem(i, itemstack);
|
||||
- }
|
||||
- }
|
||||
+ // itemstack.shrink(origCount - itemstack1.getCount()); // Spigot
|
||||
+ // iinventory.setItem(i, itemstack);
|
||||
+
|
||||
+ // itemstack.setCount(j);
|
||||
+ // if (j == 1) {
|
||||
+ // blockEntity.setItem(i, itemstack);
|
||||
+ // }
|
||||
+ // }
|
||||
|
||||
- return false;
|
||||
+ //}
|
||||
+
|
||||
+ // return false;
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,17 +492,29 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -300,7 +537,6 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isFullContainer(Container inventory, Direction direction) {
|
||||
- return HopperBlockEntity.getSlots(inventory, direction).allMatch((i) -> {
|
||||
- ItemStack itemstack = inventory.getItem(i);
|
||||
-
|
||||
- return itemstack.getCount() >= itemstack.getMaxStackSize();
|
||||
- });
|
||||
+ // Paper start - Perf: Optimize Hoppers
|
||||
+ if (inventory instanceof WorldlyContainer worldlyContainer) {
|
||||
+ for (final int slot : worldlyContainer.getSlotsForFace(direction)) {
|
||||
+ final ItemStack stack = inventory.getItem(slot);
|
||||
+ if (stack.getCount() < stack.getMaxStackSize()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ for (int slot = 0, max = inventory.getContainerSize(); slot < max; ++slot) {
|
||||
+ final ItemStack stack = inventory.getItem(slot);
|
||||
+ if (stack.getCount() < stack.getMaxStackSize()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isEmptyContainer(Container inv, Direction facing) {
|
||||
- return HopperBlockEntity.getSlots(inv, facing).allMatch((i) -> {
|
||||
- return inv.getItem(i).isEmpty();
|
||||
- });
|
||||
+ return allMatch(inv, facing, IS_EMPTY_TEST); // Paper - Perf: Optimize Hoppers
|
||||
}
|
||||
|
||||
public static boolean suckInItems(Level world, Hopper hopper) {
|
||||
@@ -273,9 +523,33 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
if (iinventory != null) {
|
||||
Direction enumdirection = Direction.DOWN;
|
||||
|
||||
- return HopperBlockEntity.isEmptyContainer(iinventory, enumdirection) ? false : HopperBlockEntity.getSlots(iinventory, enumdirection).anyMatch((i) -> {
|
||||
- return HopperBlockEntity.a(hopper, iinventory, i, enumdirection, world); // Spigot
|
||||
- });
|
||||
+ // Paper start - Perf: Optimize Hoppers
|
||||
+ skipPullModeEventFire = skipHopperEvents;
|
||||
+ // merge container isEmpty check and move logic into one loop
|
||||
+ if (iinventory instanceof WorldlyContainer worldlyContainer) {
|
||||
+ for (final int slot : worldlyContainer.getSlotsForFace(enumdirection)) {
|
||||
+ ItemStack item = worldlyContainer.getItem(slot);
|
||||
+ if (item.isEmpty() || !canTakeItemFromContainer(hopper, iinventory, item, slot, enumdirection)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (hopperPull(world, hopper, iinventory, item, slot)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ } else {
|
||||
+ for (int slot = 0, max = iinventory.getContainerSize(); slot < max; ++slot) {
|
||||
+ ItemStack item = iinventory.getItem(slot);
|
||||
+ if (item.isEmpty() || !canTakeItemFromContainer(hopper, iinventory, item, slot, enumdirection)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (hopperPull(world, hopper, iinventory, item, slot)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
} else {
|
||||
Iterator iterator = HopperBlockEntity.getItemsAtAndAbove(world, hopper).iterator();
|
||||
|
||||
@@ -293,48 +567,52 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -342,48 +578,52 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
}
|
||||
}
|
||||
|
||||
+ @io.papermc.paper.annotation.DoNotUse // Paper - method unused as logic is inlined above
|
||||
private static boolean a(Hopper ihopper, Container iinventory, int i, Direction enumdirection, Level world) { // Spigot
|
||||
+ @io.papermc.paper.annotation.DoNotUse // Paper - Optimize hoppers
|
||||
private static boolean tryTakeInItemFromSlot(Hopper ihopper, Container iinventory, int i, Direction enumdirection, Level world) { // Spigot
|
||||
ItemStack itemstack = iinventory.getItem(i);
|
||||
|
||||
- if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(ihopper, iinventory, itemstack, i, enumdirection)) {
|
||||
- ItemStack itemstack1 = itemstack.copy();
|
||||
- // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.removeItem(i, 1), (EnumDirection) null);
|
||||
if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(ihopper, iinventory, itemstack, i, enumdirection)) {
|
||||
- int j = itemstack.getCount();
|
||||
- // CraftBukkit start - Call event on collection of items from inventories into the hopper
|
||||
- CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot
|
||||
-
|
||||
@ -556,11 +489,11 @@ index e3b6f2bf93710ea695b0c25c0b6968a8f24f0829..cdb739df2a285032d25d84f4464f202a
|
||||
- sourceInventory = new CraftInventory(iinventory);
|
||||
- }
|
||||
-
|
||||
- InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), ihopper.getOwner().getInventory(), false);
|
||||
- InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack, ihopper.getOwner().getInventory(), false);
|
||||
-
|
||||
- Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
- if (event.isCancelled()) {
|
||||
- iinventory.setItem(i, itemstack1);
|
||||
- iinventory.setItem(i, itemstack);
|
||||
-
|
||||
- if (ihopper instanceof HopperBlockEntity) {
|
||||
- ((HopperBlockEntity) ihopper).setCooldown(world.spigotConfig.hopperTransfer); // Spigot
|
||||
@ -568,22 +501,21 @@ index e3b6f2bf93710ea695b0c25c0b6968a8f24f0829..cdb739df2a285032d25d84f4464f202a
|
||||
-
|
||||
- return false;
|
||||
- }
|
||||
- int origCount = event.getItem().getAmount(); // Spigot
|
||||
- ItemStack itemstack2 = HopperBlockEntity.addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null);
|
||||
- ItemStack itemstack1 = HopperBlockEntity.addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null);
|
||||
- // CraftBukkit end
|
||||
-
|
||||
- if (itemstack2.isEmpty()) {
|
||||
- if (itemstack1.isEmpty()) {
|
||||
- iinventory.setChanged();
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot
|
||||
- iinventory.setItem(i, itemstack1);
|
||||
+ // Paper start - Perf: Optimize Hoppers; replace pull logic; MAKE SURE TO CHECK FOR DIFFS WHEN UPDATING
|
||||
+ if (!itemstack.isEmpty() && HopperBlockEntity.canTakeItemFromContainer(ihopper, iinventory, itemstack, i, enumdirection)) { // If this logic changes, update above. this is left unused incase reflective plugins
|
||||
- itemstack.setCount(j);
|
||||
- if (j == 1) {
|
||||
- iinventory.setItem(i, itemstack);
|
||||
- }
|
||||
+ // Paper start - Perf: Optimize Hoppers
|
||||
+ return hopperPull(world, ihopper, iinventory, itemstack, i);
|
||||
+ // ItemStack itemstack1 = itemstack.copy();
|
||||
+ // // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.removeItem(i, 1), (EnumDirection) null);
|
||||
+ // int j = itemstack.getCount();
|
||||
+ // // CraftBukkit start - Call event on collection of items from inventories into the hopper
|
||||
+ // CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.removeItem(i, world.spigotConfig.hopperAmount)); // Spigot
|
||||
+
|
||||
@ -597,11 +529,11 @@ index e3b6f2bf93710ea695b0c25c0b6968a8f24f0829..cdb739df2a285032d25d84f4464f202a
|
||||
+ // sourceInventory = new CraftInventory(iinventory);
|
||||
+ // }
|
||||
+
|
||||
+ // InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), ihopper.getOwner().getInventory(), false);
|
||||
+ // InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack, ihopper.getOwner().getInventory(), false);
|
||||
+
|
||||
+ // Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
+ // if (event.isCancelled()) {
|
||||
+ // iinventory.setItem(i, itemstack1);
|
||||
+ // iinventory.setItem(i, itemstack);
|
||||
+
|
||||
+ // if (ihopper instanceof HopperBlockEntity) {
|
||||
+ // ((HopperBlockEntity) ihopper).setCooldown(world.spigotConfig.hopperTransfer); // Spigot
|
||||
@ -609,22 +541,23 @@ index e3b6f2bf93710ea695b0c25c0b6968a8f24f0829..cdb739df2a285032d25d84f4464f202a
|
||||
+
|
||||
+ // return false;
|
||||
+ // }
|
||||
+ // int origCount = event.getItem().getAmount(); // Spigot
|
||||
+ // ItemStack itemstack2 = HopperBlockEntity.addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null);
|
||||
+ // ItemStack itemstack1 = HopperBlockEntity.addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null);
|
||||
+ // // CraftBukkit end
|
||||
+
|
||||
+ // if (itemstack2.isEmpty()) {
|
||||
+ // if (itemstack1.isEmpty()) {
|
||||
+ // iinventory.setChanged();
|
||||
+ // return true;
|
||||
+ // }
|
||||
+
|
||||
+ // itemstack1.shrink(origCount - itemstack2.getCount()); // Spigot
|
||||
+ // iinventory.setItem(i, itemstack1);
|
||||
+ // itemstack.setCount(j);
|
||||
+ // if (j == 1) {
|
||||
+ // iinventory.setItem(i, itemstack);
|
||||
+ // }
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -343,12 +621,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -392,12 +632,14 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
public static boolean addItem(Container inventory, ItemEntity itemEntity) {
|
||||
boolean flag = false;
|
||||
// CraftBukkit start
|
||||
@ -640,7 +573,7 @@ index e3b6f2bf93710ea695b0c25c0b6968a8f24f0829..cdb739df2a285032d25d84f4464f202a
|
||||
ItemStack itemstack = itemEntity.getItem().copy();
|
||||
ItemStack itemstack1 = HopperBlockEntity.addItem((Container) null, inventory, itemstack, (Direction) null);
|
||||
|
||||
@@ -444,7 +724,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
@@ -491,7 +733,9 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
stack = stack.split(to.getMaxStackSize());
|
||||
}
|
||||
// Spigot end
|
||||
@ -650,101 +583,55 @@ index e3b6f2bf93710ea695b0c25c0b6968a8f24f0829..cdb739df2a285032d25d84f4464f202a
|
||||
stack = leftover; // Paper - Make hoppers respect inventory max stack size
|
||||
flag = true;
|
||||
} else if (HopperBlockEntity.canMergeItems(itemstack1, stack)) {
|
||||
@@ -518,19 +800,47 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
// CraftBukkit end
|
||||
}
|
||||
|
||||
+ // Paper start - Perf: Optimize Hoppers
|
||||
+ static final AABB HOPPER_ITEM_SUCK_OVERALL = Hopper.SUCK.bounds();
|
||||
+ static final AABB[] HOPPER_ITEM_SUCK_INDIVIDUAL = Hopper.SUCK.toAabbs().toArray(new AABB[0]);
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
+
|
||||
public static List<ItemEntity> getItemsAtAndAbove(Level world, Hopper hopper) {
|
||||
- return (List) hopper.getSuckShape().toAabbs().stream().flatMap((axisalignedbb) -> {
|
||||
- return world.getEntitiesOfClass(ItemEntity.class, axisalignedbb.move(hopper.getLevelX() - 0.5D, hopper.getLevelY() - 0.5D, hopper.getLevelZ() - 0.5D), EntitySelector.ENTITY_STILL_ALIVE).stream();
|
||||
- }).collect(Collectors.toList());
|
||||
+ // Paper start - Perf: Optimize Hoppers
|
||||
+ // eliminate multiple getEntitiesOfClass() but maintain the voxelshape collision by moving
|
||||
+ // the individual AABB checks into the predicate
|
||||
+ final double shiftX = hopper.getLevelX() - 0.5D;
|
||||
+ final double shiftY = hopper.getLevelY() - 0.5D;
|
||||
+ final double shiftZ = hopper.getLevelZ() - 0.5D;
|
||||
+ return world.getEntitiesOfClass(ItemEntity.class, HOPPER_ITEM_SUCK_OVERALL.move(shiftX, shiftY, shiftZ), (final Entity entity) -> {
|
||||
+ if (!entity.isAlive()) { // EntitySelector.ENTITY_STILL_ALIVE
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ for (final AABB aabb : HOPPER_ITEM_SUCK_INDIVIDUAL) {
|
||||
+ if (aabb.move(shiftX, shiftY, shiftZ).intersects(entity.getBoundingBox())) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ });
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
}
|
||||
@@ -571,14 +815,20 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
@Nullable
|
||||
public static Container getContainerAt(Level world, BlockPos pos) {
|
||||
- return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D);
|
||||
+ return HopperBlockEntity.getContainerAt(world, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, true); // Paper - Perf: Optimize Hoppers
|
||||
- return HopperBlockEntity.getContainerAt(world, pos, world.getBlockState(pos), (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D);
|
||||
+ return HopperBlockEntity.getContainerAt(world, pos, world.getBlockState(pos), (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Container getContainerAt(Level world, double x, double y, double z) {
|
||||
private static Container getContainerAt(Level world, BlockPos pos, BlockState state, double x, double y, double z) {
|
||||
+ // Paper start - Perf: Optimize Hoppers
|
||||
+ return HopperBlockEntity.getContainerAt(world, x, y, z, false);
|
||||
+ return HopperBlockEntity.getContainerAt(world, pos, state, x, y, z, false);
|
||||
+ }
|
||||
+ @Nullable
|
||||
+ private static Container getContainerAt(Level world, double x, double y, double z, final boolean optimizeEntities) {
|
||||
+ private static Container getContainerAt(Level world, BlockPos pos, BlockState state, double x, double y, double z, boolean optimizeEntities) {
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
Object object = null;
|
||||
BlockPos blockposition = BlockPos.containing(x, y, z);
|
||||
if ( !world.spigotConfig.hopperCanLoadChunks && !world.hasChunkAt( blockposition ) ) return null; // Spigot
|
||||
@@ -550,8 +860,8 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
}
|
||||
Container iinventory = HopperBlockEntity.getBlockContainer(world, pos, state);
|
||||
|
||||
- if (iinventory == null) {
|
||||
+ if (iinventory == null && (!optimizeEntities || !world.paperConfig().hopper.ignoreOccludingBlocks || !state.getBukkitMaterial().isOccluding())) { // Paper - Perf: Optimize Hoppers
|
||||
iinventory = HopperBlockEntity.getEntityContainer(world, x, y, z);
|
||||
}
|
||||
|
||||
- if (object == null) {
|
||||
@@ -613,13 +863,13 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
|
||||
@Nullable
|
||||
private static Container getEntityContainer(Level world, double x, double y, double z) {
|
||||
- List<Entity> list = world.getEntities((Entity) null, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR);
|
||||
+ if (object == null && (!optimizeEntities || !world.paperConfig().hopper.ignoreOccludingBlocks || !iblockdata.getBukkitMaterial().isOccluding())) { // Paper - Perf: Optimize Hoppers
|
||||
+ List<Entity> list = world.getEntitiesOfClass((Class)Container.class, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); // Paper - Perf: Optimize Hoppers
|
||||
+ List<Entity> list = world.getEntitiesOfClass((Class) Container.class, new AABB(x - 0.5D, y - 0.5D, z - 0.5D, x + 0.5D, y + 0.5D, z + 0.5D), EntitySelector.CONTAINER_ENTITY_SELECTOR); // Paper - Perf: Optimize hoppers
|
||||
|
||||
if (!list.isEmpty()) {
|
||||
object = (Container) list.get(world.random.nextInt(list.size()));
|
||||
@@ -562,7 +872,7 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
|
||||
return !list.isEmpty() ? (Container) list.get(world.random.nextInt(list.size())) : null;
|
||||
}
|
||||
|
||||
private static boolean canMergeItems(ItemStack first, ItemStack second) {
|
||||
- return first.getCount() <= first.getMaxStackSize() && ItemStack.isSameItemSameTags(first, second);
|
||||
+ return first.getCount() < first.getMaxStackSize() && first.is(second.getItem()) && first.getDamageValue() == second.getDamageValue() && ((first.isEmpty() && second.isEmpty()) || java.util.Objects.equals(first.getTag(), second.getTag())); // Paper - Perf: Optimize Hoppers; used to return true for full itemstacks?!
|
||||
- return first.getCount() <= first.getMaxStackSize() && ItemStack.isSameItemSameComponents(first, second);
|
||||
+ return first.getCount() < first.getMaxStackSize() && ItemStack.isSameItemSameComponents(first, second); // Paper - Perf: Optimize Hoppers; used to return true for full itemstacks?!
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
index f33c4633094002a3dd0c54353b62f7b358628be3..dfd1246b735fe64c5beae83567a013861eb00822 100644
|
||||
index 6a6473ebf03e5b1e502db7e66203783b9980d072..674c3c2b3cc2c00a8830900baf797bc20f154fe7 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
@@ -93,12 +93,19 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
this.unpackLootTable(null);
|
||||
- return this.getItems().stream().allMatch(ItemStack::isEmpty);
|
||||
+ // Paper start - Perf: Optimize Hoppers
|
||||
+ for (final ItemStack itemStack : this.getItems()) {
|
||||
+ if (!itemStack.isEmpty()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+ // Paper end - Perf: Optimize Hoppers
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(int slot) {
|
||||
- this.unpackLootTable(null);
|
||||
+ if (slot == 0) this.unpackLootTable(null); // Paper - Perf: Optimize Hoppers
|
||||
return this.getItems().get(slot);
|
||||
return super.getItem(slot);
|
||||
}
|
||||
|
@ -1,216 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
|
||||
Date: Wed, 7 Dec 2022 17:25:19 -0500
|
||||
Subject: [PATCH] Properly resend entities
|
||||
|
||||
This resolves some issues which caused entities to not be resent correctly.
|
||||
Entities that are interacted with need to be resent to the client, so we resend all the entity
|
||||
data to the player whilst making sure not to clear dirty entries from the tracker. This makes
|
||||
sure that values will be correctly updated to other players.
|
||||
|
||||
This also adds utilities to aid in further preventing entity desyncs.
|
||||
|
||||
This also also fixes the bug causing cancelling PlayerInteractEvent to cause items to continue
|
||||
to be used despite being cancelled on the server.
|
||||
|
||||
For example, items being consumed but never finishing, shields being put up, etc.
|
||||
The underlying issue of this is that the client modifies their synced data values,
|
||||
and so we have to (forcibly) resend them in order for the client to reset their using item state.
|
||||
|
||||
See: https://github.com/PaperMC/Paper/pull/1896
|
||||
|
||||
== AT ==
|
||||
public net.minecraft.server.level.ChunkMap$TrackedEntity serverEntity
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
index 07a362f9e485d0d507f16f1dda1ac84ade07ab27..58b602e550258c1062ee940bc46538dac95d8979 100644
|
||||
--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
+++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
|
||||
@@ -275,14 +275,63 @@ public class SynchedEntityData {
|
||||
// CraftBukkit start
|
||||
public void refresh(ServerPlayer to) {
|
||||
if (!this.isEmpty()) {
|
||||
- List<SynchedEntityData.DataValue<?>> list = this.getNonDefaultValues();
|
||||
+ List<SynchedEntityData.DataValue<?>> list = this.packAll(); // Paper - Update EVERYTHING not just not default
|
||||
|
||||
if (list != null) {
|
||||
+ if (to.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper
|
||||
to.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), list));
|
||||
+ } // Paper
|
||||
}
|
||||
}
|
||||
}
|
||||
// CraftBukkit end
|
||||
+ // Paper start
|
||||
+ // We need to pack all as we cannot rely on "non default values" or "dirty" ones.
|
||||
+ // Because these values can possibly be desynced on the client.
|
||||
+ @Nullable
|
||||
+ private List<SynchedEntityData.DataValue<?>> packAll() {
|
||||
+ if (this.isEmpty()) {
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ List<SynchedEntityData.DataValue<?>> list = new ArrayList<>();
|
||||
+ for (DataItem<?> dataItem : this.itemsById.values()) {
|
||||
+ list.add(dataItem.value());
|
||||
+ }
|
||||
+
|
||||
+ return list;
|
||||
+ }
|
||||
+
|
||||
+ // This method should only be used if the data of an entity could have became desynced
|
||||
+ // due to interactions on the client.
|
||||
+ public void resendPossiblyDesyncedEntity(ServerPlayer player) {
|
||||
+ if (this.entity.tracker == null) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (player.getBukkitEntity().canSee(entity.getBukkitEntity())) {
|
||||
+ net.minecraft.server.level.ServerEntity serverEntity = this.entity.tracker.serverEntity;
|
||||
+
|
||||
+ List<net.minecraft.network.protocol.Packet<net.minecraft.network.protocol.game.ClientGamePacketListener>> list = new ArrayList<>();
|
||||
+ serverEntity.sendPairingData(player, list::add);
|
||||
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundBundlePacket(list));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // This method allows you to specifically resend certain data accessor keys to the client
|
||||
+ public void resendPossiblyDesyncedDataValues(List<EntityDataAccessor<?>> keys, ServerPlayer to) {
|
||||
+ if (!to.getBukkitEntity().canSee(this.entity.getBukkitEntity())) {
|
||||
+ return;
|
||||
+ }
|
||||
+ List<SynchedEntityData.DataValue<?>> values = new ArrayList<>(keys.size());
|
||||
+ for (EntityDataAccessor<?> key : keys) {
|
||||
+ SynchedEntityData.DataItem<?> synchedValue = this.getItem(key);
|
||||
+ values.add(synchedValue.value());
|
||||
+ }
|
||||
+
|
||||
+ to.connection.send(new ClientboundSetEntityDataPacket(this.entity.getId(), values));
|
||||
+ }
|
||||
+ // Paper end
|
||||
|
||||
public static class DataItem<T> {
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
index 692a01b52a71e26887ee42cbd5fd64b0a81bfc99..ef3048a4748113538a0ee0af5b526b2cd51d5c29 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
|
||||
@@ -561,6 +561,7 @@ public class ServerPlayerGameMode {
|
||||
}
|
||||
// Paper end - extend Player Interact cancellation
|
||||
player.getBukkitEntity().updateInventory(); // SPIGOT-2867
|
||||
+ this.player.resyncUsingItem(this.player); // Paper - Properly cancel usable items
|
||||
enuminteractionresult = (event.useItemInHand() != Event.Result.ALLOW) ? InteractionResult.SUCCESS : InteractionResult.PASS;
|
||||
} else if (this.gameModeForPlayer == GameType.SPECTATOR) {
|
||||
MenuProvider itileinventory = iblockdata.getMenuProvider(world, blockposition);
|
||||
@@ -604,6 +605,11 @@ public class ServerPlayerGameMode {
|
||||
|
||||
return enuminteractionresult1;
|
||||
}
|
||||
+ // Paper start - Properly cancel usable items; Cancel only if cancelled + if the interact result is different from default response
|
||||
+ else if (this.interactResult && this.interactResult != cancelledItem) {
|
||||
+ this.player.resyncUsingItem(this.player);
|
||||
+ }
|
||||
+ // Paper end - Properly cancel usable items
|
||||
}
|
||||
return enuminteractionresult;
|
||||
// CraftBukkit end
|
||||
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
index d0ae2c485b0e37406633c79043bd833a8a6b3e2d..b8db3c3a5870e9d7dbba38caf7c9e1c1f3849bde 100644
|
||||
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
||||
@@ -1990,6 +1990,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
}
|
||||
|
||||
if (cancelled) {
|
||||
+ this.player.resyncUsingItem(this.player); // Paper - Properly cancel usable items
|
||||
this.player.getBukkitEntity().updateInventory(); // SPIGOT-2524
|
||||
return;
|
||||
}
|
||||
@@ -2708,7 +2709,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl
|
||||
|
||||
// Entity in bucket - SPIGOT-4048 and SPIGOT-6859a
|
||||
if ((entity instanceof Bucketable && entity instanceof LivingEntity && origItem != null && origItem.asItem() == Items.WATER_BUCKET) && (event.isCancelled() || ServerGamePacketListenerImpl.this.player.getInventory().getSelected() == null || ServerGamePacketListenerImpl.this.player.getInventory().getSelected().getItem() != origItem)) {
|
||||
- ServerGamePacketListenerImpl.this.send(new ClientboundAddEntityPacket(entity));
|
||||
+ entity.getEntityData().resendPossiblyDesyncedEntity(player); // Paper - The entire mob gets deleted, so resend it.
|
||||
ServerGamePacketListenerImpl.this.player.containerMenu.sendAllDataToRemote();
|
||||
}
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
index 97b0119ac71284b3a223c089bec26d87a01d3b25..1e5f709115007ff19901c0a6c3cf884d9e4d3a6c 100644
|
||||
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
||||
@@ -391,7 +391,7 @@ public abstract class PlayerList {
|
||||
((ServerLevel)player.level()).getChunkSource().chunkMap.addEntity(player); // Paper - Fire PlayerJoinEvent when Player is actually ready; track entity now
|
||||
// CraftBukkit end
|
||||
|
||||
- player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn
|
||||
+ //player.getEntityData().refresh(player); // CraftBukkit - BungeeCord#2321, send complete data to self on spawn Paper - THIS IS NOT NEEDED ANYMORE
|
||||
|
||||
this.sendLevelInfo(player, worldserver1);
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index a9d549d1f35928b7e9220e1e2e4ac30f3199ba2d..28b4e9ebc35058c3e094c1f8bd87130e288cea33 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3844,6 +3844,11 @@ public abstract class LivingEntity extends Entity implements Attackable {
|
||||
return ((Byte) this.entityData.get(LivingEntity.DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND;
|
||||
}
|
||||
|
||||
+ // Paper start - Properly cancel usable items
|
||||
+ public void resyncUsingItem(ServerPlayer serverPlayer) {
|
||||
+ this.getEntityData().resendPossiblyDesyncedDataValues(java.util.List.of(DATA_LIVING_ENTITY_FLAGS), serverPlayer);
|
||||
+ }
|
||||
+ // Paper end - Properly cancel usable items
|
||||
private void updatingUsingItem() {
|
||||
if (this.isUsingItem()) {
|
||||
if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/animal/Bucketable.java b/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
|
||||
index a1bfd700cd4c39e4bb1b9c140b54b7c82cd8b32c..205b52e486123aa23a1469de896ab1ec2e70ca13 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/animal/Bucketable.java
|
||||
@@ -110,8 +110,7 @@ public interface Bucketable {
|
||||
itemstack1 = CraftItemStack.asNMSCopy(playerBucketFishEvent.getEntityBucket());
|
||||
if (playerBucketFishEvent.isCancelled()) {
|
||||
((ServerPlayer) player).containerMenu.sendAllDataToRemote(); // We need to update inventory to resync client's bucket
|
||||
- ((ServerPlayer) player).connection.send(new ClientboundAddEntityPacket(entity)); // We need to play out these packets as the client assumes the fish is gone
|
||||
- entity.getEntityData().refresh((ServerPlayer) player); // Need to send data such as the display name to client
|
||||
+ entity.getEntityData().resendPossiblyDesyncedEntity((ServerPlayer) player); // Paper
|
||||
return Optional.of(InteractionResult.FAIL);
|
||||
}
|
||||
entity.playSound(((Bucketable) entity).getPickupSound(), 1.0F, 1.0F);
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
index 76193067a21ff962cf2634b36d0ddf3eff8f85d7..e8e4489bcd64fde1b3226bdc7a7cc612508bda3f 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
|
||||
@@ -1000,7 +1000,11 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
return;
|
||||
}
|
||||
|
||||
- entityTracker.broadcast(this.getHandle().getAddEntityPacket());
|
||||
+ // Paper start, resend possibly desynced entity instead of add entity packet
|
||||
+ for (ServerPlayerConnection playerConnection : entityTracker.seenBy) {
|
||||
+ this.getHandle().getEntityData().resendPossiblyDesyncedEntity(playerConnection.getPlayer());
|
||||
+ }
|
||||
+ // Paper end
|
||||
}
|
||||
|
||||
private static PermissibleBase getPermissibleBase() {
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java
|
||||
index 0801bcdee8fcff0d388d302387e4f1d587e0a283..2fcd9b836d42e3549a3b6b921c57a4c103146dff 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftItemFrame.java
|
||||
@@ -39,9 +39,11 @@ public class CraftItemFrame extends CraftHanging implements ItemFrame {
|
||||
protected void update() {
|
||||
super.update();
|
||||
|
||||
+ // Paper start, don't mark as dirty as this is handled in super.update()
|
||||
// mark dirty, so that the client gets updated with item and rotation
|
||||
- this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ITEM);
|
||||
- this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ROTATION);
|
||||
+ //this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ITEM);
|
||||
+ //this.getHandle().getEntityData().markDirty(net.minecraft.world.entity.decoration.ItemFrame.DATA_ROTATION);
|
||||
+ // Paper end
|
||||
|
||||
// update redstone
|
||||
if (!this.getHandle().generation) {
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren