1.21.6 dev

Co-authored-by: Bjarne Koll <git@lynxplay.dev>
Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com>
Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com>
Co-authored-by: Noah van der Aa <ndvdaa@gmail.com>
Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
This commit is contained in:
Bjarne Koll
2025-05-28 13:23:32 +02:00
committed by Nassim Jahnke
parent 39203a65e0
commit a24f9b204c
788 changed files with 41006 additions and 6324 deletions

View File

@ -15,7 +15,7 @@ plugins {
val paperMavenPublicUrl = "https://repo.papermc.io/repository/maven-public/"
dependencies {
mache("io.papermc:mache:1.21.5+build.2")
mache("io.papermc:mache:1.21.6-rc1+build.1")
paperclip("io.papermc:paperclip:3.0.3")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
@ -24,11 +24,8 @@ paperweight {
minecraftVersion = providers.gradleProperty("mcVersion")
gitFilePatches = false
//updatingMinecraft {
// oldPaperCommit = "f4f275519f7c1fbe9db173b7144a4fe81440e365"
//}
spigot {
enabled = false
buildDataRef = "702e1a0a5072b2c4082371d5228cb30525687efc"
packageVersion = "v1_21_R4" // also needs to be updated in MappingEnvironment
}
@ -230,6 +227,11 @@ tasks.compileTestJava {
options.compilerArgs.add("-parameters")
}
// Bump compile tasks to 1GB memory to avoid OOMs
tasks.withType<JavaCompile>().configureEach {
options.forkOptions.memoryMaximumSize = "1G"
}
val scanJarForBadCalls by tasks.registering(io.papermc.paperweight.tasks.ScanJarForBadCalls::class) {
badAnnotations.add("Lio/papermc/paper/annotation/DoNotUse;")
jarToScan.set(tasks.jar.flatMap { it.archiveFile })

View File

@ -28,7 +28,7 @@ and then catch exceptions and close if they fire.
Part of this commit was authored by: Spottedleaf, sandtechnology
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42eafb96fa1 100644
index 2252c7c3e78c1d6dc9b56c0f6f01aec04699f072..235a076f982247552fef6d86d7e1b141eb8c72b5 100644
--- a/net/minecraft/network/Connection.java
+++ b/net/minecraft/network/Connection.java
@@ -85,7 +85,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@ -51,10 +51,10 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
public Connection(PacketFlow receiving) {
this.receiving = receiving;
@@ -423,11 +427,38 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -419,11 +423,38 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
public void send(Packet<?> packet, @Nullable PacketSendListener listener, boolean flush) {
public void send(Packet<?> packet, @Nullable ChannelFutureListener channelFutureListener, boolean flag) {
- if (this.isConnected()) {
- this.flushQueue();
+ // Paper start - Optimize network: Handle oversized packets better
@ -67,14 +67,14 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
+ if (connected && (InnerUtil.canSendImmediate(this, packet)
+ || (io.papermc.paper.util.MCUtil.isMainThread() && packet.isReady() && this.pendingActions.isEmpty()
+ && (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty())))) {
this.sendPacket(packet, listener, flush);
this.sendPacket(packet, channelFutureListener, flag);
} else {
- this.pendingActions.add(connection -> connection.sendPacket(packet, listener, flush));
- this.pendingActions.add(connection -> connection.sendPacket(packet, channelFutureListener, flag));
+ // Write the packets to the queue, then flush - antixray hooks there already
+ final java.util.List<Packet<?>> extraPackets = InnerUtil.buildExtraPackets(packet);
+ final boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty();
+ if (!hasExtraPackets) {
+ this.pendingActions.add(new PacketSendAction(packet, listener, flush));
+ this.pendingActions.add(new PacketSendAction(packet, channelFutureListener, flag));
+ } else {
+ final java.util.List<PacketSendAction> actions = new java.util.ArrayList<>(1 + extraPackets.size());
+ actions.add(new PacketSendAction(packet, null, false)); // Delay the future listener until the end of the extra packets
@ -82,7 +82,7 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
+ for (int i = 0, len = extraPackets.size(); i < len;) {
+ final Packet<?> extraPacket = extraPackets.get(i);
+ final boolean end = ++i == len;
+ actions.add(new PacketSendAction(extraPacket, end ? listener : null, end)); // Append listener to the end
+ actions.add(new PacketSendAction(extraPacket, end ? channelFutureListener : null, end)); // Append listener to the end
+ }
+
+ this.pendingActions.addAll(actions);
@ -93,7 +93,7 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
}
}
@@ -436,7 +467,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -432,7 +463,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.flushQueue();
action.accept(this);
} else {
@ -102,10 +102,10 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
}
}
@@ -450,6 +481,14 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -446,21 +477,41 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
private void doSendPacket(Packet<?> packet, @Nullable PacketSendListener sendListener, boolean flush) {
private void doSendPacket(Packet<?> packet, @Nullable ChannelFutureListener channelFutureListener, boolean flag) {
+ // Paper start - Optimize network
+ final net.minecraft.server.level.ServerPlayer player = this.getPlayer();
+ if (!this.isConnected()) {
@ -113,24 +113,29 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
+ return;
+ }
+ try {
+ final ChannelFuture channelFuture;
+ // Paper end - Optimize network
ChannelFuture channelFuture = flush ? this.channel.writeAndFlush(packet) : this.channel.write(packet);
if (sendListener != null) {
channelFuture.addListener(future -> {
@@ -465,14 +504,24 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
});
}
if (channelFutureListener != null) {
- ChannelFuture channelFuture = flag ? this.channel.writeAndFlush(packet) : this.channel.write(packet);
+ channelFuture = flag ? this.channel.writeAndFlush(packet) : this.channel.write(packet); // Paper - Optimize network
channelFuture.addListener(channelFutureListener);
} else if (flag) {
- this.channel.writeAndFlush(packet, this.channel.voidPromise());
+ channelFuture = this.channel.writeAndFlush(packet, this.channel.voidPromise()); // Paper - Optimize network
} else {
- this.channel.write(packet, this.channel.voidPromise());
+ channelFuture = this.channel.write(packet, this.channel.voidPromise()); // Paper - Optimize network
+ }
+
+ // Paper start - Optimize network
+ if (packet.hasFinishListener()) {
+ channelFuture.addListener((ChannelFutureListener) future -> packet.onPacketDispatchFinish(player, future));
+ }
channelFuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
+ } catch (final Exception e) {
+ LOGGER.error("NetworkException: {}", player, e);
+ this.disconnect(Component.translatable("disconnect.genericReason", "Internal Exception: " + e.getMessage()));
+ packet.onPacketDispatchFinish(player, null);
+ }
}
+ // Paper end - Optimize network
}
@ -143,7 +148,7 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
}
}
@@ -484,16 +533,57 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -472,16 +523,57 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
}
@ -206,7 +211,7 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper - Buffer joins to world
private static int joinAttemptsThisTick; // Paper - Buffer joins to world
@@ -563,6 +653,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -551,6 +643,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void disconnect(DisconnectionDetails disconnectionDetails) {
this.preparing = false; // Spigot
@ -214,7 +219,7 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
if (this.channel == null) {
this.delayedDisconnect = disconnectionDetails;
}
@@ -751,7 +842,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -739,7 +832,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void handleDisconnection() {
if (this.channel != null && !this.channel.isOpen()) {
if (this.disconnectionHandled) {
@ -223,7 +228,7 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
} else {
this.disconnectionHandled = true;
PacketListener packetListener = this.getPacketListener();
@@ -762,7 +853,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -750,7 +843,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
);
packetListener1.onDisconnect(disconnectionDetails);
}
@ -232,7 +237,7 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
// Paper start - Add PlayerConnectionCloseEvent
if (packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl commonPacketListener) {
/* Player was logged in, either game listener or configuration listener */
@@ -797,4 +888,97 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -785,4 +878,97 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void setBandwidthLogger(LocalSampleLogger bandwithLogger) {
this.bandwidthDebugMonitor = new BandwidthDebugMonitor(bandwithLogger);
}
@ -323,8 +328,8 @@ index 42f44c7cb0bd55ddfacd18acb0e596e7a953870e..2040b9555c430420a8a8697cc131d42e
+ private static final class PacketSendAction extends WrappedConsumer {
+ private final Packet<?> packet;
+
+ private PacketSendAction(final Packet<?> packet, @Nullable final PacketSendListener packetSendListener, final boolean flush) {
+ super(connection -> connection.sendPacket(packet, packetSendListener, flush));
+ private PacketSendAction(final Packet<?> packet, @Nullable final ChannelFutureListener channelFutureListener, final boolean flush) {
+ super(connection -> connection.sendPacket(packet, channelFutureListener, flush));
+ this.packet = packet;
+ }
+ }

View File

@ -15,19 +15,20 @@ Adds villagers as separate config
diff --git a/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ebee223085fe7926c7f3e555df19ae69f36157e
index 0000000000000000000000000000000000000000..ae2bb9a73106febfe5f0d090abd4252bbb5fd27e
--- /dev/null
+++ b/io/papermc/paper/entity/activation/ActivationRange.java
@@ -0,0 +1,318 @@
@@ -0,0 +1,334 @@
+package io.papermc.paper.entity.activation;
+
+import net.minecraft.core.BlockPos;
+import net.minecraft.server.MinecraftServer;
+import net.minecraft.world.entity.Entity;
+import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.entity.ExperienceOrb;
+import net.minecraft.world.entity.FlyingMob;
+import net.minecraft.world.entity.LightningBolt;
+import net.minecraft.world.entity.LivingEntity;
+import net.minecraft.world.entity.Marker;
+import net.minecraft.world.entity.Mob;
+import net.minecraft.world.entity.ai.Brain;
+import net.minecraft.world.entity.animal.Animal;
@ -38,6 +39,7 @@ index 0000000000000000000000000000000000000000..2ebee223085fe7926c7f3e555df19ae6
+import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
+import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
+import net.minecraft.world.entity.boss.wither.WitherBoss;
+import net.minecraft.world.entity.item.FallingBlockEntity;
+import net.minecraft.world.entity.item.ItemEntity;
+import net.minecraft.world.entity.item.PrimedTnt;
+import net.minecraft.world.entity.monster.Creeper;
@ -51,9 +53,13 @@ index 0000000000000000000000000000000000000000..2ebee223085fe7926c7f3e555df19ae6
+import net.minecraft.world.entity.projectile.ThrowableProjectile;
+import net.minecraft.world.entity.projectile.ThrownTrident;
+import net.minecraft.world.entity.schedule.Activity;
+import net.minecraft.world.entity.vehicle.AbstractBoat;
+import net.minecraft.world.entity.vehicle.AbstractMinecart;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.phys.AABB;
+import org.spigotmc.SpigotWorldConfig;
+import java.util.List;
+import java.util.Set;
+
+public final class ActivationRange {
+
@ -121,9 +127,9 @@ index 0000000000000000000000000000000000000000..2ebee223085fe7926c7f3e555df19ae6
+ || entity instanceof AbstractHurtingProjectile
+ || entity instanceof LightningBolt
+ || entity instanceof PrimedTnt
+ || entity instanceof net.minecraft.world.entity.item.FallingBlockEntity
+ || entity instanceof net.minecraft.world.entity.vehicle.AbstractMinecart
+ || entity instanceof net.minecraft.world.entity.vehicle.AbstractBoat
+ || entity instanceof FallingBlockEntity
+ || entity instanceof AbstractMinecart
+ || entity instanceof AbstractBoat
+ || entity instanceof EndCrystal
+ || entity instanceof FireworkRocketEntity
+ || entity instanceof ThrownTrident;
@ -172,10 +178,10 @@ index 0000000000000000000000000000000000000000..2ebee223085fe7926c7f3e555df19ae6
+ ActivationType.FLYING_MONSTER.boundingBox = player.getBoundingBox().inflate(flyingActivationRange, worldHeight, flyingActivationRange);
+ ActivationType.VILLAGER.boundingBox = player.getBoundingBox().inflate(villagerActivationRange, worldHeight, villagerActivationRange);
+
+ final java.util.List<Entity> entities = world.getEntities((Entity) null, ActivationRange.maxBB, e -> true);
+ final List<Entity> entities = world.getEntities((Entity) null, ActivationRange.maxBB, e -> true);
+ final boolean tickMarkers = world.paperConfig().entities.markers.tick;
+ for (final Entity entity : entities) {
+ if (!tickMarkers && entity instanceof net.minecraft.world.entity.Marker) {
+ if (!tickMarkers && entity instanceof Marker) {
+ continue;
+ }
+
@ -228,7 +234,7 @@ index 0000000000000000000000000000000000000000..2ebee223085fe7926c7f3e555df19ae6
+ return 100;
+ }
+ if (!(entity instanceof final AbstractArrow arrow)) {
+ if ((!entity.onGround() && !(entity instanceof FlyingMob))) {
+ if ((!entity.onGround() && !isEntityThatFlies(entity))) {
+ return 10;
+ }
+ } else if (!arrow.isInGround()) {
@ -336,9 +342,19 @@ index 0000000000000000000000000000000000000000..2ebee223085fe7926c7f3e555df19ae6
+ // removed the original's dumb tick skipping for active entities
+ return isActive;
+ }
+
+ private static Set<EntityType<?>> ENTITIES_THAT_FLY = Set.of(
+ EntityType.GHAST,
+ EntityType.HAPPY_GHAST,
+ EntityType.PHANTOM
+ );
+
+ private static boolean isEntityThatFlies(final Entity entity) {
+ return ENTITIES_THAT_FLY.contains(entity.getType());
+ }
+}
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 88b81a5fbc88e6240f86c1e780d80eb4b601df8c..00a5ed09caa2689543bd47bcd93d5a6141d0af46 100644
index 7b5ed00c9b2f22af5cbc44171192d674936dc7d7..5fe3c9a159908785e08fa874982bc1a82283bb1d 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableList;
@ -358,10 +374,10 @@ index 88b81a5fbc88e6240f86c1e780d80eb4b601df8c..00a5ed09caa2689543bd47bcd93d5a61
import java.io.Writer;
import java.nio.file.Path;
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 81c615d00323bdf86bdb76db17bb47288cf3feba..6b67cc939851745718f919488c997eb6719a16fc 100644
index 18551bebb7e40c936de94c6d1b009db4752d3bba..e6f958b6128213fb9577406c6495148dccac40ca 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -544,6 +544,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -548,6 +548,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
profilerFiller.pop();
}
@ -369,7 +385,7 @@ index 81c615d00323bdf86bdb76db17bb47288cf3feba..6b67cc939851745718f919488c997eb6
this.entityTickList
.forEach(
entity -> {
@@ -982,12 +983,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -990,12 +991,15 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
entity.totalEntityAge++; // Paper - age-like counter for all entities
profilerFiller.push(() -> BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString());
profilerFiller.incrementCounter("tickNonPassenger");
@ -386,7 +402,7 @@ index 81c615d00323bdf86bdb76db17bb47288cf3feba..6b67cc939851745718f919488c997eb6
}
// Paper start - log detailed entity tick information
} finally {
@@ -998,7 +1002,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1006,7 +1010,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Paper end - log detailed entity tick information
}
@ -395,7 +411,7 @@ index 81c615d00323bdf86bdb76db17bb47288cf3feba..6b67cc939851745718f919488c997eb6
if (passengerEntity.isRemoved() || passengerEntity.getVehicle() != ridingEntity) {
passengerEntity.stopRiding();
} else if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) {
@@ -1008,12 +1012,21 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1016,12 +1020,21 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push(() -> BuiltInRegistries.ENTITY_TYPE.getKey(passengerEntity.getType()).toString());
profilerFiller.incrementCounter("tickPassenger");
@ -419,10 +435,10 @@ index 81c615d00323bdf86bdb76db17bb47288cf3feba..6b67cc939851745718f919488c997eb6
}
}
diff --git a/net/minecraft/world/entity/AgeableMob.java b/net/minecraft/world/entity/AgeableMob.java
index f9cfa9dd17bd259cfbc0d96bf48a17556b365d8b..201c6d6e2f5799a7678b16f01c85508bc72e8af5 100644
index 16c5ad1547eb383e40c9fbae9b1119afc418b3a4..04875840085541ebfc7014868beec49bb7ab9976 100644
--- a/net/minecraft/world/entity/AgeableMob.java
+++ b/net/minecraft/world/entity/AgeableMob.java
@@ -129,6 +129,23 @@ public abstract class AgeableMob extends PathfinderMob {
@@ -130,6 +130,23 @@ public abstract class AgeableMob extends PathfinderMob {
super.onSyncedDataUpdated(key);
}
@ -447,10 +463,10 @@ index f9cfa9dd17bd259cfbc0d96bf48a17556b365d8b..201c6d6e2f5799a7678b16f01c85508b
public void aiStep() {
super.aiStep();
diff --git a/net/minecraft/world/entity/AreaEffectCloud.java b/net/minecraft/world/entity/AreaEffectCloud.java
index bf44f6b9c8710e0c9a85d44f6217501abc98a7b1..bfd904e468bbf2cc1a5b3353d3a69ad5087c81ae 100644
index c70a58f5f633fa8e255f74c42f5e87c96b7b013a..ec20a5a6d7c8f65abda528fec36bec7bc71117f6 100644
--- a/net/minecraft/world/entity/AreaEffectCloud.java
+++ b/net/minecraft/world/entity/AreaEffectCloud.java
@@ -144,6 +144,16 @@ public class AreaEffectCloud extends Entity implements TraceableEntity {
@@ -142,6 +142,16 @@ public class AreaEffectCloud extends Entity implements TraceableEntity {
this.duration = duration;
}
@ -468,10 +484,10 @@ index bf44f6b9c8710e0c9a85d44f6217501abc98a7b1..bfd904e468bbf2cc1a5b3353d3a69ad5
public void tick() {
super.tick();
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index a63873a0fe4335813cafe84cae2b2030c8f0e627..f0c72465a71dc5a51c22af5e614af744b0434e94 100644
index f961540a00bfb5e1c8eb0e739f8ae535e9eee8f3..7453ddb09f349b7836f966573e4933646a75cba6 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -388,6 +388,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -409,6 +409,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
private final int despawnTime; // Paper - entity despawn time limit
public int totalEntityAge; // Paper - age-like counter for all entities
public final io.papermc.paper.entity.activation.ActivationType activationType = io.papermc.paper.entity.activation.ActivationType.activationTypeFor(this); // Paper - EAR 2/tracking ranges
@ -487,7 +503,7 @@ index a63873a0fe4335813cafe84cae2b2030c8f0e627..f0c72465a71dc5a51c22af5e614af744
// CraftBukkit end
// Paper start
@@ -407,6 +416,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -424,6 +433,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.position = Vec3.ZERO;
this.blockPosition = BlockPos.ZERO;
this.chunkPosition = ChunkPos.ZERO;
@ -501,7 +517,7 @@ index a63873a0fe4335813cafe84cae2b2030c8f0e627..f0c72465a71dc5a51c22af5e614af744
SynchedEntityData.Builder builder = new SynchedEntityData.Builder(this);
builder.define(DATA_SHARED_FLAGS_ID, (byte)0);
builder.define(DATA_AIR_SUPPLY_ID, this.getMaxAirSupply());
@@ -962,6 +978,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -984,6 +1000,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z);
} else {
if (type == MoverType.PISTON) {
@ -512,7 +528,7 @@ index a63873a0fe4335813cafe84cae2b2030c8f0e627..f0c72465a71dc5a51c22af5e614af744
movement = this.limitPistonMovement(movement);
if (movement.equals(Vec3.ZERO)) {
return;
@@ -975,6 +995,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -997,6 +1017,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.stuckSpeedMultiplier = Vec3.ZERO;
this.setDeltaMovement(Vec3.ZERO);
}
@ -527,10 +543,10 @@ index a63873a0fe4335813cafe84cae2b2030c8f0e627..f0c72465a71dc5a51c22af5e614af744
movement = this.maybeBackOffFromEdge(movement, type);
Vec3 vec3 = this.collide(movement);
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 267544f50fafd914566df1c4b2327bc64d673165..3e8f4f3c3d43c6875108295187023c48eece2788 100644
index 13cf40918ead3e2cb2699398ac659a3e1806294b..1ba342a1a60951f828034d3ed535b577b3990bf6 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -3163,6 +3163,14 @@ public abstract class LivingEntity extends Entity implements Attackable {
@@ -3215,6 +3215,14 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
return false;
}
@ -546,10 +562,10 @@ index 267544f50fafd914566df1c4b2327bc64d673165..3e8f4f3c3d43c6875108295187023c48
public void tick() {
super.tick();
diff --git a/net/minecraft/world/entity/Mob.java b/net/minecraft/world/entity/Mob.java
index 8f5c377540f83911c8d245fb00569f08dbc6a690..73ba442b9d39bc021cd5eb6c1c0f98aed94a5a02 100644
index 3047763580fabd069db5e90a9a854396c6243763..0470c4bbf8be7e48ce8dfa4910c3b9f5ebb23360 100644
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -203,6 +203,19 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
@@ -206,6 +206,19 @@ public abstract class Mob extends LivingEntity implements EquipmentUser, Leashab
return this.lookControl;
}
@ -570,7 +586,7 @@ index 8f5c377540f83911c8d245fb00569f08dbc6a690..73ba442b9d39bc021cd5eb6c1c0f98ae
return this.getControlledVehicle() instanceof Mob mob ? mob.getMoveControl() : this.moveControl;
}
diff --git a/net/minecraft/world/entity/PathfinderMob.java b/net/minecraft/world/entity/PathfinderMob.java
index 0caf50ec50f056b83a20bbc6a2fe0144593aef39..af59a700755654eb68d6bf57d0712c4a2ac6c09b 100644
index 60cc5cf40967eee8988cda8a45ff098e66e8ddf2..741b5078ab9ee9b8463c61ab66ba9b5c9cda0974 100644
--- a/net/minecraft/world/entity/PathfinderMob.java
+++ b/net/minecraft/world/entity/PathfinderMob.java
@@ -17,6 +17,8 @@ public abstract class PathfinderMob extends Mob {
@ -583,10 +599,10 @@ index 0caf50ec50f056b83a20bbc6a2fe0144593aef39..af59a700755654eb68d6bf57d0712c4a
return this.getWalkTargetValue(pos, this.level());
}
diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java
index 9338e63cc28413f5559bb0122ef5e04a84bd51d1..eeba224bd575451ba6023df65ef9d9b97f7f1c71 100644
index d552e47aa38c61a8f78ed114a3433603c9658a24..674966c580220a4e0c83a628c763aaea8bfd0b1c 100644
--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
@@ -25,6 +25,7 @@ public class GoalSelector {
@@ -24,6 +24,7 @@ public class GoalSelector {
private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap<>(Goal.Flag.class);
private final Set<WrappedGoal> availableGoals = new ObjectLinkedOpenHashSet<>();
private final EnumSet<Goal.Flag> disabledFlags = EnumSet.noneOf(Goal.Flag.class);
@ -594,7 +610,7 @@ index 9338e63cc28413f5559bb0122ef5e04a84bd51d1..eeba224bd575451ba6023df65ef9d9b9
public void addGoal(int priority, Goal goal) {
this.availableGoals.add(new WrappedGoal(priority, goal));
@@ -35,6 +36,22 @@ public class GoalSelector {
@@ -33,6 +34,22 @@ public class GoalSelector {
this.availableGoals.removeIf(wrappedGoal -> filter.test(wrappedGoal.getGoal()));
}
@ -618,7 +634,7 @@ index 9338e63cc28413f5559bb0122ef5e04a84bd51d1..eeba224bd575451ba6023df65ef9d9b9
for (WrappedGoal wrappedGoal : this.availableGoals) {
if (wrappedGoal.getGoal() == goal && wrappedGoal.isRunning()) {
diff --git a/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
index 789fea258d70e60d38271ebb31270562dc7eb3ab..d0ab3db7bbd2942db19f473474371b20ce822608 100644
index 3f780276be6766ef253c50212e06fd93a96b0caa..7e70c7bee633c54497d1cd2854dd60f4fb5ff160 100644
--- a/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
+++ b/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
@@ -23,6 +23,14 @@ public abstract class MoveToBlockGoal extends Goal {
@ -638,17 +654,17 @@ index 789fea258d70e60d38271ebb31270562dc7eb3ab..d0ab3db7bbd2942db19f473474371b20
this.mob = mob;
@@ -113,6 +121,7 @@ public abstract class MoveToBlockGoal extends Goal {
mutableBlockPos.setWithOffset(blockPos, i4, i2 - 1, i5);
if (this.mob.isWithinRestriction(mutableBlockPos) && this.isValidTarget(this.mob.level(), mutableBlockPos)) {
if (this.mob.isWithinHome(mutableBlockPos) && this.isValidTarget(this.mob.level(), mutableBlockPos)) {
this.blockPos = mutableBlockPos;
+ this.mob.movingTarget = mutableBlockPos == BlockPos.ZERO ? null : mutableBlockPos.immutable(); // Paper
return true;
}
}
diff --git a/net/minecraft/world/entity/item/ItemEntity.java b/net/minecraft/world/entity/item/ItemEntity.java
index ea3afc27600cde05a17197b071f14972d2c832e6..6c0ebfb2be4e8b884456a2aa3d5fdc87e45a0e3c 100644
index 548d7c8dc517da6c4db86b11f579ae63e6db56cf..a29860af4c37b2b45df49f9ba18f7e38921dfb02 100644
--- a/net/minecraft/world/entity/item/ItemEntity.java
+++ b/net/minecraft/world/entity/item/ItemEntity.java
@@ -131,6 +131,29 @@ public class ItemEntity extends Entity implements TraceableEntity {
@@ -121,6 +121,29 @@ public class ItemEntity extends Entity implements TraceableEntity {
return 0.04;
}
@ -679,10 +695,10 @@ index ea3afc27600cde05a17197b071f14972d2c832e6..6c0ebfb2be4e8b884456a2aa3d5fdc87
public void tick() {
if (this.getItem().isEmpty()) {
diff --git a/net/minecraft/world/entity/npc/Villager.java b/net/minecraft/world/entity/npc/Villager.java
index 94032c60944f161519f0ddee69426cbfe3075170..e0e0d2ea7fc60e3142c675404d152eca60263240 100644
index b0607f4a9b35570b319423c7876bb904d5154e8e..98c8653647dc52059d8becfe38a74d4e62edf08f 100644
--- a/net/minecraft/world/entity/npc/Villager.java
+++ b/net/minecraft/world/entity/npc/Villager.java
@@ -268,11 +268,35 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -269,11 +269,35 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
return this.assignProfessionWhenSpawned;
}
@ -719,7 +735,7 @@ index 94032c60944f161519f0ddee69426cbfe3075170..e0e0d2ea7fc60e3142c675404d152eca
profilerFiller.pop();
if (this.assignProfessionWhenSpawned) {
this.assignProfessionWhenSpawned = false;
@@ -296,7 +320,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -297,7 +321,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
this.lastTradedPlayer = null;
}
@ -728,7 +744,7 @@ index 94032c60944f161519f0ddee69426cbfe3075170..e0e0d2ea7fc60e3142c675404d152eca
Raid raidAt = level.getRaidAt(this.blockPosition());
if (raidAt != null && raidAt.isActive() && !raidAt.isOver()) {
level.broadcastEntityEvent(this, (byte)42);
@@ -307,6 +331,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
@@ -308,6 +332,7 @@ public class Villager extends AbstractVillager implements ReputationEventHandler
this.stopTrading();
}
@ -758,10 +774,10 @@ index 1f22f44abb21d1ed9a4870f668779efb8fd9b295..91ead824718eeea2afba3bc0ef619b8a
public void tick() {
super.tick();
diff --git a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
index dcb7714b2edeab8cfb0358929d07bd04cead26bf..e0e193078e550225e163149638bf9e053c0531f8 100644
index 7d5c6eec8e7c2448a3502255135dd9154b6ed2d8..d8dc196ef92e97f831cf97cd1536a46f81f9d5d1 100644
--- a/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
+++ b/net/minecraft/world/entity/projectile/FireworkRocketEntity.java
@@ -109,6 +109,21 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier {
@@ -107,6 +107,21 @@ public class FireworkRocketEntity extends Projectile implements ItemSupplier {
return super.shouldRender(x, y, z) && !this.isAttachedToEntity();
}
@ -784,10 +800,10 @@ index dcb7714b2edeab8cfb0358929d07bd04cead26bf..e0e193078e550225e163149638bf9e05
public void tick() {
super.tick();
diff --git a/net/minecraft/world/entity/vehicle/MinecartHopper.java b/net/minecraft/world/entity/vehicle/MinecartHopper.java
index 6162415095b030b4cc47364c56fa66236b3b0535..a56d9cdeb6589a053ffaaf2cd599a98ae0a0989a 100644
index 52acc72841f0c6980f5f3f8ef21d0b29dd472ce3..41a6ec508a10a49a37539d2f10171d15c233b280 100644
--- a/net/minecraft/world/entity/vehicle/MinecartHopper.java
+++ b/net/minecraft/world/entity/vehicle/MinecartHopper.java
@@ -48,6 +48,7 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
@@ -49,6 +49,7 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
if (flag != this.isEnabled()) {
this.setEnabled(flag);
}
@ -795,7 +811,7 @@ index 6162415095b030b4cc47364c56fa66236b3b0535..a56d9cdeb6589a053ffaaf2cd599a98a
}
public boolean isEnabled() {
@@ -101,11 +102,13 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
@@ -102,11 +103,13 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
public boolean suckInItems() {
if (HopperBlockEntity.suckInItems(this.level(), this)) {
@ -809,7 +825,7 @@ index 6162415095b030b4cc47364c56fa66236b3b0535..a56d9cdeb6589a053ffaaf2cd599a98a
return true;
}
}
@@ -140,4 +143,11 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
@@ -141,4 +144,11 @@ public class MinecartHopper extends AbstractMinecartContainer implements Hopper
public AbstractContainerMenu createMenu(int id, Inventory playerInventory) {
return new HopperMenu(id, playerInventory, this);
}
@ -822,7 +838,7 @@ index 6162415095b030b4cc47364c56fa66236b3b0535..a56d9cdeb6589a053ffaaf2cd599a98a
+
}
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index fff4914de57dff26f66259a145d662ff5c96d840..1bb40f18b671d63719d96a58ff283767c2cfe383 100644
index d26e4d85d8fd8bd4f0c7de30b50a2ce370b37bf5..bab28e7afb7b1249d40631aabff16fc18cf95ea0 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -143,6 +143,12 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
@ -839,10 +855,10 @@ index fff4914de57dff26f66259a145d662ff5c96d840..1bb40f18b671d63719d96a58ff283767
public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot
// Paper start - add paper world config
diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
index f8d10be7a0aa7f66f05126e75187025c040e3494..1669b76800756000a2f620610b3c8c8b6c48dd4a 100644
index ba757b3accf0ee7e57f82507a6c04b90ae850d55..f1ce4cff1c03a0037ade2c8ef989cf327c973a7e 100644
--- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
+++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java
@@ -153,6 +153,10 @@ public class PistonMovingBlockEntity extends BlockEntity {
@@ -152,6 +152,10 @@ public class PistonMovingBlockEntity extends BlockEntity {
}
entity.setDeltaMovement(d1, d2, d3);

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Anti-Xray
diff --git a/io/papermc/paper/FeatureHooks.java b/io/papermc/paper/FeatureHooks.java
index b9a838d638571bca1d00a620cedf169a3fa87e9d..329e9562e9c2b25228b04c21ff7353d2d8d6e5f6 100644
index dce30842f6abab549f3abc25226604bb70ad0624..0a80ab83ca69b8b51fb1bb8c12ee6fcf439a3ac4 100644
--- a/io/papermc/paper/FeatureHooks.java
+++ b/io/papermc/paper/FeatureHooks.java
@@ -37,20 +37,25 @@ public final class FeatureHooks {
@ -39,7 +39,7 @@ index b9a838d638571bca1d00a620cedf169a3fa87e9d..329e9562e9c2b25228b04c21ff7353d2
public static Set<Long> getSentChunkKeys(final ServerPlayer player) {
diff --git a/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java b/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java
index d4872b7f4e9591b3b1c67406312905851303f521..cb41460e94161675e2ab43f4b1b5286ee38e2e13 100644
index c9086bca5cbb780fd586f667e31a8fe1400ae58a..f828d07018d9a17aaa0142aac67ebed58dd84c3e 100644
--- a/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java
+++ b/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java
@@ -70,8 +70,10 @@ public record ClientboundChunksBiomesPacket(List<ClientboundChunksBiomesPacket.C
@ -52,10 +52,10 @@ index d4872b7f4e9591b3b1c67406312905851303f521..cb41460e94161675e2ab43f4b1b5286e
+ levelChunkSection.getBiomes().write(buffer, null, chunkSectionIndex); // Paper - Anti-Xray
+ chunkSectionIndex++; // Paper - Anti-Xray
}
}
if (buffer.writerIndex() != buffer.capacity()) {
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
index 89761bd368d75b8fb84f850fb3f8162fa280e236..272da41db7ce4619a8e459a2f0a2221e42f58a40 100644
index de234f220ba09ad9b5e0c8215b49d20ca51d0ac7..83c4b454472714de6ebf99cd4e50867920d07509 100644
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -33,13 +33,23 @@ public class ClientboundLevelChunkPacketData {
@ -100,8 +100,8 @@ index 89761bd368d75b8fb84f850fb3f8162fa280e236..272da41db7ce4619a8e459a2f0a2221e
+ chunkSectionIndex++;
+ // Paper end - Anti-Xray - Add chunk packet info
}
}
if (buffer.writerIndex() != buffer.capacity()) {
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
index 3a384175f8e7f204234bbaf3081bdc20c47a0d4b..5699bc15eba92e22433a20cb8326b59f2ebd3036 100644
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
@ -143,10 +143,10 @@ index 3a384175f8e7f204234bbaf3081bdc20c47a0d4b..5699bc15eba92e22433a20cb8326b59f
private ClientboundLevelChunkWithLightPacket(RegistryFriendlyByteBuf buffer) {
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 6b67cc939851745718f919488c997eb6719a16fc..085040aa98704f2874bcd95b751b0a81dcdb15ad 100644
index e6f958b6128213fb9577406c6495148dccac40ca..49008b4cbaead8a66a93d2b0d4b50b335a6c3eed 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -343,7 +343,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -346,7 +346,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
org.bukkit.generator.BiomeProvider biomeProvider // CraftBukkit
) {
// CraftBukkit start
@ -156,7 +156,7 @@ index 6b67cc939851745718f919488c997eb6719a16fc..085040aa98704f2874bcd95b751b0a81
this.levelStorageAccess = levelStorageAccess;
this.uuid = org.bukkit.craftbukkit.util.WorldUUID.getOrCreate(levelStorageAccess.levelDirectory.path().toFile());
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
index b5378d6d73b6dab56bf664024f3f82496e9a9487..b604cba2490a747661d6819251bc3b9a1d35c7d4 100644
index b29ecfcc07304c1ee3d77cd431db0889ebc7d6b1..6734756d7a51e635a50a47577f9e6b6f8111db51 100644
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -296,6 +296,7 @@ public class ServerPlayerGameMode {
@ -168,7 +168,7 @@ index b5378d6d73b6dab56bf664024f3f82496e9a9487..b604cba2490a747661d6819251bc3b9a
public void destroyAndAck(BlockPos pos, int sequence, String message) {
diff --git a/net/minecraft/server/network/PlayerChunkSender.java b/net/minecraft/server/network/PlayerChunkSender.java
index 342bc843c384761e883de861044f4f8930ae8763..14878690a88fd4de3e2c127086607e6c819c636c 100644
index 8cd7363704d4532c926dbf4778eb4dfec5fdf8bc..0376a10ee0544b13e8fd629a7b13f78811e57a30 100644
--- a/net/minecraft/server/network/PlayerChunkSender.java
+++ b/net/minecraft/server/network/PlayerChunkSender.java
@@ -78,8 +78,11 @@ public class PlayerChunkSender {
@ -186,20 +186,20 @@ index 342bc843c384761e883de861044f4f8930ae8763..14878690a88fd4de3e2c127086607e6c
if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), packetListener.getPlayer().getBukkitEntity()).callEvent();
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 9b2ee3e16e2c443e8ff03faec59dd55d729e9274..5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8 100644
index b595fc3bd844eaf2a56f70f166523ee6254386b6..891d3e13057c6034c59a78e594935c433921de04 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -407,7 +407,7 @@ public abstract class PlayerList {
@@ -408,7 +408,7 @@ public abstract class PlayerList {
.getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
new net.minecraft.world.level.chunk.EmptyLevelChunk(serverLevel, player.chunkPosition(), plains),
- serverLevel.getLightEngine(), (java.util.BitSet)null, (java.util.BitSet) null)
+ serverLevel.getLightEngine(), (java.util.BitSet)null, (java.util.BitSet) null, true) // Paper - Anti-Xray
);
}
// Paper end - Send empty chunk
);
}
// Paper end - Send empty chunk
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 1bb40f18b671d63719d96a58ff283767c2cfe383..ba50f21707a69bbf720345996d7c83d2064e5246 100644
index 980eaba27ce2616c1573a4760cf4acc2dd251190..1eb8cb187d33510a4e99d229e721a2e7db4012ad 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -132,6 +132,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
@ -237,10 +237,10 @@ index 1bb40f18b671d63719d96a58ff283767c2cfe383..ba50f21707a69bbf720345996d7c83d2
if (blockState == null) {
// CraftBukkit start - remove blockstate if failed (or the same)
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
index c378f9e226df80ab0d4ebd06ae54ce556d0d94e7..97231db28146df56c727c9765f36277634d59a64 100644
index f98ee299f5900b0a66c447d7970bd16a7ced1086..d1ae452f0aa96c36afe8b7ecddd3e06b06165878 100644
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
@@ -114,14 +114,14 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
@@ -115,14 +115,14 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
}
}
@ -259,10 +259,10 @@ index c378f9e226df80ab0d4ebd06ae54ce556d0d94e7..97231db28146df56c727c9765f362776
}
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 8fa871512ad52c345f15b1f5fb1baf54bb2ec93b..08e2442f6965cc6eaab67bdf9340a5152c08db2a 100644
index 1e60b295f8fa672ecee96a71fd1fea14339b7054..6f19586b4a39541c0fb895a18a0a4fd9b5da504c 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -110,7 +110,7 @@ public class LevelChunk extends ChunkAccess {
@@ -112,7 +112,7 @@ public class LevelChunk extends ChunkAccess {
@Nullable LevelChunk.PostLoadProcessor postLoad,
@Nullable BlendingData blendingData
) {
@ -313,10 +313,10 @@ index 2399a0f8839c0925a9923bae87362c2c9a217197..1aa4e39431a93a7789b74a2e3476a3e4
public int getSerializedSize() {
diff --git a/net/minecraft/world/level/chunk/PalettedContainer.java b/net/minecraft/world/level/chunk/PalettedContainer.java
index 5a3ed1c2dd22434d96947580c4dff28a95eb8252..1491401ec94038450ea5eeb589fc33a336a3ae55 100644
index cd2b1240f13acaaecbb8e6d0f7f8b326ab24b5b0..9b0f17841230640f532ac33bb86e6585e88b5a57 100644
--- a/net/minecraft/world/level/chunk/PalettedContainer.java
+++ b/net/minecraft/world/level/chunk/PalettedContainer.java
@@ -28,6 +28,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -27,6 +27,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
private static final int MIN_PALETTE_BITS = 0;
private final PaletteResize<T> dummyPaletteResize = (bits, objectAdded) -> 0;
public final IdMap<T> registry;
@ -324,7 +324,7 @@ index 5a3ed1c2dd22434d96947580c4dff28a95eb8252..1491401ec94038450ea5eeb589fc33a3
private volatile PalettedContainer.Data<T> data;
private final PalettedContainer.Strategy strategy;
//private final ThreadingDetector threadingDetector = new ThreadingDetector("PalettedContainer"); // Paper - unused
@@ -40,13 +41,21 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -39,13 +40,21 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
// this.threadingDetector.checkAndUnlock(); // Paper - disable this - use proper synchronization
}
@ -348,7 +348,7 @@ index 5a3ed1c2dd22434d96947580c4dff28a95eb8252..1491401ec94038450ea5eeb589fc33a3
.map(container -> (PalettedContainerRO<T>)container);
return codec(registry, codec, strategy, value, unpacker);
}
@@ -66,27 +75,66 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -65,27 +74,66 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
);
}
@ -418,7 +418,7 @@ index 5a3ed1c2dd22434d96947580c4dff28a95eb8252..1491401ec94038450ea5eeb589fc33a3
this.strategy = strategy;
this.registry = registry;
this.data = this.createOrReuseData(null, 0);
@@ -101,11 +149,30 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -100,11 +148,30 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@Override
public synchronized int onResize(int bits, T objectAdded) { // Paper - synchronize
PalettedContainer.Data<T> data = this.data;
@ -450,7 +450,7 @@ index 5a3ed1c2dd22434d96947580c4dff28a95eb8252..1491401ec94038450ea5eeb589fc33a3
public synchronized T getAndSet(int x, int y, int z, T state) { // Paper - synchronize
this.acquire();
@@ -172,24 +239,35 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -171,24 +238,35 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
data.palette.read(buffer);
buffer.readFixedSizeLongArray(data.storage.getRaw());
this.data = data;
@ -489,7 +489,7 @@ index 5a3ed1c2dd22434d96947580c4dff28a95eb8252..1491401ec94038450ea5eeb589fc33a3
) {
List<T> list = packedData.paletteEntries();
int size = strategy.size();
@@ -222,7 +300,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -221,7 +299,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
}
}
@ -498,7 +498,7 @@ index 5a3ed1c2dd22434d96947580c4dff28a95eb8252..1491401ec94038450ea5eeb589fc33a3
}
@Override
@@ -280,12 +358,12 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@@ -279,12 +357,12 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
@Override
public PalettedContainer<T> copy() {
@ -513,8 +513,8 @@ index 5a3ed1c2dd22434d96947580c4dff28a95eb8252..1491401ec94038450ea5eeb589fc33a3
}
@Override
@@ -324,9 +402,16 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
return 1 + this.palette.getSerializedSize() + VarInt.getByteSize(this.storage.getRaw().length) + this.storage.getRaw().length * 8;
@@ -323,9 +401,16 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
return 1 + this.palette.getSerializedSize() + this.storage.getRaw().length * 8;
}
- public void write(FriendlyByteBuf buffer) {
@ -548,10 +548,10 @@ index bfbb1a2bb4abbb369a24f2f01439e9ea3e16794b..8d6ed8be4d93f7d4e6ea80c351020d88
int getSerializedSize();
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index 8efb5148a22b57ed090fb8fd20dd642223b3fb95..58bc96235f0149ea868da3bc3d20472f96d5f6ec 100644
index e846bda9517f3325f0d343758d3235382bb8980d..15417fab103feec3c1f7d5bd5b332e89d3ace3f5 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -94,7 +94,7 @@ public record SerializableChunkData(
@@ -96,7 +96,7 @@ public record SerializableChunkData(
, @Nullable net.minecraft.nbt.Tag persistentDataContainer // CraftBukkit - persistentDataContainer
) {
public static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(
@ -560,7 +560,7 @@ index 8efb5148a22b57ed090fb8fd20dd642223b3fb95..58bc96235f0149ea868da3bc3d20472f
);
private static final Codec<List<SavedTick<Block>>> BLOCK_TICKS_CODEC = SavedTick.codec(BuiltInRegistries.BLOCK.byNameCodec()).listOf();
private static final Codec<List<SavedTick<Fluid>>> FLUID_TICKS_CODEC = SavedTick.codec(BuiltInRegistries.FLUID.byNameCodec()).listOf();
@@ -130,6 +130,7 @@ public record SerializableChunkData(
@@ -132,6 +132,7 @@ public record SerializableChunkData(
@Nullable
public static SerializableChunkData parse(LevelHeightAccessor levelHeightAccessor, RegistryAccess registries, CompoundTag tag) {
@ -568,7 +568,7 @@ index 8efb5148a22b57ed090fb8fd20dd642223b3fb95..58bc96235f0149ea868da3bc3d20472f
if (tag.getString("Status").isEmpty()) {
return null;
} else {
@@ -190,15 +191,17 @@ public record SerializableChunkData(
@@ -192,15 +193,17 @@ public record SerializableChunkData(
int byteOr = compoundTag.getByteOr("Y", (byte)0);
LevelChunkSection levelChunkSection;
if (byteOr >= levelHeightAccessor.getMinSectionY() && byteOr <= levelHeightAccessor.getMaxSectionY()) {
@ -588,7 +588,7 @@ index 8efb5148a22b57ed090fb8fd20dd642223b3fb95..58bc96235f0149ea868da3bc3d20472f
)
);
PalettedContainer<Holder<Biome>> palettedContainerRo = compoundTag.getCompound("biomes") // CraftBukkit - read/write
@@ -209,7 +212,7 @@ public record SerializableChunkData(
@@ -211,7 +214,7 @@ public record SerializableChunkData(
)
.orElseGet(
() -> new PalettedContainer<>(
@ -597,7 +597,7 @@ index 8efb5148a22b57ed090fb8fd20dd642223b3fb95..58bc96235f0149ea868da3bc3d20472f
)
);
levelChunkSection = new LevelChunkSection(palettedContainer, palettedContainerRo);
@@ -382,7 +385,7 @@ public record SerializableChunkData(
@@ -384,7 +387,7 @@ public record SerializableChunkData(
// CraftBukkit start - read/write
private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodecRW(Registry<Biome> biomeRegistry) {

View File

@ -269,10 +269,10 @@ index bc674b08a41d5529fe06c6d3f077051cf4138f73..ea8a894158c44c2e7943dea43ecd8e1f
+ // Paper end - Use Velocity cipher
}
diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
index 2040b9555c430420a8a8697cc131d42eafb96fa1..4ed9611994c5c8da01fede690197527c5b3a5731 100644
index 235a076f982247552fef6d86d7e1b141eb8c72b5..34524dc5a503bebcec99ada0d9560d6f4df48cdf 100644
--- a/net/minecraft/network/Connection.java
+++ b/net/minecraft/network/Connection.java
@@ -772,11 +772,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -762,11 +762,22 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
return connection;
}
@ -299,7 +299,7 @@ index 2040b9555c430420a8a8697cc131d42eafb96fa1..4ed9611994c5c8da01fede690197527c
public boolean isEncrypted() {
return this.encrypted;
@@ -815,16 +826,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -805,16 +816,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
// Paper end - add proper async disconnect
public void setupCompression(int threshold, boolean validateDecompressed) {
if (threshold >= 0) {

View File

@ -14,10 +14,10 @@ movement will load only the chunk the player enters anyways and avoids loading
massive amounts of surrounding chunks due to large AABB lookups.
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index a8eaccde3ec9ed912cbc6df0b29e9f8136a46578..0f6ca6ef161ac2934ba761a1eca3215290c7262b 100644
index 7453ddb09f349b7836f966573e4933646a75cba6..58eda0d6426f30cda604f4120f1ddb012316c108 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -223,6 +223,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -229,6 +229,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// Paper end - Share random for entities to make them more random
public @Nullable org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason; // Paper - Entity#getEntitySpawnReason
@ -76,7 +76,7 @@ index ed6e4f9fd0c7ad1219e66bc1cb4038191dd6edd8..45a20dbb935b12d429153463dba5d6fd
&& (nextType != 2 || blockState.is(Blocks.MOVING_PISTON))) {
VoxelShape collisionShape = this.context.getCollisionShape(blockState, this.collisionGetter, this.pos);
diff --git a/net/minecraft/world/level/CollisionGetter.java b/net/minecraft/world/level/CollisionGetter.java
index 79af1e4dd1f84580e509ac3e9a77bcd5531c8da6..a031d39854eb049a701f3de9e11c73419883d5ca 100644
index 8956e5d66481d8ca874999df8f38eb28651362db..056005f0728ba14c9d0dd9dd16400a35a9656243 100644
--- a/net/minecraft/world/level/CollisionGetter.java
+++ b/net/minecraft/world/level/CollisionGetter.java
@@ -50,11 +50,13 @@ public interface CollisionGetter extends BlockGetter {

View File

@ -7,7 +7,7 @@ Optimise the stream.anyMatch statement to move to a bitset
where we can replace the call with a single bitwise operation.
diff --git a/net/minecraft/world/entity/ai/goal/Goal.java b/net/minecraft/world/entity/ai/goal/Goal.java
index d4f8387254a65b25fc808932a069298d0f8da091..5f5bf0e710ecff09a571091e5a923332be70cb74 100644
index a66c86066ca2eda10f0ef62e5197a765a994f250..f54bbe2e65b18f214266769c7a64144baafa9a58 100644
--- a/net/minecraft/world/entity/ai/goal/Goal.java
+++ b/net/minecraft/world/entity/ai/goal/Goal.java
@@ -7,7 +7,15 @@ import net.minecraft.world.entity.Entity;
@ -69,10 +69,10 @@ index d4f8387254a65b25fc808932a069298d0f8da091..5f5bf0e710ecff09a571091e5a923332
// Paper end - Mob Goal API
diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java
index eeba224bd575451ba6023df65ef9d9b97f7f1c71..a927c2790c8ab9ccaa7161b970e10b0b44817dd8 100644
index 674966c580220a4e0c83a628c763aaea8bfd0b1c..859b859d29b637200cf7c9a0bd52d9f712413e3d 100644
--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
@@ -24,7 +24,8 @@ public class GoalSelector {
@@ -23,7 +23,8 @@ public class GoalSelector {
};
private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap<>(Goal.Flag.class);
private final Set<WrappedGoal> availableGoals = new ObjectLinkedOpenHashSet<>();
@ -82,7 +82,7 @@ index eeba224bd575451ba6023df65ef9d9b97f7f1c71..a927c2790c8ab9ccaa7161b970e10b0b
private int curRate; // Paper - EAR 2
public void addGoal(int priority, Goal goal) {
@@ -62,18 +63,18 @@ public class GoalSelector {
@@ -60,18 +61,18 @@ public class GoalSelector {
this.availableGoals.removeIf(wrappedGoal1 -> wrappedGoal1.getGoal() == goal);
}
@ -110,7 +110,7 @@ index eeba224bd575451ba6023df65ef9d9b97f7f1c71..a927c2790c8ab9ccaa7161b970e10b0b
if (!flag.getOrDefault(flag1, NO_GOAL).canBeReplacedBy(goal)) {
return false;
}
@@ -87,7 +88,7 @@ public class GoalSelector {
@@ -85,7 +86,7 @@ public class GoalSelector {
profilerFiller.push("goalCleanup");
for (WrappedGoal wrappedGoal : this.availableGoals) {
@ -119,7 +119,7 @@ index eeba224bd575451ba6023df65ef9d9b97f7f1c71..a927c2790c8ab9ccaa7161b970e10b0b
wrappedGoal.stop();
}
}
@@ -97,11 +98,14 @@ public class GoalSelector {
@@ -95,11 +96,14 @@ public class GoalSelector {
profilerFiller.push("goalUpdate");
for (WrappedGoal wrappedGoalx : this.availableGoals) {
@ -139,7 +139,7 @@ index eeba224bd575451ba6023df65ef9d9b97f7f1c71..a927c2790c8ab9ccaa7161b970e10b0b
WrappedGoal wrappedGoal1 = this.lockedFlags.getOrDefault(flag, NO_GOAL);
wrappedGoal1.stop();
this.lockedFlags.put(flag, wrappedGoalx);
@@ -133,11 +137,11 @@ public class GoalSelector {
@@ -131,11 +135,11 @@ public class GoalSelector {
}
public void disableControlFlag(Goal.Flag flag) {

View File

@ -9,7 +9,7 @@ creating too large of a packet to sed.
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
index 272da41db7ce4619a8e459a2f0a2221e42f58a40..526c117e0d53ad527eb610c79cdc46ec16b18c0c 100644
index 83c4b454472714de6ebf99cd4e50867920d07509..9f6d7c5dc0e591488a8a3763d8a1f1b3671d5299 100644
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -32,6 +32,14 @@ public class ClientboundLevelChunkPacketData {

View File

@ -7,7 +7,7 @@ bypass the need to get a player chunk, then get the either,
then unwrap it...
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 006d8abe66b2d66740b984d8ff7f56a41b9929f7..52104bcd74107bb9a475109230ca85dd2eba5b06 100644
index b805b9964ca5bf6b3d13dae615cb49177d43ded3..17ec8224bf5c2eebc7d6bcbe25e275be4bdb0a45 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -224,6 +224,12 @@ public class ServerChunkCache extends ChunkSource {

File diff suppressed because one or more lines are too long

View File

@ -48,7 +48,7 @@ index db31989ebe3d7021cfd2311439e9a00f819b0841..1373977b339405ef59bb3ea03d195285
serverEntity.getLastSentYRot(),
entity.getType(),
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 1463c31ba980ab0eb2174e3e891d1423a505e9dc..886340232b58afd59caa6df29e211589a7781070 100644
index 61692c07dfb75ca0c19f603aafc96c0817861107..56a1d081a28e8b38384cfca732b103462693e322 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -1278,6 +1278,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@ -60,7 +60,7 @@ index 1463c31ba980ab0eb2174e3e891d1423a505e9dc..886340232b58afd59caa6df29e211589
} else if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index a1ae77b70f69852d9e4332bf1cb3409c33b21de0..b118e91f1e0b5a8b8c0b2a4a32faabc5a34a5954 100644
index 3d5a8163a7dd78a195b77c4aaebdee2dc3dee64b..e96d4dee14c05f2fa329bfb1588ec795d4e3d730 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -103,6 +103,13 @@ public class ServerEntity {
@ -90,12 +90,12 @@ index a1ae77b70f69852d9e4332bf1cb3409c33b21de0..b118e91f1e0b5a8b8c0b2a4a32faabc5
long l1 = this.positionCodec.encodeY(vec3);
long l2 = this.positionCodec.encodeZ(vec3);
boolean flag5 = l < -32768L || l > 32767L || l1 < -32768L || l1 > 32767L || l2 < -32768L || l2 > 32767L;
- if (flag5 || this.teleportDelay > 400 || this.wasRiding || this.wasOnGround != this.entity.onGround()) {
+ if (this.forceStateResync || flag5 || this.teleportDelay > 400 || this.wasRiding || this.wasOnGround != this.entity.onGround()) { // Paper - fix desync when a player is added to the tracker
this.wasOnGround = this.entity.onGround();
this.teleportDelay = 0;
packet = ClientboundEntityPositionSyncPacket.of(this.entity);
@@ -241,6 +248,7 @@ public class ServerEntity {
- if (this.entity.getRequiresPrecisePosition()
+ if (this.forceStateResync || this.entity.getRequiresPrecisePosition() // Paper - fix desync when a player is added to the tracker
|| flag5
|| this.teleportDelay > 400
|| this.wasRiding
@@ -245,6 +252,7 @@ public class ServerEntity {
}
this.entity.hasImpulse = false;

View File

@ -2326,10 +2326,10 @@ index 0000000000000000000000000000000000000000..298076a0db4e6ee6e4775ac43bf749d9
+ }
+}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee..32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e 100644
index f9c96bbdc54e68b9216b7f8662bfae03012d2866..34b7769663e235b93c6388ab0c92c00f0297e42f 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -210,6 +210,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -213,6 +213,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
public final java.util.UUID uuid;
public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent
@ -2337,7 +2337,7 @@ index 8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee..32db2b9e375c12cbf7abab69cc01e8ac
@Override
public @Nullable LevelChunk getChunkIfLoaded(int x, int z) {
@@ -2552,6 +2553,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -2591,6 +2592,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return this.chunkSource.getGenerator().getSeaLevel();
}
@ -2352,10 +2352,10 @@ index 8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee..32db2b9e375c12cbf7abab69cc01e8ac
@Override
public void onCreated(Entity entity) {
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index eb4d03cfdb34243901cfba832d35559d5be9e876..013ed7dbe2309f562f63e66203179a90566e8115 100644
index f286dd9996590e5d448ca809c34b6f640203e274..c41df4b1fff1f65532256e835dc30fadbb4f8c8b 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -2096,6 +2096,17 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
@@ -2093,6 +2093,17 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
return 0;
}

View File

@ -204,10 +204,10 @@ index 6d3e3ec045d5b15a435f7217369968b33e082724..b7a3758af337270737041f84d10eb437
int i = this.inventory.findSlotMatchingCraftingIngredient(item, item1);
if (i == -1) {
diff --git a/net/minecraft/world/entity/player/Inventory.java b/net/minecraft/world/entity/player/Inventory.java
index e25e0bd410f8822cb9a1118b39a786f44aabef7b..d9cb4f0ed0c4f63362c837aeef3c4194911455c9 100644
index 46408ccee787b45e7957c12bfe426cb391f6e173..a6bb436dc80daf6901dc027a6011ead4b3ed27e2 100644
--- a/net/minecraft/world/entity/player/Inventory.java
+++ b/net/minecraft/world/entity/player/Inventory.java
@@ -234,12 +234,12 @@ public class Inventory implements Container, Nameable {
@@ -251,12 +251,12 @@ public class Inventory implements Container, Nameable {
return !stack.isDamaged() && !stack.isEnchanted() && !stack.has(DataComponents.CUSTOM_NAME);
}

View File

@ -1,81 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Wed, 18 Nov 2020 20:52:25 -0800
Subject: [PATCH] Entity load/save limit per chunk
Adds a config option to limit the number of entities saved and loaded
to a chunk. The default values of -1 disable the limit. Although
defaults are only included for certain entites, this allows setting
limits for any entity type.
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
index 1c82dcd38f789707e15e8cbec72ef9cdc7efdf56..ba20e87d2105ce53cdaf4049de2388d05fcd1b56 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
@@ -104,7 +104,18 @@ public final class ChunkEntitySlices {
}
final ListTag entitiesTag = new ListTag();
+ final java.util.Map<net.minecraft.world.entity.EntityType<?>, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk
for (final Entity entity : PlatformHooks.get().modifySavedEntities(world, chunkPos.x, chunkPos.z, entities)) {
+ // Paper start - Entity load/save limit per chunk
+ final EntityType<?> entityType = entity.getType();
+ final int saveLimit = world.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1);
+ if (saveLimit > -1) {
+ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) {
+ continue;
+ }
+ savedEntityCounts.merge(entityType, 1, Integer::sum);
+ }
+ // Paper end - Entity load/save limit per chunk
CompoundTag compoundTag = new CompoundTag();
if (entity.save(compoundTag)) {
entitiesTag.add(compoundTag);
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index 4c57990c94721dd0973477669e1dadfab5f16404..8af02ed823da098a5592ef195c9fe8ed8f245b53 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -1430,9 +1430,20 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
}
public static Stream<Entity> loadEntitiesRecursive(List<? extends Tag> entityTags, Level level, EntitySpawnReason spawnReason) {
+ final java.util.Map<EntityType<?>, Integer> loadedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk
return entityTags.stream()
.flatMap(tag -> tag.asCompound().stream())
.mapMulti((compoundTag, consumer) -> loadEntityRecursive(compoundTag, level, spawnReason, entity -> {
+ // Paper start - Entity load/save limit per chunk
+ final EntityType<?> entityType = entity.getType();
+ final int saveLimit = level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1);
+ if (saveLimit > -1) {
+ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) {
+ return null;
+ }
+ loadedEntityCounts.merge(entityType, 1, Integer::sum);
+ }
+ // Paper end - Entity load/save limit per chunk
consumer.accept(entity);
return entity;
}));
diff --git a/net/minecraft/world/level/chunk/storage/EntityStorage.java b/net/minecraft/world/level/chunk/storage/EntityStorage.java
index bcc2a4081fac07c4579c3aabfe4353743f8cd876..f9fb1380be9cbe960127c208c65c19f770e50b6d 100644
--- a/net/minecraft/world/level/chunk/storage/EntityStorage.java
+++ b/net/minecraft/world/level/chunk/storage/EntityStorage.java
@@ -87,7 +87,18 @@ public class EntityStorage implements EntityPersistentStorage<Entity> {
}
} else {
ListTag listTag = new ListTag();
+ final java.util.Map<net.minecraft.world.entity.EntityType<?>, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk
entities.getEntities().forEach(entity -> {
+ // Paper start - Entity load/save limit per chunk
+ final EntityType<?> entityType = entity.getType();
+ final int saveLimit = this.level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1);
+ if (saveLimit > -1) {
+ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) {
+ return;
+ }
+ savedEntityCounts.merge(entityType, 1, Integer::sum);
+ }
+ // Paper end - Entity load/save limit per chunk
CompoundTag compoundTag1 = new CompoundTag();
if (entity.save(compoundTag1)) {
listTag.add(compoundTag1);

View File

@ -0,0 +1,80 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
Date: Wed, 18 Nov 2020 20:52:25 -0800
Subject: [PATCH] Entity load/save limit per chunk
Adds a config option to limit the number of entities saved and loaded
to a chunk. The default values of -1 disable the limit. Although
defaults are only included for certain entites, this allows setting
limits for any entity type.
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
index c380487a97f626163e1f13d87231d64ce2ea4b24..b2bcfb3557a0326fd7ec1059f95d6da4568dfd80 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/ChunkEntitySlices.java
@@ -116,8 +116,19 @@ public final class ChunkEntitySlices {
}
final ListTag entitiesTag = new ListTag();
+ final java.util.Map<net.minecraft.world.entity.EntityType<?>, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk
try (final ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(ChunkAccess.problemPath(chunkPos), LOGGER)) {
for (final Entity entity : PlatformHooks.get().modifySavedEntities(world, chunkPos.x, chunkPos.z, entities)) {
+ // Paper start - Entity load/save limit per chunk
+ final EntityType<?> entityType = entity.getType();
+ final int saveLimit = world.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1);
+ if (saveLimit > -1) {
+ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) {
+ continue;
+ }
+ savedEntityCounts.merge(entityType, 1, Integer::sum);
+ }
+ // Paper end - Entity load/save limit per chunk
final TagValueOutput savedEntity = TagValueOutput.createWithContext(
scopedCollector.forChild(entity.problemPath()), entity.registryAccess()
);
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index 98586dfc562cf6909df0f4bfa1c19e35b3172abe..f92adee1c187561d3790a5a5c8c81f5e1543ed97 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -1448,7 +1448,18 @@ public class EntityType<T extends Entity> implements FeatureElement, EntityTypeT
}
public static Stream<Entity> loadEntitiesRecursive(ValueInput.ValueInputList input, Level level, EntitySpawnReason spawnReason) {
+ final java.util.Map<EntityType<?>, Integer> loadedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk
return input.stream().mapMulti((valueInput, consumer) -> loadEntityRecursive(valueInput, level, spawnReason, entity -> {
+ // Paper start - Entity load/save limit per chunk
+ final EntityType<?> entityType = entity.getType();
+ final int saveLimit = level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1);
+ if (saveLimit > -1) {
+ if (loadedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) {
+ return null;
+ }
+ loadedEntityCounts.merge(entityType, 1, Integer::sum);
+ }
+ // Paper end - Entity load/save limit per chunk
consumer.accept(entity);
return entity;
}));
diff --git a/net/minecraft/world/level/chunk/storage/EntityStorage.java b/net/minecraft/world/level/chunk/storage/EntityStorage.java
index bf45cce4db77966d44d7a8d97673bb6631a6adaf..f1f8575a4b37114ced3cdb1d2ea33a36a2db44fd 100644
--- a/net/minecraft/world/level/chunk/storage/EntityStorage.java
+++ b/net/minecraft/world/level/chunk/storage/EntityStorage.java
@@ -95,7 +95,18 @@ public class EntityStorage implements EntityPersistentStorage<Entity> {
} else {
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(ChunkAccess.problemPath(pos), LOGGER)) {
ListTag listTag = new ListTag();
+ final java.util.Map<net.minecraft.world.entity.EntityType<?>, Integer> savedEntityCounts = new java.util.HashMap<>(); // Paper - Entity load/save limit per chunk
entities.getEntities().forEach(entity -> {
+ // Paper start - Entity load/save limit per chunk
+ final EntityType<?> entityType = entity.getType();
+ final int saveLimit = this.level.paperConfig().chunks.entityPerChunkSaveLimit.getOrDefault(entityType, -1);
+ if (saveLimit > -1) {
+ if (savedEntityCounts.getOrDefault(entityType, 0) >= saveLimit) {
+ return;
+ }
+ savedEntityCounts.merge(entityType, 1, Integer::sum);
+ }
+ // Paper end - Entity load/save limit per chunk
TagValueOutput tagValueOutput = TagValueOutput.createWithContext(scopedCollector.forChild(entity.problemPath()), entity.registryAccess());
if (entity.save(tagValueOutput)) {
CompoundTag compoundTag1 = tagValueOutput.buildResult();

View File

@ -778,10 +778,10 @@ index 1649119f45d970a9bf1683d676c47ecfc18ad047..cc544f3199cd6af29e50362923d06517
public static final RegionFileVersion VERSION_GZIP = register(
new RegionFileVersion(
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
index 03d1527073cf827fc3e191915fe5f7f064e36c3b..749096358fccbd5d1d13801092255c51096eb001 100644
index 2e6263d8b466e0f61bc72eb818044734b7d0ee6d..e04d3479383cd480cf35ed7ac3c82e7f6fb69e28 100644
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
@@ -122,6 +122,18 @@ public record SerializableChunkData(
@@ -124,6 +124,18 @@ public record SerializableChunkData(
}
}
// Paper end - guard against serializing mismatching coordinates
@ -799,8 +799,8 @@ index 03d1527073cf827fc3e191915fe5f7f064e36c3b..749096358fccbd5d1d13801092255c51
+ // Paper end - Attempt to recalculate regionfile header if it is corrupt
// Paper start - Do not let the server load chunks from newer versions
private static final int CURRENT_DATA_VERSION = net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion();
@@ -571,7 +583,7 @@ public record SerializableChunkData(
private static final int CURRENT_DATA_VERSION = net.minecraft.SharedConstants.getCurrentVersion().dataVersion().version();
@@ -573,7 +585,7 @@ public record SerializableChunkData(
compoundTag.putInt("xPos", this.chunkPos.x);
compoundTag.putInt("yPos", this.minSectionY);
compoundTag.putInt("zPos", this.chunkPos.z);

View File

@ -5,10 +5,10 @@ Subject: [PATCH] Incremental chunk and player saving
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 094ef7f54ad71795a2d8c2a8d03a32bef6ff2164..79bc1b7d9f640d2322814177eb3e921da8671e87 100644
index 80442494db670fec34df310390ea787fb963eef4..2dd512565ab901bf853f34b384155902b0fe8120 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -952,7 +952,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -954,7 +954,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
boolean var4;
try {
this.isSaving = true;
@ -17,7 +17,7 @@ index 094ef7f54ad71795a2d8c2a8d03a32bef6ff2164..79bc1b7d9f640d2322814177eb3e921d
var4 = this.saveAllChunks(suppressLog, flush, forced);
} finally {
this.isSaving = false;
@@ -1531,9 +1531,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1533,9 +1533,29 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
this.ticksUntilAutosave--;
@ -50,10 +50,10 @@ index 094ef7f54ad71795a2d8c2a8d03a32bef6ff2164..79bc1b7d9f640d2322814177eb3e921d
ProfilerFiller profilerFiller = Profiler.get();
this.runAllTasks(); // Paper - move runAllTasks() into full server tick (previously for timings)
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 32c8d4675de341d5edad7dbd9c0bf4bce5037733..bfbfbaa9660d21071c420b60b10be0a02a1bc87e 100644
index 34b7769663e235b93c6388ab0c92c00f0297e42f..dda8d38ef61672cc714d9e5a475f9b0412ed5ff9 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -1317,6 +1317,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -1339,6 +1339,28 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
return !(entity instanceof Player player && (this.server.isUnderSpawnProtection(this, pos, player) || !this.getWorldBorder().isWithinBounds(pos)));
}
@ -83,10 +83,10 @@ index 32c8d4675de341d5edad7dbd9c0bf4bce5037733..bfbfbaa9660d21071c420b60b10be0a0
// Paper start - add close param
this.save(progress, flush, skipSave, false);
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 5a60f2598560571e156612bf256c1c340d92a922..57e7d0a8b5f2a5bc65b0f290fb655625b1481f31 100644
index c0b74d408340101bc3aac4cb4b7232c5cc78b08a..b70929df38389d789dad46c0a6d94f6c08aa7eba 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -188,6 +188,7 @@ import org.slf4j.Logger;
@@ -195,6 +195,7 @@ import org.slf4j.Logger;
public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patches.chunk_system.player.ChunkSystemServerPlayer { // Paper - rewrite chunk system
private static final Logger LOGGER = LogUtils.getLogger();
@ -95,10 +95,10 @@ index 5a60f2598560571e156612bf256c1c340d92a922..57e7d0a8b5f2a5bc65b0f290fb655625
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
private static final int FLY_STAT_RECORDING_SPEED = 25;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index a7a07ebe6ceed99fa768b6834e350fe2f51a6950..9ca3c55a3b5b1a532b86b08eb92460df4cb54f2a 100644
index a3aa852b04e6deccccf995cfc57f95fa79860c04..b1524279c02cd3be82338a6bd0320cb125a134d5 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -486,6 +486,7 @@ public abstract class PlayerList {
@@ -489,6 +489,7 @@ public abstract class PlayerList {
protected void save(ServerPlayer player) {
if (!player.getBukkitEntity().isPersistent()) return; // CraftBukkit
@ -106,7 +106,7 @@ index a7a07ebe6ceed99fa768b6834e350fe2f51a6950..9ca3c55a3b5b1a532b86b08eb92460df
this.playerIo.save(player);
ServerStatsCounter serverStatsCounter = player.getStats(); // CraftBukkit
if (serverStatsCounter != null) {
@@ -1079,9 +1080,23 @@ public abstract class PlayerList {
@@ -1075,9 +1076,23 @@ public abstract class PlayerList {
}
public void saveAll() {

View File

@ -993,7 +993,7 @@ index c3bcb494afe464207e805f8c40b03c700059c64a..063fca9686a6a048ba279a49271f4144
private boolean isValid;
diff --git a/net/minecraft/world/level/chunk/storage/SectionStorage.java b/net/minecraft/world/level/chunk/storage/SectionStorage.java
index 778bd73a938c94ecb85ca0f8b686ff4e1baee040..79d4ce7712f16995b0de3be86477fb43ab3961d7 100644
index 964dfe6c84ca947ec7165aff821588ad8513d467..5e8f4d4bd98ef8a9f962b969c95a784764b8def5 100644
--- a/net/minecraft/world/level/chunk/storage/SectionStorage.java
+++ b/net/minecraft/world/level/chunk/storage/SectionStorage.java
@@ -131,11 +131,11 @@ public class SectionStorage<R, P> implements AutoCloseable, ca.spottedleaf.moonr

View File

@ -5,7 +5,7 @@ Subject: [PATCH] Optional per player mob spawns
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 886340232b58afd59caa6df29e211589a7781070..4f4bcc4bbfcc9b191d12d667b8fc1e644a9d5957 100644
index 86ba02916c4a1c1311eeca5b1fb10a46626ba9ab..b40b94c49dc0997654aca0a1a0dffe482cd14eac 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -243,11 +243,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@ -43,7 +43,7 @@ index 886340232b58afd59caa6df29e211589a7781070..4f4bcc4bbfcc9b191d12d667b8fc1e64
protected ChunkGenerator generator() {
return this.worldGenContext.generator();
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index 5d63bf024cbcbd2f627c64fee77553c9a512bd15..f863377a807b672f49f7140688f378eca2cf650b 100644
index 8e9988130d9b912e5b858cd7792bdcefdeb66ada..25d74f866546362a17505b5d4abf85382c0df20c 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -541,9 +541,18 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@ -78,10 +78,10 @@ index 5d63bf024cbcbd2f627c64fee77553c9a512bd15..f863377a807b672f49f7140688f378ec
profiler.popPush("tickSpawningChunks");
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 4b2801749328f250ce5735fbe7f6941a6bede01a..af04fcdba1e57b4eac678235b56ad3e1c70169b7 100644
index b70929df38389d789dad46c0a6d94f6c08aa7eba..e96bb37bb7a7340a7ee33046820652ecd4accc53 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -395,6 +395,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -406,6 +406,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
public boolean queueHealthUpdatePacket;
public @Nullable net.minecraft.network.protocol.game.ClientboundSetHealthPacket queuedHealthUpdatePacket;
// Paper end - cancellable death event

View File

@ -6,7 +6,7 @@ Subject: [PATCH] Improve cancelling PreCreatureSpawnEvent with per player mob
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 4f4bcc4bbfcc9b191d12d667b8fc1e644a9d5957..0d8aefe8c886eaa4c33cbab53b0ad1c016f0531f 100644
index b40b94c49dc0997654aca0a1a0dffe482cd14eac..b72000ce6bdcb97b787bfab79236f60bdb4aa2ee 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -262,8 +262,25 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
@ -37,7 +37,7 @@ index 4f4bcc4bbfcc9b191d12d667b8fc1e644a9d5957..0d8aefe8c886eaa4c33cbab53b0ad1c0
// Paper end - Optional per player mob spawns
diff --git a/net/minecraft/server/level/ServerChunkCache.java b/net/minecraft/server/level/ServerChunkCache.java
index f863377a807b672f49f7140688f378eca2cf650b..59e8a5e1b35c81883c9b1ca00c6e55d77584d8cc 100644
index 25d74f866546362a17505b5d4abf85382c0df20c..7d78d270b7a076f595301acd9b3c6275e804496e 100644
--- a/net/minecraft/server/level/ServerChunkCache.java
+++ b/net/minecraft/server/level/ServerChunkCache.java
@@ -546,7 +546,17 @@ public class ServerChunkCache extends ChunkSource implements ca.spottedleaf.moon
@ -60,10 +60,10 @@ index f863377a807b672f49f7140688f378eca2cf650b..59e8a5e1b35c81883c9b1ca00c6e55d7
spawnState = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, null, true);
} else {
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index af04fcdba1e57b4eac678235b56ad3e1c70169b7..3781d9cc174b7aecacb9b9855d52c7b1ff05835c 100644
index e96bb37bb7a7340a7ee33046820652ecd4accc53..53f038e1b5e7a13a08a0c925c8bd3f8a40868195 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -399,6 +399,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -410,6 +410,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
public static final int MOBCATEGORY_TOTAL_ENUMS = net.minecraft.world.entity.MobCategory.values().length;
public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS];
// Paper end - Optional per player mob spawns

View File

@ -48,10 +48,10 @@ index 0000000000000000000000000000000000000000..24a2090e068ad3c0d08705050944abdf
+ }
+}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 79bc1b7d9f640d2322814177eb3e921da8671e87..f1373fd5fdebb9f4600ba7f32a5df6188de3a0e9 100644
index 2dd512565ab901bf853f34b384155902b0fe8120..d6dcb6d146d89a8fb96e7c669e5deb802223abd6 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1706,6 +1706,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1708,6 +1708,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent
serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent
serverLevel.updateLagCompensationTick(); // Paper - lag compensation
@ -60,10 +60,10 @@ index 79bc1b7d9f640d2322814177eb3e921da8671e87..f1373fd5fdebb9f4600ba7f32a5df618
/* Drop global time updates
if (this.tickCount % 20 == 0) {
diff --git a/net/minecraft/world/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java
index 72cd623a1a3ce4b7a570a853456b067cd93736b1..ad7852a19ff73368ec9e7e63dcb7a064f78eefa0 100644
index fc91f7f5ca01f1afe6ceb21f12d1a6ec6f5b68f9..cf283389d9263ba29720bf296a778be9eaf308a7 100644
--- a/net/minecraft/world/item/ItemStack.java
+++ b/net/minecraft/world/item/ItemStack.java
@@ -831,10 +831,16 @@ public final class ItemStack implements DataComponentHolder {
@@ -811,10 +811,16 @@ public final class ItemStack implements DataComponentHolder {
}
public ItemStack copy() {
@ -83,10 +83,10 @@ index 72cd623a1a3ce4b7a570a853456b067cd93736b1..ad7852a19ff73368ec9e7e63dcb7a064
return itemStack;
}
diff --git a/net/minecraft/world/level/block/entity/BlockEntity.java b/net/minecraft/world/level/block/entity/BlockEntity.java
index 7783ff94e5183737d01c75c521b70b4fbd8c34a6..a1075c26d55cc01219acd94d0138f81aa9d34c48 100644
index 275646a9f99f3c46bc81a23143c1960f2a6300b1..5986825d6a381eeb445dd424dd127864aa703163 100644
--- a/net/minecraft/world/level/block/entity/BlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BlockEntity.java
@@ -33,6 +33,7 @@ import net.minecraft.world.level.block.state.BlockState;
@@ -35,6 +35,7 @@ import net.minecraft.world.level.storage.ValueOutput;
import org.slf4j.Logger;
public abstract class BlockEntity {
@ -94,7 +94,7 @@ index 7783ff94e5183737d01c75c521b70b4fbd8c34a6..a1075c26d55cc01219acd94d0138f81a
// CraftBukkit start - data containers
private static final org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry();
public final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer;
@@ -202,6 +203,7 @@ public abstract class BlockEntity {
@@ -227,6 +228,7 @@ public abstract class BlockEntity {
public void setChanged() {
if (this.level != null) {
@ -103,7 +103,7 @@ index 7783ff94e5183737d01c75c521b70b4fbd8c34a6..a1075c26d55cc01219acd94d0138f81a
}
}
diff --git a/net/minecraft/world/level/block/entity/HopperBlockEntity.java b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
index 9a03934dd4d96184f37b9ff5661eb7bd76150464..15d4f60942c0cc612c1468b4c0fda886867a67cb 100644
index 94d68fbb3d152b2fd43f989b728c5efabbf3c22c..800b7e78ae989868ed0b9e060c80dcd002759412 100644
--- a/net/minecraft/world/level/block/entity/HopperBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/HopperBlockEntity.java
@@ -143,18 +143,56 @@ public class HopperBlockEntity extends RandomizableContainerBlockEntity implemen
@ -669,7 +669,7 @@ index 9a03934dd4d96184f37b9ff5661eb7bd76150464..15d4f60942c0cc612c1468b4c0fda886
@Override
diff --git a/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
index 1c98d003907feb16de8f26377fceedf728afe7fb..eed5f8f912544b79c8ed54dcdc5eeacb6dcfaccd 100644
index d2cd30ed072a3d75c32b49a72920a9c26ce29922..dc59465d63e36bd50a48a8ea4197424556736552 100644
--- a/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
@@ -54,7 +54,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc

View File

@ -14,7 +14,7 @@ timestamp so that fs watchers can detect when RegionFiles are
modified.
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
index 1acea58838f057ab87efd103cbecb6f5aeaef393..98fbc5c8044bd945d64569f13412a6e7e49a4e7f 100644
index 09320f243a54f855b29d3833089b096975ca0075..709df35246fb328cda21679b53d44d9f96206cb3 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
@@ -1258,6 +1258,14 @@ public final class MoonriseRegionFileIO {

View File

@ -6,53 +6,43 @@ Subject: [PATCH] Optimise collision checking in player move packet handling
Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a195b8302 100644
index c9a0df5e5617e62703787942d067883ea537618b..aeb43902a09ef9c1b137964065780be3e87648f4 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -555,7 +555,7 @@ public class ServerGamePacketListenerImpl
return;
}
- boolean flag = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625));
+ final AABB oldBox = rootVehicle.getBoundingBox(); // Paper - copy from player movement packet
d3 = d - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
d4 = d1 - this.vehicleLastGoodY; // Paper - diff on change, used for checking large move vectors above
d5 = d2 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
@@ -565,6 +565,7 @@ public class ServerGamePacketListenerImpl
@@ -592,6 +592,7 @@ public class ServerGamePacketListenerImpl
}
rootVehicle.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
+ final boolean didCollide = toX != rootVehicle.getX() || toY != rootVehicle.getY() || toZ != rootVehicle.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be...
double verticalDelta = d4; // Paper - Decompile fix: lvt reassignment lost
double verticalDelta = d4;
d3 = d - rootVehicle.getX();
d4 = d1 - rootVehicle.getY();
@@ -576,14 +577,22 @@ public class ServerGamePacketListenerImpl
@@ -603,12 +604,21 @@ public class ServerGamePacketListenerImpl
d7 = d3 * d3 + d4 * d4 + d5 * d5;
boolean flag2 = false;
boolean flag1 = false;
if (d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
- flag2 = true;
+ flag2 = true; // Paper - diff on change, this should be moved wrongly
- flag1 = true;
+ flag1 = true; // Paper - diff on change, this should be moved wrongly
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7));
}
rootVehicle.absSnapTo(d, d1, d2, f, f1);
this.player.absSnapTo(d, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
- boolean flag3 = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625));
- if (flag && (flag2 || !flag3)) {
- if (flag1 && serverLevel.noCollision(rootVehicle, boundingBox)
- || this.isEntityCollidingWithAnythingNew(serverLevel, rootVehicle, boundingBox, d, d1, d2)) {
+ // Paper start - optimise out extra getCubes
+ boolean teleportBack = flag2; // violating this is always a fail
+ boolean teleportBack = flag1;
+ if (!teleportBack) {
+ // note: only call after setLocation, or else getBoundingBox is wrong
+ final AABB newBox = rootVehicle.getBoundingBox();
+ if (didCollide || !oldBox.equals(newBox)) {
+ teleportBack = this.hasNewCollision(serverLevel, rootVehicle, oldBox, newBox);
+ if (didCollide || !boundingBox.equals(newBox)) {
+ teleportBack = this.hasNewCollision(serverLevel, rootVehicle, boundingBox, newBox);
+ } // else: no collision at all detected, why do we care?
+ }
+ if (teleportBack) { // Paper end - optimise out extra getCubes
+ if (teleportBack) {
+ // Paper end - optimise out extra getCubes
rootVehicle.absSnapTo(x, y, z, f, f1);
this.player.absSnapTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
this.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle));
@@ -661,9 +670,32 @@ public class ServerGamePacketListenerImpl
rootVehicle.removeLatestMovementRecording();
@@ -687,9 +697,32 @@ public class ServerGamePacketListenerImpl
}
private boolean noBlocksAround(Entity entity) {
@ -88,7 +78,7 @@ index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a
}
@Override
@@ -1432,7 +1464,7 @@ public class ServerGamePacketListenerImpl
@@ -1465,7 +1498,7 @@ public class ServerGamePacketListenerImpl
}
}
@ -97,7 +87,7 @@ index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a
d3 = d - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above
d4 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above
d5 = d2 - this.lastGoodZ; // Paper - diff on change, used for checking large move vectors above
@@ -1471,6 +1503,7 @@ public class ServerGamePacketListenerImpl
@@ -1504,6 +1537,7 @@ public class ServerGamePacketListenerImpl
boolean flag1 = this.player.verticalCollisionBelow;
this.player.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move
@ -105,26 +95,26 @@ index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a
// Paper start - prevent position desync
if (this.awaitingPositionFromClient != null) {
return; // ... thanks Mojang for letting move calls teleport across dimensions.
@@ -1503,7 +1536,17 @@ public class ServerGamePacketListenerImpl
@@ -1536,7 +1570,17 @@ public class ServerGamePacketListenerImpl
}
// Paper start - Add fail move event
- boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && serverLevel.noCollision(this.player, boundingBox) || this.isPlayerCollidingWithAnythingNew(serverLevel, boundingBox, d, d1, d2));
- boolean allowMovement = this.player.noPhysics || this.player.isSleeping() || (!movedWrongly || !serverLevel.noCollision(this.player, boundingBox)) && !this.isEntityCollidingWithAnythingNew(serverLevel, this.player, boundingBox, d, d1, d2);
+ // Paper start - optimise out extra getCubes
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly;
+ boolean allowMovement = this.player.noPhysics || this.player.isSleeping() || !movedWrongly;
+ this.player.absSnapTo(d, d1, d2, f, f1); // prevent desync by tping to the set position, dropped for unknown reasons by mojang
+ if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) {
+ if (!this.player.noPhysics && !this.player.isSleeping() && allowMovement) {
+ final AABB newBox = this.player.getBoundingBox();
+ if (didCollide || !boundingBox.equals(newBox)) {
+ // note: only call after setLocation, or else getBoundingBox is wrong
+ teleportBack = this.hasNewCollision(serverLevel, this.player, boundingBox, newBox);
+ allowMovement = !this.hasNewCollision(serverLevel, this.player, boundingBox, newBox);
+ } // else: no collision at all detected, why do we care?
+ }
+ // Paper end - optimise out extra getCubes
if (teleportBack) {
if (!allowMovement) {
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
toX, toY, toZ, toYaw, toPitch, false);
@@ -1640,7 +1683,7 @@ public class ServerGamePacketListenerImpl
@@ -1672,7 +1716,7 @@ public class ServerGamePacketListenerImpl
private boolean updateAwaitingTeleport() {
if (this.awaitingPositionFromClient != null) {
@ -133,7 +123,7 @@ index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a
this.awaitingTeleportTime = this.tickCount;
this.teleport(
this.awaitingPositionFromClient.x,
@@ -1659,6 +1702,33 @@ public class ServerGamePacketListenerImpl
@@ -1691,6 +1735,33 @@ public class ServerGamePacketListenerImpl
}
}
@ -164,6 +154,6 @@ index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a
+ return false;
+ }
+ // Paper end - optimise out extra getCubes
private boolean isPlayerCollidingWithAnythingNew(LevelReader level, AABB box, double x, double y, double z) {
AABB aabb = this.player.getBoundingBox().move(x - this.player.getX(), y - this.player.getY(), z - this.player.getZ());
Iterable<VoxelShape> collisions = level.getCollisions(this.player, aabb.deflate(1.0E-5F));
private boolean isEntityCollidingWithAnythingNew(LevelReader levelReader, Entity entity, AABB aabb, double d, double d1, double d2) {
AABB aabb1 = entity.getBoundingBox().move(d - entity.getX(), d1 - entity.getY(), d2 - entity.getZ());
Iterable<VoxelShape> preMoveCollisions = levelReader.getPreMoveCollisions(entity, aabb1.deflate(1.0E-5F), aabb.getBottomCenter());

View File

@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Owen1212055 <23108066+Owen1212055@users.noreply.github.com>
Date: Sat, 7 Jun 2025 15:05:05 -0400
Subject: [PATCH] DataConverter Fixes
diff --git a/ca/spottedleaf/dataconverter/minecraft/versions/V4307.java b/ca/spottedleaf/dataconverter/minecraft/versions/V4307.java
index d2877c20f389d0131e1dd208b464f590671e5d82..27bdc70d861ca39487ad16cb3afb89d604b462c8 100644
--- a/ca/spottedleaf/dataconverter/minecraft/versions/V4307.java
+++ b/ca/spottedleaf/dataconverter/minecraft/versions/V4307.java
@@ -87,10 +87,10 @@ public final class V4307 {
@Override
public MapType convert(final MapType root, final long sourceVersion, final long toVersion) {
- final Set<String> hiddenComponents = new LinkedHashSet<>();
-
- unwrapBlockPredicates(root, "minecraft:can_break", hiddenComponents);
+ // Don't use a linked hash set, and ensure that it is added in the same (undefined) order as the vanilla datafixer
+ final Set<String> hiddenComponents = new java.util.HashSet<>();
unwrapBlockPredicates(root, "minecraft:can_place_on", hiddenComponents);
+ unwrapBlockPredicates(root, "minecraft:can_break", hiddenComponents);
updateComponent(root, "minecraft:trim", hiddenComponents);
updateComponent(root, "minecraft:unbreakable", hiddenComponents);

View File

@ -1,6 +1,6 @@
--- /dev/null
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
@@ -1,0 +_,241 @@
@@ -1,0 +_,250 @@
+package ca.spottedleaf.moonrise.paper;
+
+import ca.spottedleaf.moonrise.common.PlatformHooks;
@ -33,6 +33,8 @@
+
+public final class PaperHooks extends BaseChunkSystemHooks implements PlatformHooks {
+
+ private static final org.slf4j.Logger LOGGER = com.mojang.logging.LogUtils.getLogger();
+
+ @Override
+ public String getBrand() {
+ return "Paper";
@ -150,6 +152,11 @@
+ }
+
+ @Override
+ public long[] getCounterTypesUncached(final net.minecraft.server.level.TicketType type) {
+ return new long[0];
+ }
+
+ @Override
+ public boolean configFixMC224294() {
+ return true;
+ }
@ -234,7 +241,9 @@
+
+ @Override
+ public void postLoadProtoChunk(final ServerLevel world, final ProtoChunk chunk) {
+ net.minecraft.world.level.chunk.status.ChunkStatusTasks.postLoadProtoChunk(world, chunk.getEntities());
+ try (final net.minecraft.util.ProblemReporter.ScopedCollector scopedCollector = new net.minecraft.util.ProblemReporter.ScopedCollector(chunk.problemPath(), LOGGER)) {
+ net.minecraft.world.level.chunk.status.ChunkStatusTasks.postLoadProtoChunk(world, net.minecraft.world.level.storage.TagValueInput.create(scopedCollector, world.registryAccess(), chunk.getEntities()));
+ }
+ }
+
+ @Override

View File

@ -300,7 +300,7 @@
+
+ @Override
+ public int getViewDistance(final ServerPlayer player) {
+ final ServerLevel level = player.serverLevel();
+ final ServerLevel level = player.level();
+ if (level == null) {
+ return Bukkit.getViewDistance();
+ }
@ -309,7 +309,7 @@
+
+ @Override
+ public int getTickViewDistance(final ServerPlayer player) {
+ final ServerLevel level = player.serverLevel();
+ final ServerLevel level = player.level();
+ if (level == null) {
+ return Bukkit.getSimulationDistance();
+ }

View File

@ -10,7 +10,7 @@
private final RedirectModifier<S> modifier;
private final boolean forks;
private Command<S> command;
+ public CommandNode<net.minecraft.commands.CommandSourceStack> clientNode; // Paper - Brigadier API
+ public CommandNode<S> clientNode; // Paper - Brigadier API
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> unwrappedCached = null; // Paper - Brigadier Command API
+ public CommandNode<io.papermc.paper.command.brigadier.CommandSourceStack> wrappedCached = null; // Paper - Brigadier Command API
+ public io.papermc.paper.command.brigadier.APICommandMeta apiCommandMeta; // Paper - Brigadier Command API
@ -24,25 +24,6 @@
protected CommandNode(final Command<S> command, final Predicate<S> requirement, final CommandNode<S> redirect, final RedirectModifier<S> modifier, final boolean forks) {
this.command = command;
@@ -61,7 +_,17 @@
return modifier;
}
- public boolean canUse(final S source) {
+ // CraftBukkit start
+ public synchronized boolean canUse(final S source) {
+ if (source instanceof final net.minecraft.commands.CommandSourceStack css) {
+ try {
+ css.currentCommand.put(Thread.currentThread(), this); // Paper - Thread Safe Vanilla Command permission checking
+ return this.requirement.test(source);
+ } finally {
+ css.currentCommand.remove(Thread.currentThread()); // Paper - Thread Safe Vanilla Command permission checking
+ }
+ }
+ // CraftBukkit end
return requirement.test(source);
}
@@ -151,6 +_,12 @@
protected abstract String getSortedKey();

View File

@ -64,7 +64,7 @@
+
+ public static Set<Chunk> getSentChunks(final ServerPlayer player) {
+ final ObjectSet<Chunk> chunks = new ObjectOpenHashSet<>();
+ final World world = player.serverLevel().getWorld();
+ final World world = player.level().getWorld();
+ player.getChunkTrackingView().forEach(pos -> {
+ final org.bukkit.Chunk chunk = world.getChunkAt(pos.longKey);
+ chunks.add(chunk);

View File

@ -1,24 +1,23 @@
--- a/net/minecraft/commands/CommandSourceStack.java
+++ b/net/minecraft/commands/CommandSourceStack.java
@@ -45,7 +_,7 @@
@@ -47,7 +_,7 @@
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
-public class CommandSourceStack implements ExecutionCommandSource<CommandSourceStack>, SharedSuggestionProvider {
+public class CommandSourceStack implements ExecutionCommandSource<CommandSourceStack>, SharedSuggestionProvider, io.papermc.paper.command.brigadier.PaperCommandSourceStack { // Paper - Brigadier API
-public class CommandSourceStack implements ExecutionCommandSource<CommandSourceStack>, PermissionSource, SharedSuggestionProvider {
+public class CommandSourceStack implements ExecutionCommandSource<CommandSourceStack>, PermissionSource, SharedSuggestionProvider, io.papermc.paper.command.brigadier.PaperCommandSourceStack { // Paper - Brigadier API
public static final SimpleCommandExceptionType ERROR_NOT_PLAYER = new SimpleCommandExceptionType(Component.translatable("permissions.requires.player"));
public static final SimpleCommandExceptionType ERROR_NOT_ENTITY = new SimpleCommandExceptionType(Component.translatable("permissions.requires.entity"));
public final CommandSource source;
@@ -63,6 +_,8 @@
@@ -65,6 +_,7 @@
private final Vec2 rotation;
private final CommandSigningContext signingContext;
private final TaskChainer chatMessageChainer;
+ public java.util.Map<Thread, com.mojang.brigadier.tree.CommandNode> currentCommand = new java.util.concurrent.ConcurrentHashMap<>(); // CraftBukkit // Paper - Thread Safe Vanilla Command permission checking
+ public boolean bypassSelectorPermissions = false; // Paper - add bypass for selector permissions
public CommandSourceStack(
CommandSource source,
@@ -188,6 +_,30 @@
@@ -190,6 +_,30 @@
);
}
@ -49,19 +48,7 @@
public CommandSourceStack withRotation(Vec2 rotation) {
return this.rotation.equals(rotation)
? this
@@ -391,9 +_,44 @@
@Override
public boolean hasPermission(int level) {
+ // CraftBukkit start
+ // Paper start - Thread Safe Vanilla Command permission checking
+ com.mojang.brigadier.tree.CommandNode currentCommand = this.currentCommand.get(Thread.currentThread());
+ if (currentCommand != null) {
+ return this.hasPermission(level, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand));
+ // Paper end - Thread Safe Vanilla Command permission checking
+ }
+ // CraftBukkit end
+
@@ -396,6 +_,32 @@
return this.permissionLevel >= level;
}
@ -94,7 +81,7 @@
public Vec3 getPosition() {
return this.worldPosition;
}
@@ -498,20 +_,25 @@
@@ -500,20 +_,25 @@
Component component = Component.translatable("chat.type.admin", this.getDisplayName(), message).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC);
if (this.server.getGameRules().getBoolean(GameRules.RULE_SENDCOMMANDFEEDBACK)) {
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
@ -123,7 +110,7 @@
}
}
@@ -522,7 +_,7 @@
@@ -524,7 +_,7 @@
@Override
public Collection<String> getOnlinePlayerNames() {
@ -132,7 +119,7 @@
}
@Override
@@ -597,4 +_,16 @@
@@ -604,4 +_,16 @@
public boolean isSilent() {
return this.silent;
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -150,6 +_,11 @@
@@ -176,6 +_,11 @@
private final CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
public Commands(Commands.CommandSelection selection, CommandBuildContext context) {
@ -12,7 +12,7 @@
AdvancementCommands.register(this.dispatcher);
AttributeCommand.register(this.dispatcher, context);
ExecuteCommand.register(this.dispatcher, context);
@@ -251,6 +_,40 @@
@@ -280,6 +_,42 @@
PublishCommand.register(this.dispatcher);
}
@ -20,6 +20,8 @@
+ for (final CommandNode<CommandSourceStack> node : this.dispatcher.getRoot().getChildren()) {
+ if (node.getRequirement() == com.mojang.brigadier.builder.ArgumentBuilder.<CommandSourceStack>defaultRequirement()) {
+ node.requirement = stack -> stack.source == CommandSource.NULL || stack.getBukkitSender().hasPermission(org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(node));
+ } else if (node.getRequirement() instanceof net.minecraft.commands.PermissionSource.Check<CommandSourceStack> check) {
+ check.vanillaNode().set(node);
+ }
+ }
+ // Paper end - Vanilla command permission fixes
@ -53,7 +55,7 @@
this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer());
}
@@ -260,15 +_,58 @@
@@ -289,9 +_,41 @@
return new ParseResults<>(commandContextBuilder, parseResults.getReader(), parseResults.getExceptions());
}
@ -89,12 +91,16 @@
+ }
+
+ public void performPrefixedCommand(CommandSourceStack source, String command, String label) {
command = command.startsWith("/") ? command.substring(1) : command;
command = trimOptionalPrefix(command);
- this.performCommand(this.dispatcher.parse(command, source), command);
+ this.performCommand(this.dispatcher.parse(command, source), command, label);
+ // CraftBukkit end
}
public static String trimOptionalPrefix(String command) {
@@ -299,9 +_,20 @@
}
public void performCommand(ParseResults<CommandSourceStack> parseResults, String command) {
+ // CraftBukkit start
+ this.performCommand(parseResults, command, command);
@ -114,7 +120,7 @@
try {
if (contextChain != null) {
@@ -280,9 +_,10 @@
@@ -313,9 +_,10 @@
);
}
} catch (Exception var12) {
@ -127,7 +133,7 @@
StackTraceElement[] stackTrace = var12.getStackTrace();
for (int i = 0; i < Math.min(stackTrace.length, 3); i++) {
@@ -308,18 +_,22 @@
@@ -341,18 +_,22 @@
}
@Nullable
@ -153,7 +159,7 @@
if (min > 10) {
mutableComponent.append(CommonComponents.ELLIPSIS);
}
@@ -331,7 +_,17 @@
@@ -364,7 +_,17 @@
}
mutableComponent.append(Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC));
@ -172,13 +178,13 @@
}
return null;
@@ -359,26 +_,121 @@
@@ -392,17 +_,110 @@
}
public void sendCommands(ServerPlayer player) {
+ // Paper start - Send empty commands if tab completion is disabled
+ if (org.spigotmc.SpigotConfig.tabComplete < 0) {
+ player.connection.send(new ClientboundCommandsPacket(new RootCommandNode<>()));
+ player.connection.send(new ClientboundCommandsPacket(new RootCommandNode<>(), COMMAND_NODE_INSPECTOR));
+ return;
+ }
+ // Paper end - Send empty commands if tab completion is disabled
@ -203,11 +209,11 @@
+
+ private void sendAsync(ServerPlayer player, java.util.Collection<CommandNode<CommandSourceStack>> dispatcherRootChildren) {
+ // Paper end - Perf: Async command map building
Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> map = Maps.newHashMap();
RootCommandNode<SharedSuggestionProvider> rootCommandNode = new RootCommandNode<>();
Map<CommandNode<CommandSourceStack>, CommandNode<CommandSourceStack>> map = new HashMap<>();
RootCommandNode<CommandSourceStack> rootCommandNode = new RootCommandNode<>();
map.put(this.dispatcher.getRoot(), rootCommandNode);
- this.fillUsableCommands(this.dispatcher.getRoot(), rootCommandNode, player.createCommandSourceStack(), map);
+ this.fillUsableCommands(dispatcherRootChildren, rootCommandNode, player.createCommandSourceStack(), map); // Paper - Perf: Async command map building; pass copy of children
- fillUsableCommands(this.dispatcher.getRoot(), rootCommandNode, player.createCommandSourceStack(), map);
+ fillUsableCommands(dispatcherRootChildren, rootCommandNode, player.createCommandSourceStack(), map); // Paper - Perf: Async command map building; pass copy of children
+
+ java.util.Collection<String> bukkit = new java.util.LinkedHashSet<>();
+ for (CommandNode node : rootCommandNode.getChildren()) {
@ -216,11 +222,11 @@
+ // Paper start - Perf: Async command map building
+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent<CommandSourceStack>(player.getBukkitEntity(), (RootCommandNode) rootCommandNode, false).callEvent(); // Paper - Brigadier API
+ net.minecraft.server.MinecraftServer.getServer().execute(() -> {
+ runSync(player, bukkit, rootCommandNode);
+ runSync(player, bukkit, rootCommandNode);
+ });
+ }
+
+ private void runSync(ServerPlayer player, java.util.Collection<String> bukkit, RootCommandNode<SharedSuggestionProvider> rootCommandNode) {
+ private void runSync(ServerPlayer player, java.util.Collection<String> bukkit, RootCommandNode<CommandSourceStack> rootCommandNode) {
+ // Paper end - Perf: Async command map building
+ new com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent<CommandSourceStack>(player.getBukkitEntity(), (RootCommandNode) rootCommandNode, true).callEvent(); // Paper - Brigadier API
+ org.bukkit.event.player.PlayerCommandSendEvent event = new org.bukkit.event.player.PlayerCommandSendEvent(player.getBukkitEntity(), new java.util.LinkedHashSet<>(bukkit));
@ -233,28 +239,21 @@
+ }
+ }
+ // CraftBukkit end
+
player.connection.send(new ClientboundCommandsPacket(rootCommandNode));
player.connection.send(new ClientboundCommandsPacket(rootCommandNode, COMMAND_NODE_INSPECTOR));
}
private void fillUsableCommands(
- CommandNode<CommandSourceStack> rootCommandSource,
+ java.util.Collection<CommandNode<CommandSourceStack>> children, // Paper - Perf: Async command map building; pass copy of children
CommandNode<SharedSuggestionProvider> rootSuggestion,
CommandSourceStack source,
Map<CommandNode<CommandSourceStack>, CommandNode<SharedSuggestionProvider>> commandNodeToSuggestionNode
) {
- for (CommandNode<CommandSourceStack> commandNode : rootCommandSource.getChildren()) {
+ for (CommandNode<CommandSourceStack> commandNode : children) { // Paper - Perf: Async command map building; pass copy of children
- private static <S> void fillUsableCommands(CommandNode<S> root, CommandNode<S> current, S source, Map<CommandNode<S>, CommandNode<S>> output) {
- for (CommandNode<S> commandNode : root.getChildren()) {
+ private static <S> void fillUsableCommands(java.util.Collection<CommandNode<S>> children, CommandNode<S> current, S source, Map<CommandNode<S>, CommandNode<S>> output) { // Paper - Perf: Async command map building; pass copy of children
+ for (CommandNode<S> commandNode : children) { // Paper - Perf: Async command map building; pass copy of children
+ // Paper start - Brigadier API
+ if (commandNode.clientNode != null) {
+ commandNode = commandNode.clientNode;
+ }
+ // Paper end - Brigadier API
+ if (!org.spigotmc.SpigotConfig.sendNamespaced && commandNode.getName().contains(":")) continue; // Spigot
+ if (commandNode.wrappedCached != null && commandNode.wrappedCached.apiCommandMeta != null && commandNode.wrappedCached.apiCommandMeta.serverSideOnly()) continue; // Paper
if (commandNode.canUse(source)) {
ArgumentBuilder<SharedSuggestionProvider, ?> argumentBuilder = (ArgumentBuilder) commandNode.createBuilder();
ArgumentBuilder<S, ?> argumentBuilder = commandNode.createBuilder();
+ // Paper start
+ /*
+ Because of how commands can be yeeted right left and center due to bad bukkit practices
@ -271,41 +270,34 @@
+ - Do this :)
+ */
+ // Is there an invalid command redirect?
+ if (argumentBuilder.getRedirect() != null && commandNodeToSuggestionNode.get(argumentBuilder.getRedirect()) == null) {
+ if (argumentBuilder.getRedirect() != null && output.get(argumentBuilder.getRedirect()) == null) {
+ // Create the argument builder with the same values as the specified node, but with a different literal and populated children
+
+ final CommandNode<SharedSuggestionProvider> redirect = argumentBuilder.getRedirect();
+ final CommandNode<S> redirect = argumentBuilder.getRedirect();
+ // Diff copied from LiteralCommand#createBuilder
+ final com.mojang.brigadier.builder.LiteralArgumentBuilder<SharedSuggestionProvider> builder = com.mojang.brigadier.builder.LiteralArgumentBuilder.literal(commandNode.getName());
+ final com.mojang.brigadier.builder.LiteralArgumentBuilder<S> builder = com.mojang.brigadier.builder.LiteralArgumentBuilder.literal(commandNode.getName());
+ builder.requires(redirect.getRequirement());
+ // builder.forward(redirect.getRedirect(), redirect.getRedirectModifier(), redirect.isFork()); We don't want to migrate the forward, since it's invalid.
+ if (redirect.getCommand() != null) {
+ builder.executes(redirect.getCommand());
+ }
+ // Diff copied from LiteralCommand#createBuilder
+ for (final CommandNode<SharedSuggestionProvider> child : redirect.getChildren()) {
+ for (final CommandNode<S> child : redirect.getChildren()) {
+ builder.then(child);
+ }
+
+ argumentBuilder = builder;
+ }
+ // Paper end
argumentBuilder.requires(suggestions -> true);
- if (argumentBuilder.getCommand() != null) {
- argumentBuilder.executes(commandContext -> 0);
- }
+ // Paper - don't replace Command instance on suggestion node
+ // we want the exact command instance to be used for equality checks
+ // when assigning serialization ids to each command node
if (argumentBuilder instanceof RequiredArgumentBuilder requiredArgumentBuilder
&& requiredArgumentBuilder.getSuggestionsProvider() != null) {
@@ -393,7 +_,7 @@
commandNodeToSuggestionNode.put(commandNode, commandNode1);
rootSuggestion.addChild(commandNode1);
if (argumentBuilder.getRedirect() != null) {
argumentBuilder.redirect(output.get(argumentBuilder.getRedirect()));
}
@@ -411,7 +_,7 @@
output.put(commandNode, commandNode1);
current.addChild(commandNode1);
if (!commandNode.getChildren().isEmpty()) {
- this.fillUsableCommands(commandNode, commandNode1, source, commandNodeToSuggestionNode);
+ this.fillUsableCommands(commandNode.getChildren(), commandNode1, source, commandNodeToSuggestionNode); // Paper - Perf: Async command map building; pass copy of children
- fillUsableCommands(commandNode, commandNode1, source, output);
+ fillUsableCommands(commandNode.getChildren(), commandNode1, source, output); // Paper - Perf: Async command map building; pass copy of children
}
}
}

View File

@ -0,0 +1,24 @@
--- a/net/minecraft/commands/PermissionSource.java
+++ b/net/minecraft/commands/PermissionSource.java
@@ -9,9 +_,20 @@
return this.hasPermission(2);
}
- public record Check<T extends PermissionSource>(@Override int requiredLevel) implements PermissionCheck<T> {
+ public record Check<T extends PermissionSource>(@Override int requiredLevel, java.util.concurrent.atomic.AtomicReference<com.mojang.brigadier.tree.CommandNode<CommandSourceStack>> vanillaNode) implements PermissionCheck<T> { // Paper
+ // Paper start - Vanilla Command permission checking
+ public Check(int requiredLevel) {
+ this(requiredLevel, new java.util.concurrent.atomic.AtomicReference<>());
+ }
+ // Paper end - Vanilla Command permission checking
@Override
public boolean test(T source) {
+ // Paper start - Vanilla Command permission checking
+ com.mojang.brigadier.tree.CommandNode<CommandSourceStack> currentCommand = vanillaNode.get();
+ if (currentCommand != null && source instanceof CommandSourceStack commandSourceStack) {
+ return commandSourceStack.hasPermission(this.requiredLevel, org.bukkit.craftbukkit.command.VanillaCommandWrapper.getPermission(currentCommand));
+ }
+ // Paper end - Vanilla Command permission checking
return source.hasPermission(this.requiredLevel);
}
}

View File

@ -16,7 +16,7 @@
if (entitySelector.getMaxResults() > 1 && this.single) {
if (this.playersOnly) {
reader.setCursor(0);
@@ -129,7 +_,12 @@
@@ -129,7 +_,13 @@
if (context.getSource() instanceof SharedSuggestionProvider sharedSuggestionProvider) {
StringReader stringReader = new StringReader(builder.getInput());
stringReader.setCursor(builder.getStart());
@ -24,7 +24,8 @@
+ // Paper start - Fix EntityArgument permissions
+ final boolean permission = sharedSuggestionProvider instanceof CommandSourceStack stack
+ ? stack.bypassSelectorPermissions || stack.hasPermission(2, "minecraft.command.selector")
+ : sharedSuggestionProvider.hasPermission(2);
+ // Only CommandSourceStack implements SharedSuggestionProvider. If *somehow* anything else ends up here, try to query its permission level, otherwise yield false.
+ : (sharedSuggestionProvider instanceof final net.minecraft.commands.PermissionSource permissionSource && permissionSource.hasPermission(2));
+ EntitySelectorParser entitySelectorParser = new EntitySelectorParser(stringReader, permission);
+ // Paper end - Fix EntityArgument permissions

View File

@ -4,7 +4,7 @@
}
private void checkPermissions(CommandSourceStack source) throws CommandSyntaxException {
- if (this.usesSelector && !source.hasPermission(2)) {
- if (this.usesSelector && !source.allowsSelectors()) {
+ if (!source.bypassSelectorPermissions && (this.usesSelector && !source.hasPermission(2, "minecraft.command.selector"))) { // CraftBukkit // Paper - add bypass for selector perms
throw EntityArgument.ERROR_SELECTORS_NOT_ALLOWED.create();
}

View File

@ -9,7 +9,7 @@
+ return stack.bypassSelectorPermissions || stack.hasPermission(2, "minecraft.command.selector");
+ }
+ // Paper end - Fix EntityArgument permissions
return suggestionProvider instanceof SharedSuggestionProvider sharedSuggestionProvider && sharedSuggestionProvider.hasPermission(2);
return suggestionProvider instanceof PermissionSource permissionSource && permissionSource.allowsSelectors();
}
@@ -198,8 +_,10 @@

View File

@ -0,0 +1,40 @@
--- a/net/minecraft/core/HolderLookup.java
+++ b/net/minecraft/core/HolderLookup.java
@@ -68,6 +_,9 @@
}
public interface RegistryLookup<T> extends HolderLookup<T>, HolderOwner<T> {
+
+ Optional<T> getValueForCopying(ResourceKey<T> resourceKey); // Paper - add method to get the value for pre-filling builders in the reg mod API
+
ResourceKey<? extends Registry<? extends T>> key();
Lifecycle registryLifecycle();
@@ -80,6 +_,13 @@
default HolderLookup.RegistryLookup<T> filterElements(final Predicate<T> predicate) {
return new HolderLookup.RegistryLookup.Delegate<T>() {
+ // Paper start - add getValueForCopying
+ @Override
+ public Optional<T> getValueForCopying(final ResourceKey<T> resourceKey) {
+ return this.parent().getValueForCopying(resourceKey).filter(predicate);
+ }
+ // Paper end - add getValueForCopying
+
@Override
public HolderLookup.RegistryLookup<T> parent() {
return RegistryLookup.this;
@@ -99,6 +_,13 @@
public interface Delegate<T> extends HolderLookup.RegistryLookup<T> {
HolderLookup.RegistryLookup<T> parent();
+
+ // Paper start - add getValueForCopying
+ @Override
+ default Optional<T> getValueForCopying(ResourceKey<T> resourceKey) {
+ return this.parent().getValueForCopying(resourceKey);
+ }
+ // Paper end - add getValueForCopying
@Override
default ResourceKey<? extends Registry<? extends T>> key() {

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/core/MappedRegistry.java
+++ b/net/minecraft/core/MappedRegistry.java
@@ -32,17 +_,18 @@
@@ -32,17 +_,25 @@
public class MappedRegistry<T> implements WritableRegistry<T> {
private final ResourceKey<? extends Registry<T>> key;
private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
@ -20,7 +20,14 @@
private boolean frozen;
@Nullable
private Map<T, Holder.Reference<T>> unregisteredIntrusiveHolders;
+ public final Map<ResourceLocation, T> temporaryUnfrozenMap = new HashMap<>(); // Paper - support pre-filling in registry mod API
+ // Paper start - support pre-filling in registry mod API
+ private final Map<ResourceLocation, T> temporaryUnfrozenMap = new HashMap<>();
+
+ @Override
+ public Optional<T> getValueForCopying(final ResourceKey<T> resourceKey) {
+ return this.frozen ? this.getOptional(resourceKey) : Optional.ofNullable(this.temporaryUnfrozenMap.get(resourceKey.location()));
+ }
+ // Paper end - support pre-filling in registry mod API
@Override
public Stream<HolderSet.Named<T>> listTags() {

View File

@ -0,0 +1,30 @@
--- a/net/minecraft/core/RegistrySetBuilder.java
+++ b/net/minecraft/core/RegistrySetBuilder.java
@@ -41,6 +_,13 @@
final Map<ResourceKey<T>, Holder.Reference<T>> elements
) {
return new RegistrySetBuilder.EmptyTagRegistryLookup<T>(owner) {
+ // Paper start - add getValueForCopying method
+ @Override
+ public Optional<T> getValueForCopying(final ResourceKey<T> resourceKey) {
+ return this.get(resourceKey).map(Holder.Reference::value);
+ }
+ // Paper end - add getValueForCopying method
+
@Override
public ResourceKey<? extends Registry<? extends T>> key() {
return registryKey;
@@ -121,6 +_,13 @@
public <T> Optional<RegistryOps.RegistryInfo<T>> lookup(ResourceKey<? extends Registry<? extends T>> registryKey) {
return getEntry(registryKey).map(Entry::opsInfo);
}
+
+ // Paper start - add method to get the value for pre-filling builders in the reg mod API
+ @Override
+ public HolderLookup.Provider lookupForValueCopyViaBuilders() {
+ throw new UnsupportedOperationException("Not implemented");
+ }
+ // Paper end - add method to get the value for pre-filling builders in the reg mod API
});
}
};

View File

@ -27,23 +27,27 @@
+ // CraftBukkit end
if (!serverLevel.isClientSide()) {
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
- this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearLivingEntity(serverLevel, blockPos, item));
+ this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearLivingEntity(serverLevel, blockPos, item, bukkitBlock, craftItem)); // CraftBukkit
- this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearEntity(serverLevel, blockPos, item));
+ this.setSuccess(tryShearBeehive(serverLevel, blockPos) || tryShearEntity(serverLevel, blockPos, item, bukkitBlock, craftItem)); // CraftBukkit
if (this.isSuccess()) {
item.hurtAndBreak(1, serverLevel, null, item1 -> {});
}
@@ -50,10 +_,18 @@
@@ -50,14 +_,22 @@
return false;
}
- private static boolean tryShearLivingEntity(ServerLevel level, BlockPos pos, ItemStack stack) {
+ private static boolean tryShearLivingEntity(ServerLevel level, BlockPos pos, ItemStack stack, org.bukkit.block.Block bukkitBlock, org.bukkit.craftbukkit.inventory.CraftItemStack craftItem) { // CraftBukkit - add args
for (LivingEntity livingEntity : level.getEntitiesOfClass(LivingEntity.class, new AABB(pos), EntitySelector.NO_SPECTATORS)) {
if (livingEntity instanceof Shearable shearable && shearable.readyForShearing()) {
- private static boolean tryShearEntity(ServerLevel level, BlockPos pos, ItemStack stack) {
+ private static boolean tryShearEntity(ServerLevel level, BlockPos pos, ItemStack stack, org.bukkit.block.Block bukkitBlock, org.bukkit.craftbukkit.inventory.CraftItemStack craftItem) { // CraftBukkit - add args
for (Entity entity : level.getEntitiesOfClass(Entity.class, new AABB(pos), EntitySelector.NO_SPECTATORS)) {
if (entity.shearOffAllLeashConnections(null)) {
return true;
}
if (entity instanceof Shearable shearable && shearable.readyForShearing()) {
- shearable.shear(level, SoundSource.BLOCKS, stack);
+ // CraftBukkit start
+ // Paper start - Add drops to shear events
+ org.bukkit.event.block.BlockShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockShearEntityEvent(livingEntity, bukkitBlock, craftItem, shearable.generateDefaultDrops(level, stack));
+ org.bukkit.event.block.BlockShearEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockShearEntityEvent(entity, bukkitBlock, craftItem, shearable.generateDefaultDrops(level, stack));
+ if (event.isCancelled()) {
+ // Paper end - Add drops to shear events
+ continue;

View File

@ -1,32 +1,26 @@
--- a/net/minecraft/core/registries/BuiltInRegistries.java
+++ b/net/minecraft/core/registries/BuiltInRegistries.java
@@ -311,6 +_,17 @@
);
@@ -325,6 +_,11 @@
public static final Registry<MapCodec<? extends DialogBody>> DIALOG_BODY_TYPE = registerSimple(Registries.DIALOG_BODY_TYPE, DialogBodyTypes::bootstrap);
public static final Registry<Consumer<GameTestHelper>> TEST_FUNCTION = registerSimple(Registries.TEST_FUNCTION, BuiltinTestFunctions::bootstrap);
public static final Registry<? extends Registry<?>> REGISTRY = WRITABLE_REGISTRY;
+ // Paper start - add built-in registry conversions
+ public static final io.papermc.paper.registry.data.util.Conversions BUILT_IN_CONVERSIONS = new io.papermc.paper.registry.data.util.Conversions(new net.minecraft.resources.RegistryOps.RegistryInfoLookup() {
+ @Override
+ public <T> java.util.Optional<net.minecraft.resources.RegistryOps.RegistryInfo<T>> lookup(final ResourceKey<? extends Registry<? extends T>> registryRef) {
+ final Registry<T> registry = net.minecraft.server.RegistryLayer.STATIC_ACCESS.lookupOrThrow(registryRef);
+ return java.util.Optional.of(
+ new net.minecraft.resources.RegistryOps.RegistryInfo<>(registry, registry, Lifecycle.experimental())
+ );
+ }
+ });
+ public static final io.papermc.paper.registry.data.util.Conversions STATIC_ACCESS_CONVERSIONS = new io.papermc.paper.registry.data.util.Conversions(
+ new net.minecraft.resources.RegistryOps.HolderLookupAdapter(net.minecraft.server.RegistryLayer.STATIC_ACCESS)
+ );
+ // Paper end - add built-in registry conversions
private static <T> Registry<T> registerSimple(ResourceKey<? extends Registry<T>> key, BuiltInRegistries.RegistryBootstrap<T> bootstrap) {
return internalRegister(key, new MappedRegistry<>(key, Lifecycle.stable(), false), bootstrap);
@@ -336,6 +_,7 @@
@@ -350,6 +_,7 @@
ResourceKey<? extends Registry<T>> key, R registry, BuiltInRegistries.RegistryBootstrap<T> bootstrap
) {
Bootstrap.checkBootstrapCalled(() -> "registry " + key.location());
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(registry.key(), registry); // Paper - initialize API registry
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(registry); // Paper - initialize API registry
ResourceLocation resourceLocation = key.location();
LOADERS.put(resourceLocation, () -> bootstrap.run(registry));
WRITABLE_REGISTRY.register((ResourceKey)key, registry, RegistrationInfo.BUILT_IN);
@@ -343,16 +_,34 @@
@@ -357,16 +_,34 @@
}
public static void bootStrap() {
@ -61,11 +55,11 @@
});
}
@@ -361,6 +_,7 @@
@@ -375,6 +_,7 @@
for (Registry<?> registry : REGISTRY) {
bindBootstrappedTagsToEmpty(registry);
+ io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.runFreezeListeners(registry.key(), BUILT_IN_CONVERSIONS); // Paper
+ io.papermc.paper.registry.PaperRegistryListenerManager.INSTANCE.runFreezeListeners(registry.key(), STATIC_ACCESS_CONVERSIONS); // Paper
registry.freeze();
}
}

View File

@ -8,4 +8,4 @@
+ LevelStorageSource.LevelStorageAccess levelStorageAccess = LevelStorageSource.createDefault(Paths.get(string)).createAccess("gametestworld", net.minecraft.world.level.dimension.LevelStem.OVERWORLD); // Paper
PackRepository packRepository = ServerPacksSource.createPackRepository(levelStorageAccess);
MinecraftServer.spin(
thread -> GameTestServer.create(thread, levelStorageAccess, packRepository, optionalFromOption(optionSet, tests), optionSet.has(verify))
thread -> {

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/gametest/framework/StructureUtils.java
+++ b/net/minecraft/gametest/framework/StructureUtils.java
@@ -86,7 +_,7 @@
@@ -87,7 +_,7 @@
level.clearBlockEvents(boundingBox1);
AABB aabb = AABB.of(boundingBox1);
List<Entity> entitiesOfClass = level.getEntitiesOfClass(Entity.class, aabb, entity -> !(entity instanceof Player));

View File

@ -23,7 +23,7 @@
@Override
public CompoundTag copy() {
- HashMap<String, Tag> map = new HashMap<>();
- this.tags.forEach((string, tag) -> map.put(string, tag.copy()));
- this.tags.forEach((key, value) -> map.put(key, value.copy()));
- return new CompoundTag(map);
+ // Paper start - Reduce memory footprint of CompoundTag
+ it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<String, Tag> ret = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(this.tags.size(), 0.8f);

View File

@ -192,7 +192,7 @@
} catch (RejectedExecutionException var6) {
this.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown"));
} catch (ClassCastException var7) {
@@ -385,10 +_,30 @@
@@ -373,10 +_,30 @@
}
}
@ -223,7 +223,7 @@
}
if (!this.isConnected() && !this.disconnectionHandled) {
@@ -396,7 +_,7 @@
@@ -384,7 +_,7 @@
}
if (this.channel != null) {
@ -232,7 +232,7 @@
}
if (this.tickCount++ % 20 == 0) {
@@ -432,12 +_,13 @@
@@ -420,12 +_,13 @@
}
public void disconnect(DisconnectionDetails disconnectionDetails) {
@ -247,7 +247,7 @@
this.disconnectionDetails = disconnectionDetails;
}
}
@@ -584,6 +_,13 @@
@@ -572,6 +_,13 @@
}
}
@ -261,7 +261,7 @@
public void setupCompression(int threshold, boolean validateDecompressed) {
if (threshold >= 0) {
if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder compressionDecoder) {
@@ -597,6 +_,7 @@
@@ -585,6 +_,7 @@
} else {
this.channel.pipeline().addAfter("prepender", "compress", new CompressionEncoder(threshold));
}
@ -269,7 +269,7 @@
} else {
if (this.channel.pipeline().get("decompress") instanceof CompressionDecoder) {
this.channel.pipeline().remove("decompress");
@@ -605,6 +_,7 @@
@@ -593,6 +_,7 @@
if (this.channel.pipeline().get("compress") instanceof CompressionEncoder) {
this.channel.pipeline().remove("compress");
}
@ -277,7 +277,7 @@
}
}
@@ -622,6 +_,26 @@
@@ -610,6 +_,26 @@
);
packetListener1.onDisconnect(disconnectionDetails);
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/network/FriendlyByteBuf.java
+++ b/net/minecraft/network/FriendlyByteBuf.java
@@ -70,14 +_,20 @@
@@ -71,14 +_,20 @@
public class FriendlyByteBuf extends ByteBuf {
public static final int DEFAULT_NBT_QUOTA = 2097152;
private final ByteBuf source;
@ -21,7 +21,7 @@
this.source = source;
}
@@ -106,8 +_,13 @@
@@ -107,8 +_,13 @@
}
public <T> void writeJsonWithCodec(Codec<T> codec, T value) {
@ -36,7 +36,7 @@
}
public static <T> IntFunction<T> limitValue(IntFunction<T> function, int limit) {
@@ -539,7 +_,7 @@
@@ -556,7 +_,7 @@
try {
NbtIo.writeAnyTag(nbt, new ByteBufOutputStream(buffer));

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/network/chat/Component.java
+++ b/net/minecraft/network/chat/Component.java
@@ -37,7 +_,19 @@
@@ -23,7 +_,19 @@
import net.minecraft.util.FormattedCharSequence;
import net.minecraft.world.level.ChunkPos;

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/network/codec/ByteBufCodecs.java
+++ b/net/minecraft/network/codec/ByteBufCodecs.java
@@ -389,6 +_,48 @@
@@ -435,6 +_,48 @@
};
}

View File

@ -9,7 +9,7 @@
throw new RuntimeException("Chunk Packet trying to allocate too much memory on read.");
} else {
this.buffer = new byte[varInt];
@@ -151,6 +_,7 @@
@@ -155,6 +_,7 @@
CompoundTag updateTag = blockEntity.getUpdateTag(blockEntity.getLevel().registryAccess());
BlockPos blockPos = blockEntity.getBlockPos();
int i = SectionPos.sectionRelative(blockPos.getX()) << 4 | SectionPos.sectionRelative(blockPos.getZ());

View File

@ -1,21 +1,30 @@
--- a/net/minecraft/network/protocol/login/ClientboundLoginDisconnectPacket.java
+++ b/net/minecraft/network/protocol/login/ClientboundLoginDisconnectPacket.java
@@ -18,11 +_,16 @@
}
@@ -14,8 +_,25 @@
private ClientboundLoginDisconnectPacket(FriendlyByteBuf buffer) {
- this.reason = Component.Serializer.fromJsonLenient(buffer.readUtf(262144), RegistryAccess.EMPTY);
+ this.reason = Component.Serializer.fromJsonLenient(buffer.readUtf(FriendlyByteBuf.MAX_COMPONENT_STRING_LENGTH), RegistryAccess.EMPTY); // Paper - diff on change
}
private void write(FriendlyByteBuf buffer) {
- buffer.writeUtf(Component.Serializer.toJson(this.reason, RegistryAccess.EMPTY));
+ // Paper start - Adventure
+ // buffer.writeUtf(Component.Serializer.toJson(this.reason, RegistryAccess.EMPTY));
+ // In the login phase, buffer.adventure$locale field is most likely null, but plugins may use internals to set it via the channel attribute
+ java.util.Locale bufLocale = buffer.adventure$locale;
+ buffer.writeJsonWithCodec(net.minecraft.network.chat.ComponentSerialization.localizedCodec(bufLocale == null ? java.util.Locale.US : bufLocale), this.reason, FriendlyByteBuf.MAX_COMPONENT_STRING_LENGTH);
+ // Paper end - Adventure
}
@Override
public record ClientboundLoginDisconnectPacket(Component reason) implements Packet<ClientLoginPacketListener> {
private static final RegistryOps<JsonElement> OPS = RegistryAccess.EMPTY.createSerializationContext(JsonOps.INSTANCE);
- public static final StreamCodec<ByteBuf, ClientboundLoginDisconnectPacket> STREAM_CODEC = StreamCodec.composite(
- ByteBufCodecs.lenientJson(262144).apply(ByteBufCodecs.fromCodec(OPS, ComponentSerialization.CODEC)),
+ // Paper start - localized codec
+ // In the login phase, buffer.adventure$locale field is most likely null, but plugins may use internals to set it via the channel attribute
+ public static final StreamCodec<net.minecraft.network.FriendlyByteBuf, ClientboundLoginDisconnectPacket> STREAM_CODEC = StreamCodec.composite(
+ new StreamCodec<>() {
+
+ private static final net.minecraft.network.codec.StreamCodec<ByteBuf, JsonElement> LENIENT_JSON = ByteBufCodecs.lenientJson(net.minecraft.network.FriendlyByteBuf.MAX_COMPONENT_STRING_LENGTH);
+ @Override
+ public Component decode(final net.minecraft.network.FriendlyByteBuf buffer) {
+ java.util.Locale bufLocale = buffer.adventure$locale;
+ return LENIENT_JSON.apply(ByteBufCodecs.fromCodec(OPS, ComponentSerialization.localizedCodec(bufLocale == null ? java.util.Locale.US : bufLocale))).decode(buffer);
+ }
+
+ @Override
+ public void encode(final net.minecraft.network.FriendlyByteBuf buffer, final Component value) {
+ java.util.Locale bufLocale = buffer.adventure$locale;
+ LENIENT_JSON.apply(ByteBufCodecs.fromCodec(OPS, ComponentSerialization.localizedCodec(bufLocale == null ? java.util.Locale.US : bufLocale))).encode(buffer, value);
+ }
+ },
+ // Paper end - localized codec
ClientboundLoginDisconnectPacket::reason,
ClientboundLoginDisconnectPacket::new
);

View File

@ -1,6 +1,28 @@
--- a/net/minecraft/resources/RegistryDataLoader.java
+++ b/net/minecraft/resources/RegistryDataLoader.java
@@ -271,13 +_,14 @@
@@ -206,11 +_,21 @@
final Map<ResourceKey<? extends Registry<?>>, RegistryOps.RegistryInfo<?>> map = new HashMap<>();
registryLookups.forEach(registryLookup -> map.put(registryLookup.key(), createInfoForContextRegistry((HolderLookup.RegistryLookup<?>)registryLookup)));
loaders.forEach(loader -> map.put(loader.registry.key(), createInfoForNewRegistry(loader.registry)));
+ // this creates a HolderLookup.Provider to be used exclusively to obtain real instances of values to pre-populate builders
+ // for the Registry Modification API. This concatenates the context registry lookups and the empty registries about to be filled.
+ final HolderLookup.Provider providerForBuilders = HolderLookup.Provider.create(java.util.stream.Stream.concat(registryLookups.stream(), loaders.stream().map(Loader::registry))); // Paper - add method to get the value for pre-filling builders in the reg mod API
return new RegistryOps.RegistryInfoLookup() {
@Override
public <T> Optional<RegistryOps.RegistryInfo<T>> lookup(ResourceKey<? extends Registry<? extends T>> registryKey) {
return Optional.ofNullable((RegistryOps.RegistryInfo<T>)map.get(registryKey));
}
+
+ // Paper start - add method to get the value for pre-filling builders in the reg mod API
+ @Override
+ public HolderLookup.Provider lookupForValueCopyViaBuilders() {
+ return providerForBuilders;
+ }
+ // Paper end - add method to get the value for pre-filling builders in the reg mod API
};
}
@@ -274,13 +_,14 @@
RegistryOps<JsonElement> ops,
ResourceKey<E> resourceKey,
Resource resource,
@ -9,7 +31,7 @@
+ io.papermc.paper.registry.data.util.Conversions conversions // Paper - pass conversions
) throws IOException {
try (Reader reader = resource.openAsReader()) {
JsonElement jsonElement = JsonParser.parseReader(reader);
JsonElement jsonElement = StrictJsonParser.parse(reader);
DataResult<E> dataResult = codec.parse(ops, jsonElement);
E orThrow = dataResult.getOrThrow();
- registry.register(resourceKey, orThrow, registrationInfo);
@ -17,7 +39,7 @@
}
}
@@ -291,6 +_,7 @@
@@ -294,6 +_,7 @@
FileToIdConverter fileToIdConverter = FileToIdConverter.registry(registry.key());
RegistryOps<JsonElement> registryOps = RegistryOps.create(JsonOps.INSTANCE, registryInfoLookup);
@ -25,7 +47,7 @@
for (Entry<ResourceLocation, Resource> entry : fileToIdConverter.listMatchingResources(resourceManager).entrySet()) {
ResourceLocation resourceLocation = entry.getKey();
ResourceKey<E> resourceKey = ResourceKey.create(registry.key(), fileToIdConverter.fileToId(resourceLocation));
@@ -298,7 +_,7 @@
@@ -301,7 +_,7 @@
RegistrationInfo registrationInfo = REGISTRATION_INFO_CACHE.apply(resource.knownPackInfo());
try {
@ -34,7 +56,7 @@
} catch (Exception var14) {
loadingErrors.put(
resourceKey,
@@ -307,7 +_,9 @@
@@ -310,7 +_,9 @@
}
}
@ -45,7 +67,7 @@
}
static <E> void loadContentsFromNetwork(
@@ -324,6 +_,7 @@
@@ -327,6 +_,7 @@
RegistryOps<JsonElement> registryOps1 = RegistryOps.create(JsonOps.INSTANCE, registryInfoLookup);
FileToIdConverter fileToIdConverter = FileToIdConverter.registry(registry.key());
@ -53,7 +75,7 @@
for (RegistrySynchronization.PackedRegistryEntry packedRegistryEntry : networkedRegistryData.elements) {
ResourceKey<E> resourceKey = ResourceKey.create(registry.key(), packedRegistryEntry.id());
Optional<Tag> optional = packedRegistryEntry.data();
@@ -342,7 +_,7 @@
@@ -345,7 +_,7 @@
try {
Resource resourceOrThrow = resourceProvider.getResourceOrThrow(resourceLocation);
@ -62,11 +84,11 @@
} catch (Exception var17) {
loadingErrors.put(resourceKey, new IllegalStateException("Failed to parse local data", var17));
}
@@ -384,6 +_,7 @@
@@ -387,6 +_,7 @@
RegistryDataLoader.Loader<T> create(Lifecycle registryLifecycle, Map<ResourceKey<?>, Exception> loadingErrors) {
WritableRegistry<T> writableRegistry = new MappedRegistry<>(this.key, registryLifecycle);
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(this.key, writableRegistry); // Paper - initialize API registry
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerRegistry(writableRegistry); // Paper - initialize API registry
return new RegistryDataLoader.Loader<>(this, writableRegistry, loadingErrors);
}

View File

@ -0,0 +1,24 @@
--- a/net/minecraft/resources/RegistryOps.java
+++ b/net/minecraft/resources/RegistryOps.java
@@ -117,6 +_,13 @@
public int hashCode() {
return this.lookupProvider.hashCode();
}
+
+ // Paper start - add method to get the value for pre-filling builders in the reg mod API
+ @Override
+ public HolderLookup.Provider lookupForValueCopyViaBuilders() {
+ return this.lookupProvider;
+ }
+ // Paper end - add method to get the value for pre-filling builders in the reg mod API
}
public record RegistryInfo<T>(HolderOwner<T> owner, HolderGetter<T> getter, Lifecycle elementsLifecycle) {
@@ -127,5 +_,7 @@
public interface RegistryInfoLookup {
<T> Optional<RegistryOps.RegistryInfo<T>> lookup(ResourceKey<? extends Registry<? extends T>> registryKey);
+
+ HolderLookup.Provider lookupForValueCopyViaBuilders(); // Paper - add method to get the value for pre-filling builders in the reg mod API
}
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/Main.java
+++ b/net/minecraft/server/Main.java
@@ -67,8 +_,10 @@
@@ -68,8 +_,10 @@
reason = "System.out needed before bootstrap"
)
@DontObfuscate
@ -12,7 +12,7 @@
OptionParser optionParser = new OptionParser();
OptionSpec<Void> optionSpec = optionParser.accepts("nogui");
OptionSpec<Void> optionSpec1 = optionParser.accepts("initSettings", "Initializes 'server.properties' and 'eula.txt', then quits");
@@ -93,41 +_,94 @@
@@ -94,41 +_,94 @@
optionParser.printHelpOn(System.err);
return;
}
@ -116,7 +116,7 @@
Dynamic<?> dataTag;
if (levelStorageAccess.hasWorldData()) {
LevelSummary summary;
@@ -169,12 +_,33 @@
@@ -170,12 +_,33 @@
}
Dynamic<?> dynamic = dataTag;
@ -141,7 +141,7 @@
+ "pack_format": %d
+ }
+ }
+ """.formatted(SharedConstants.getCurrentVersion().getPackVersion(net.minecraft.server.packs.PackType.SERVER_DATA))
+ """.formatted(SharedConstants.getCurrentVersion().packVersion(net.minecraft.server.packs.PackType.SERVER_DATA))
+ );
+ } catch (java.io.IOException ex) {
+ throw new RuntimeException("Could not initialize Bukkit datapack", ex);
@ -151,7 +151,7 @@
WorldStem worldStem;
try {
@@ -183,6 +_,7 @@
@@ -184,6 +_,7 @@
executor -> WorldLoader.load(
initConfig,
context -> {
@ -159,7 +159,7 @@
Registry<LevelStem> registry = context.datapackDimensions().lookupOrThrow(Registries.LEVEL_STEM);
if (dynamic != null) {
LevelDataAndDimensions levelDataAndDimensions = LevelStorageSource.getLevelDataAndDimensions(
@@ -196,7 +_,7 @@
@@ -197,7 +_,7 @@
LevelSettings levelSettings;
WorldOptions worldOptions;
WorldDimensions worldDimensions;
@ -168,7 +168,7 @@
levelSettings = MinecraftServer.DEMO_SETTINGS;
worldOptions = WorldOptions.DEMO_OPTIONS;
worldDimensions = WorldPresets.createNormalWorldDimensions(context.datapackWorldgen());
@@ -211,7 +_,7 @@
@@ -212,7 +_,7 @@
new GameRules(context.dataConfiguration().enabledFeatures()),
context.dataConfiguration()
);
@ -177,7 +177,7 @@
worldDimensions = properties.createDimensions(context.datapackWorldgen());
}
@@ -237,6 +_,7 @@
@@ -238,6 +_,7 @@
return;
}
@ -185,7 +185,7 @@
RegistryAccess.Frozen frozen = worldStem.registries().compositeAccess();
WorldData worldData = worldStem.worldData();
boolean hasOptionSpec1 = optionSet.has(optionSpec6);
@@ -245,9 +_,13 @@
@@ -246,9 +_,13 @@
}
levelStorageAccess.saveDataTag(frozen, worldData);
@ -199,7 +199,7 @@
thread1,
levelStorageAccess,
packRepository,
@@ -257,17 +_,34 @@
@@ -258,18 +_,36 @@
services,
LoggerChunkProgressListener::createFromGameruleRadius
);
@ -221,14 +221,16 @@
if (flag && !GraphicsEnvironment.isHeadless()) {
dedicatedServer1.showGui();
}
+ // Paper start
+ if (optionSet.has("port")) {
+ int port = (Integer) optionSet.valueOf("port");
+ if (port > 0) {
+ dedicatedServer1.setPort(port);
+ }
+ }
+
+ // Paper end
GameTestTicker.SINGLETON.startTicking();
return dedicatedServer1;
}
);
@ -236,7 +238,7 @@
Thread thread = new Thread("Server Shutdown Thread") {
@Override
public void run() {
@@ -276,6 +_,7 @@
@@ -278,6 +_,7 @@
};
thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
Runtime.getRuntime().addShutdownHook(thread);
@ -244,7 +246,7 @@
} catch (Exception var42) {
LOGGER.error(LogUtils.FATAL_MARKER, "Failed to start the minecraft server", (Throwable)var42);
}
@@ -317,7 +_,7 @@
@@ -319,7 +_,7 @@
RegistryAccess registryAccess,
boolean recreateRegionFiles
) {

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -173,11 +_,13 @@
@@ -174,11 +_,13 @@
import org.slf4j.Logger;
public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTask> implements ServerInfo, ChunkIOErrorReporter, CommandSource {
@ -15,7 +15,7 @@
private static final int OVERLOADED_TICKS_THRESHOLD = 20;
private static final long OVERLOADED_WARNING_INTERVAL_NANOS = 10L * TimeUtil.NANOSECONDS_PER_SECOND;
private static final int OVERLOADED_TICKS_WARNING_INTERVAL = 100;
@@ -217,6 +_,7 @@
@@ -218,6 +_,7 @@
private Map<ResourceKey<Level>, ServerLevel> levels = Maps.newLinkedHashMap();
private PlayerList playerList;
private volatile boolean running = true;
@ -23,7 +23,7 @@
private boolean stopped;
private int tickCount;
private int ticksUntilAutosave = 6000;
@@ -225,11 +_,15 @@
@@ -226,11 +_,15 @@
private boolean preventProxyConnections;
private boolean pvp;
private boolean allowFlight;
@ -41,7 +41,7 @@
@Nullable
private KeyPair keyPair;
@Nullable
@@ -270,10 +_,37 @@
@@ -271,10 +_,37 @@
private final SuppressedExceptionCollector suppressedExceptions = new SuppressedExceptionCollector();
private final DiscontinuousFrame tickFrame;
@ -80,7 +80,7 @@
if (Runtime.getRuntime().availableProcessors() > 4) {
thread.setPriority(8);
}
@@ -285,6 +_,10 @@
@@ -286,6 +_,10 @@
}
public MinecraftServer(
@ -91,7 +91,7 @@
Thread serverThread,
LevelStorageSource.LevelStorageAccess storageSource,
PackRepository packRepository,
@@ -295,9 +_,10 @@
@@ -296,9 +_,10 @@
ChunkProgressListenerFactory progressListenerFactory
) {
super("Server");
@ -103,7 +103,7 @@
throw new IllegalStateException("Missing Overworld dimension data");
} else {
this.proxy = proxy;
@@ -308,7 +_,7 @@
@@ -309,7 +_,7 @@
services.profileCache().setExecutor(this);
}
@ -112,7 +112,7 @@
this.tickRateManager = new ServerTickRateManager(this);
this.progressListenerFactory = progressListenerFactory;
this.storageSource = storageSource;
@@ -327,6 +_,38 @@
@@ -328,6 +_,38 @@
this.fuelValues = FuelValues.vanillaBurnTimes(this.registries.compositeAccess(), this.worldData.enabledFeatures());
this.tickFrame = TracyClient.createDiscontinuousFrame("Server Tick");
}
@ -151,7 +151,7 @@
}
private void readScoreboard(DimensionDataStorage dataStorage) {
@@ -335,18 +_,13 @@
@@ -336,18 +_,13 @@
protected abstract boolean initServer() throws IOException;
@ -172,7 +172,7 @@
if (profiledDuration != null) {
profiledDuration.finish(true);
}
@@ -363,25 +_,265 @@
@@ -364,25 +_,265 @@
protected void forceDifficulty() {
}
@ -457,7 +457,7 @@
if (!serverLevelData.isInitialized()) {
try {
setInitialSpawn(serverLevel, serverLevelData, worldOptions.generateBonusChest(), isDebugWorld);
@@ -402,47 +_,30 @@
@@ -403,47 +_,30 @@
serverLevelData.setInitialized(true);
}
@ -522,7 +522,7 @@
int spawnHeight = chunkSource.getGenerator().getSpawnHeight(level);
if (spawnHeight < level.getMinY()) {
BlockPos worldPosition = chunkPos.getWorldPosition();
@@ -494,36 +_,48 @@
@@ -495,36 +_,48 @@
serverLevelData.setGameType(GameType.SPECTATOR);
}
@ -582,7 +582,7 @@
}
public GameType getDefaultGameType() {
@@ -552,11 +_,14 @@
@@ -553,11 +_,14 @@
flag = true;
}
@ -597,7 +597,7 @@
if (flush) {
for (ServerLevel serverLevel2 : this.getAllLevels()) {
LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", serverLevel2.getChunkSource().chunkMap.getStorageName());
@@ -586,18 +_,48 @@
@@ -587,18 +_,48 @@
this.stopServer();
}
@ -647,7 +647,7 @@
}
LOGGER.info("Saving worlds");
@@ -639,6 +_,25 @@
@@ -640,6 +_,25 @@
} catch (IOException var4) {
LOGGER.error("Failed to unlock level {}", this.storageSource.getLevelId(), var4);
}
@ -673,7 +673,7 @@
}
public String getLocalIp() {
@@ -654,6 +_,14 @@
@@ -655,6 +_,14 @@
}
public void halt(boolean waitForServer) {
@ -688,7 +688,7 @@
this.running = false;
if (waitForServer) {
try {
@@ -664,6 +_,57 @@
@@ -665,6 +_,57 @@
}
}
@ -746,7 +746,7 @@
protected void runServer() {
try {
if (!this.initServer()) {
@@ -674,6 +_,35 @@
@@ -675,6 +_,35 @@
this.statusIcon = this.loadStatusIcon().orElse(null);
this.status = this.buildServerStatus();
@ -782,7 +782,7 @@
while (this.running) {
long l;
if (!this.isPaused() && this.tickRateManager.isSprinting() && this.tickRateManager.checkShouldSprintThisTick()) {
@@ -686,11 +_,30 @@
@@ -687,11 +_,30 @@
if (l1 > OVERLOADED_THRESHOLD_NANOS + 20L * l
&& this.nextTickTimeNanos - this.lastOverloadWarningNanos >= OVERLOADED_WARNING_INTERVAL_NANOS + 100L * l) {
long l2 = l1 / l;
@ -813,7 +813,7 @@
boolean flag = l == 0L;
if (this.debugCommandProfilerDelayStart) {
@@ -698,6 +_,8 @@
@@ -699,6 +_,8 @@
this.debugCommandProfiler = new MinecraftServer.TimeProfiler(Util.getNanos(), this.tickCount);
}
@ -822,7 +822,7 @@
this.nextTickTimeNanos += l;
try (Profiler.Scope scope = Profiler.use(this.createProfiler())) {
@@ -748,7 +_,7 @@
@@ -749,7 +_,7 @@
this.services.profileCache().clearExecutor();
}
@ -831,7 +831,7 @@
}
}
}
@@ -800,7 +_,14 @@
@@ -801,7 +_,14 @@
}
private boolean haveTime() {
@ -847,7 +847,7 @@
}
public static boolean throwIfFatalException() {
@@ -845,6 +_,12 @@
@@ -846,6 +_,12 @@
@Override
public TickTask wrapRunnable(Runnable runnable) {
@ -860,7 +860,7 @@
return new TickTask(this.tickCount, runnable);
}
@@ -864,15 +_,16 @@
@@ -865,15 +_,16 @@
if (super.pollTask()) {
return true;
} else {
@ -879,7 +879,7 @@
}
}
@@ -920,26 +_,44 @@
@@ -921,26 +_,44 @@
}
public void tickServer(BooleanSupplier hasTimeLeft) {
@ -925,7 +925,7 @@
this.tickCount++;
this.tickRateManager.tick();
this.tickChildren(hasTimeLeft);
@@ -949,11 +_,19 @@
@@ -950,11 +_,19 @@
}
this.ticksUntilAutosave--;
@ -946,7 +946,7 @@
profilerFiller.push("tallying");
long l = Util.getNanos() - nanos;
int i1 = this.tickCount % 100;
@@ -961,12 +_,17 @@
@@ -962,12 +_,17 @@
this.aggregatedTickTimesNanos += l;
this.tickTimesNanos[i1] = l;
this.smoothedTickTimeMillis = this.smoothedTickTimeMillis * 0.8F + (float)l / (float)TimeUtil.NANOSECONDS_PER_MILLISECOND * 0.19999999F;
@ -965,7 +965,7 @@
LOGGER.debug("Autosave started");
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("save");
@@ -1008,7 +_,7 @@
@@ -1009,7 +_,7 @@
private ServerStatus buildServerStatus() {
ServerStatus.Players players = this.buildPlayerStatus();
return new ServerStatus(
@ -974,7 +974,7 @@
Optional.of(players),
Optional.of(ServerStatus.Version.current()),
Optional.ofNullable(this.statusIcon),
@@ -1022,7 +_,7 @@
@@ -1023,7 +_,7 @@
if (this.hidesOnlinePlayers()) {
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
} else {
@ -983,7 +983,7 @@
ObjectArrayList<GameProfile> list = new ObjectArrayList<>(min);
int randomInt = Mth.nextInt(this.random, 0, players.size() - min);
@@ -1039,17 +_,66 @@
@@ -1040,17 +_,66 @@
protected void tickChildren(BooleanSupplier hasTimeLeft) {
ProfilerFiller profilerFiller = Profiler.get();
this.getPlayerList().getPlayers().forEach(serverPlayer1 -> serverPlayer1.connection.suspendFlushing());
@ -1050,7 +1050,7 @@
profilerFiller.push("tick");
@@ -1063,7 +_,9 @@
@@ -1064,7 +_,9 @@
profilerFiller.pop();
profilerFiller.pop();
@ -1060,7 +1060,7 @@
profilerFiller.popPush("connection");
this.tickConnection();
@@ -1141,6 +_,22 @@
@@ -1142,6 +_,22 @@
return this.levels.get(dimension);
}
@ -1083,7 +1083,7 @@
public Set<ResourceKey<Level>> levelKeys() {
return this.levels.keySet();
}
@@ -1170,7 +_,7 @@
@@ -1171,7 +_,7 @@
@DontObfuscate
public String getServerModName() {
@ -1092,7 +1092,7 @@
}
public SystemReport fillSystemReport(SystemReport systemReport) {
@@ -1205,7 +_,7 @@
@@ -1206,7 +_,7 @@
@Override
public void sendSystemMessage(Component component) {
@ -1101,7 +1101,7 @@
}
public KeyPair getKeyPair() {
@@ -1243,11 +_,14 @@
@@ -1244,11 +_,14 @@
}
}
@ -1121,7 +1121,7 @@
}
}
@@ -1257,7 +_,7 @@
@@ -1258,7 +_,7 @@
private void updateMobSpawningFlags() {
for (ServerLevel serverLevel : this.getAllLevels()) {
@ -1130,7 +1130,7 @@
}
}
@@ -1333,10 +_,20 @@
@@ -1334,10 +_,20 @@
@Override
public String getMotd() {
@ -1152,7 +1152,7 @@
this.motd = motd;
}
@@ -1359,7 +_,7 @@
@@ -1360,7 +_,7 @@
}
public ServerConnectionListener getConnection() {
@ -1161,7 +1161,7 @@
}
public boolean isReady() {
@@ -1445,7 +_,7 @@
@@ -1446,7 +_,7 @@
@Override
public void executeIfPossible(Runnable task) {
if (this.isStopped()) {
@ -1170,7 +1170,7 @@
} else {
super.executeIfPossible(task);
}
@@ -1484,7 +_,14 @@
@@ -1485,7 +_,14 @@
return this.functionManager;
}
@ -1185,7 +1185,7 @@
CompletableFuture<Void> completableFuture = CompletableFuture.<ImmutableList>supplyAsync(
() -> selectedIds.stream().map(this.packRepository::getPack).filter(Objects::nonNull).map(Pack::open).collect(ImmutableList.toImmutableList()),
this
@@ -1492,7 +_,7 @@
@@ -1493,7 +_,7 @@
.thenCompose(
list -> {
CloseableResourceManager closeableResourceManager = new MultiPackResourceManager(PackType.SERVER_DATA, list);
@ -1194,7 +1194,7 @@
return ReloadableServerResources.loadResources(
closeableResourceManager,
this.registries,
@@ -1513,20 +_,39 @@
@@ -1514,20 +_,39 @@
)
.thenAcceptAsync(
reloadableResources -> {
@ -1236,7 +1236,7 @@
},
this
);
@@ -1543,7 +_,7 @@
@@ -1544,7 +_,7 @@
DataPackConfig dataPackConfig = initialDataConfig.dataPacks();
FeatureFlagSet featureFlagSet = initMode ? FeatureFlagSet.of() : initialDataConfig.enabledFeatures();
FeatureFlagSet featureFlagSet1 = initMode ? FeatureFlags.REGISTRY.allFlags() : initialDataConfig.enabledFeatures();
@ -1245,7 +1245,7 @@
if (safeMode) {
return configureRepositoryWithSelection(packRepository, List.of("vanilla"), featureFlagSet, false);
} else {
@@ -1598,7 +_,7 @@
@@ -1599,7 +_,7 @@
private static WorldDataConfiguration configureRepositoryWithSelection(
PackRepository packRepository, Collection<String> selectedPacks, FeatureFlagSet enabledFeatures, boolean safeMode
) {
@ -1254,7 +1254,7 @@
enableForcedFeaturePacks(packRepository, enabledFeatures);
DataPackConfig selectedPacks1 = getSelectedPacks(packRepository, safeMode);
FeatureFlagSet featureFlagSet = packRepository.getRequestedFeatureFlags().join(enabledFeatures);
@@ -1630,7 +_,7 @@
@@ -1631,7 +_,7 @@
}
}
@ -1263,7 +1263,7 @@
}
}
@@ -1644,11 +_,12 @@
@@ -1645,11 +_,12 @@
public void kickUnlistedPlayers(CommandSourceStack commandSource) {
if (this.isEnforceWhitelist()) {
PlayerList playerList = commandSource.getServer().getPlayerList();
@ -1278,7 +1278,7 @@
}
}
}
@@ -1852,6 +_,17 @@
@@ -1853,6 +_,17 @@
}
}
@ -1296,7 +1296,7 @@
private ProfilerFiller createProfiler() {
if (this.willStartRecordingMetrics) {
this.metricsRecorder = ActiveMetricsRecorder.createStarted(
@@ -1973,16 +_,22 @@
@@ -1974,16 +_,22 @@
}
public void logChatMessage(Component content, ChatType.Bound boundChatType, @Nullable String header) {
@ -1323,7 +1323,7 @@
}
public boolean logIPs() {
@@ -2115,4 +_,53 @@
@@ -2120,4 +_,53 @@
};
}
}

View File

@ -17,7 +17,7 @@
public PlayerAdvancements(DataFixer dataFixer, PlayerList playerList, ServerAdvancementManager manager, Path playerSavePath, ServerPlayer player) {
this.playerList = playerList;
@@ -128,6 +_,7 @@
@@ -127,6 +_,7 @@
}
public void save() {
@ -25,7 +25,7 @@
JsonElement jsonElement = this.codec.encodeStart(JsonOps.INSTANCE, this.asData()).getOrThrow();
try {
@@ -145,6 +_,7 @@
@@ -144,6 +_,7 @@
data.forEach((path, progress) -> {
AdvancementHolder advancementHolder = advancementManager.get(path);
if (advancementHolder == null) {
@ -33,7 +33,7 @@
LOGGER.warn("Ignored advancement '{}' in progress file {} - it doesn't exist anymore?", path, this.playerSavePath);
} else {
this.startProgress(advancementHolder, progress);
@@ -169,14 +_,31 @@
@@ -168,14 +_,31 @@
AdvancementProgress orStartProgress = this.getOrStartProgress(advancement);
boolean isDone = orStartProgress.isDone();
if (orStartProgress.grantProgress(criterionKey)) {
@ -58,16 +58,16 @@
+ // Paper end
advancement.value().rewards().grant(this.player);
advancement.value().display().ifPresent(displayInfo -> {
- if (displayInfo.shouldAnnounceChat() && this.player.serverLevel().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) {
- if (displayInfo.shouldAnnounceChat() && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) {
- this.playerList.broadcastSystemMessage(displayInfo.getType().createAnnouncement(advancement, this.player), false);
+ // Paper start - Add Adventure message to PlayerAdvancementDoneEvent
+ if (event.message() != null && this.player.serverLevel().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) {
+ if (event.message() != null && this.player.level().getGameRules().getBoolean(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)) {
+ this.playerList.broadcastSystemMessage(io.papermc.paper.adventure.PaperAdventure.asVanilla(event.message()), false);
+ // Paper end
}
});
}
@@ -247,7 +_,7 @@
@@ -246,7 +_,7 @@
public void flushDirty(ServerPlayer player, boolean showAdvancements) {
if (this.isFirstPacket || !this.rootsToUpdate.isEmpty() || !this.progressChanged.isEmpty()) {
Map<ResourceLocation, AdvancementProgress> map = new HashMap<>();

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/ReloadableServerRegistries.java
+++ b/net/minecraft/server/ReloadableServerRegistries.java
@@ -48,8 +_,9 @@
@@ -46,8 +_,9 @@
List<HolderLookup.RegistryLookup<?>> list = TagLoader.buildUpdatedLookups(registryAccess.getAccessForLoading(RegistryLayer.RELOADABLE), postponedTags);
HolderLookup.Provider provider = HolderLookup.Provider.create(list.stream());
RegistryOps<JsonElement> registryOps = provider.createSerializationContext(JsonOps.INSTANCE);
@ -11,7 +11,7 @@
.toList();
CompletableFuture<List<WritableRegistry<?>>> completableFuture = Util.sequence(list1);
return completableFuture.thenApplyAsync(
@@ -58,19 +_,20 @@
@@ -56,19 +_,20 @@
}
private static <T> CompletableFuture<WritableRegistry<?>> scheduleRegistryLoad(
@ -21,7 +21,7 @@
return CompletableFuture.supplyAsync(
() -> {
WritableRegistry<T> writableRegistry = new MappedRegistry<>(lootDataType.registryKey(), Lifecycle.experimental());
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerReloadableRegistry(lootDataType.registryKey(), writableRegistry); // Paper - register reloadable registry
+ io.papermc.paper.registry.PaperRegistryAccess.instance().registerReloadableRegistry(writableRegistry); // Paper - register reloadable registry
Map<ResourceLocation, T> map = new HashMap<>();
SimpleJsonResourceReloadListener.scanDirectory(resourceManager, lootDataType.registryKey(), ops, lootDataType.codec(), map);
map.forEach(

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/ServerScoreboard.java
+++ b/net/minecraft/server/ServerScoreboard.java
@@ -43,9 +_,7 @@
@@ -45,9 +_,7 @@
protected void onScoreChanged(ScoreHolder scoreHolder, Objective objective, Score score) {
super.onScoreChanged(scoreHolder, objective, score);
if (this.trackedObjectives.contains(objective)) {
@ -11,7 +11,7 @@
new ClientboundSetScorePacket(
scoreHolder.getScoreboardName(),
objective.getName(),
@@ -68,7 +_,7 @@
@@ -70,7 +_,7 @@
@Override
public void onPlayerRemoved(ScoreHolder scoreHolder) {
super.onPlayerRemoved(scoreHolder);
@ -20,7 +20,7 @@
this.setDirty();
}
@@ -76,7 +_,7 @@
@@ -78,7 +_,7 @@
public void onPlayerScoreRemoved(ScoreHolder scoreHolder, Objective objective) {
super.onPlayerScoreRemoved(scoreHolder, objective);
if (this.trackedObjectives.contains(objective)) {
@ -29,7 +29,7 @@
}
this.setDirty();
@@ -88,7 +_,7 @@
@@ -90,7 +_,7 @@
super.setDisplayObjective(slot, objective);
if (displayObjective != objective && displayObjective != null) {
if (this.getObjectiveDisplaySlotCount(displayObjective) > 0) {
@ -38,7 +38,7 @@
} else {
this.stopTrackingObjective(displayObjective);
}
@@ -96,7 +_,7 @@
@@ -98,7 +_,7 @@
if (objective != null) {
if (this.trackedObjectives.contains(objective)) {
@ -47,27 +47,21 @@
} else {
this.startTrackingObjective(objective);
}
@@ -108,24 +_,50 @@
@@ -110,9 +_,7 @@
@Override
public boolean addPlayerToTeam(String playerName, PlayerTeam team) {
if (super.addPlayerToTeam(playerName, team)) {
- this.server
- .getPlayerList()
- .broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, playerName, ClientboundSetPlayerTeamPacket.Action.ADD));
- this.setDirty();
- return true;
- } else {
- return false;
- }
- }
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(team, playerName, ClientboundSetPlayerTeamPacket.Action.ADD)); // CraftBukkit
+ this.setDirty();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
this.updatePlayerWaypoint(playerName);
this.setDirty();
return true;
@@ -121,16 +_,44 @@
}
}
+ // Paper start - Multiple Entries with Scoreboards
+ public boolean addPlayersToTeam(java.util.Collection<String> players, PlayerTeam team) {
+ boolean anyAdded = false;
@ -86,19 +80,18 @@
+ }
+ }
+ // Paper end - Multiple Entries with Scoreboards
+
@Override
public void removePlayerFromTeam(String username, PlayerTeam playerTeam) {
super.removePlayerFromTeam(username, playerTeam);
- this.server
- .getPlayerList()
- .broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.Action.REMOVE));
- this.setDirty();
- }
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createPlayerPacket(playerTeam, username, ClientboundSetPlayerTeamPacket.Action.REMOVE)); // CraftBukkit
+ this.setDirty();
+ }
+
this.updatePlayerWaypoint(username);
this.setDirty();
}
+ // Paper start - Multiple Entries with Scoreboards
+ public void removePlayersFromTeam(java.util.Collection<String> players, PlayerTeam team) {
+ for (String playerName : players) {
@ -109,10 +102,11 @@
+ this.setDirty();
+ }
+ // Paper end - Multiple Entries with Scoreboards
+
@Override
public void onObjectiveAdded(Objective objective) {
@@ -137,7 +_,7 @@
super.onObjectiveAdded(objective);
@@ -141,7 +_,7 @@
public void onObjectiveChanged(Objective objective) {
super.onObjectiveChanged(objective);
if (this.trackedObjectives.contains(objective)) {
@ -121,7 +115,7 @@
}
this.setDirty();
@@ -156,21 +_,21 @@
@@ -160,14 +_,14 @@
@Override
public void onTeamAdded(PlayerTeam playerTeam) {
super.onTeamAdded(playerTeam);
@ -135,18 +129,19 @@
super.onTeamChanged(playerTeam);
- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false));
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(playerTeam, false)); // CraftBukkit
this.updateTeamWaypoints(playerTeam);
this.setDirty();
}
@@ -175,7 +_,7 @@
@Override
public void onTeamRemoved(PlayerTeam playerTeam) {
super.onTeamRemoved(playerTeam);
- this.server.getPlayerList().broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam));
+ this.broadcastAll(ClientboundSetPlayerTeamPacket.createRemovePacket(playerTeam)); // CraftBukkit
this.updateTeamWaypoints(playerTeam);
this.setDirty();
}
@@ -213,6 +_,7 @@
@@ -219,6 +_,7 @@
List<Packet<?>> startTrackingPackets = this.getStartTrackingPackets(objective);
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
@ -154,7 +149,7 @@
for (Packet<?> packet : startTrackingPackets) {
serverPlayer.connection.send(packet);
}
@@ -238,6 +_,7 @@
@@ -244,6 +_,7 @@
List<Packet<?>> stopTrackingPackets = this.getStopTrackingPackets(objective);
for (ServerPlayer serverPlayer : this.server.getPlayerList().getPlayers()) {
@ -162,11 +157,10 @@
for (Packet<?> packet : stopTrackingPackets) {
serverPlayer.connection.send(packet);
}
@@ -269,6 +_,16 @@
scoreboardSaveData.loadFrom(data);
return scoreboardSaveData;
@@ -295,4 +_,13 @@
.forEach(serverPlayer -> serverLevel.getWaypointManager().remakeConnections(serverPlayer));
}
}
+
+ // CraftBukkit start - Send to players
+ private void broadcastAll(Packet<?> packet) {
+ for (ServerPlayer serverPlayer : this.server.getPlayerList().players) {
@ -176,6 +170,4 @@
+ }
+ }
+ // CraftBukkit end
public static enum Method {
CHANGE,
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/commands/BanPlayerCommands.java
+++ b/net/minecraft/server/commands/BanPlayerCommands.java
@@ -55,7 +_,7 @@
@@ -57,7 +_,7 @@
);
ServerPlayer player = source.getServer().getPlayerList().getPlayer(gameProfile.getId());
if (player != null) {

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/commands/DeOpCommands.java
+++ b/net/minecraft/server/commands/DeOpCommands.java
@@ -35,7 +_,7 @@
@@ -39,7 +_,7 @@
if (playerList.isOp(gameProfile)) {
playerList.deop(gameProfile);
i++;

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/commands/EffectCommands.java
+++ b/net/minecraft/server/commands/EffectCommands.java
@@ -180,7 +_,7 @@
@@ -182,7 +_,7 @@
for (Entity entity : targets) {
if (entity instanceof LivingEntity) {
MobEffectInstance mobEffectInstance = new MobEffectInstance(effect, i1, amplifier, false, showParticles);
@ -9,7 +9,7 @@
i++;
}
}
@@ -210,7 +_,7 @@
@@ -212,7 +_,7 @@
int i = 0;
for (Entity entity : targets) {
@ -18,7 +18,7 @@
i++;
}
}
@@ -235,7 +_,7 @@
@@ -237,7 +_,7 @@
int i = 0;
for (Entity entity : targets) {

View File

@ -1,18 +1,20 @@
--- a/net/minecraft/server/commands/GameModeCommand.java
+++ b/net/minecraft/server/commands/GameModeCommand.java
@@ -54,9 +_,14 @@
int i = 0;
@@ -69,9 +_,16 @@
}
for (ServerPlayer serverPlayer : players) {
- if (serverPlayer.setGameMode(gameType)) {
+ // Paper start - Expand PlayerGameModeChangeEvent
+ org.bukkit.event.player.PlayerGameModeChangeEvent event = serverPlayer.setGameMode(gameType, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.empty());
+ if (event != null && !event.isCancelled()) {
logGamemodeChange(source.getSource(), serverPlayer, gameType);
i++;
+ } else if (event != null && event.cancelMessage() != null) {
+ source.getSource().sendSuccess(() -> io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), true);
+ // Paper end - Expand PlayerGameModeChangeEvent
}
private static boolean setGameMode(CommandSourceStack source, ServerPlayer player, GameType gameMode) {
- if (player.setGameMode(gameMode)) {
+ // Paper start
+ org.bukkit.event.player.PlayerGameModeChangeEvent event = player.setGameMode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.COMMAND, net.kyori.adventure.text.Component.empty());
+ if (event != null && !event.isCancelled()) {
+ // Paper end
logGamemodeChange(source, player, gameMode);
return true;
+ } else if (event != null && event.cancelMessage() != null) {
+ source.sendSuccess(() -> io.papermc.paper.adventure.PaperAdventure.asVanilla(event.cancelMessage()), true);
+ return false;
+ // Paper end - Expand PlayerGameModeChangeEvent
} else {
return false;
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/commands/GiveCommand.java
+++ b/net/minecraft/server/commands/GiveCommand.java
@@ -51,6 +_,7 @@
@@ -54,6 +_,7 @@
private static int giveItem(CommandSourceStack source, ItemInput item, Collection<ServerPlayer> targets, int count) throws CommandSyntaxException {
ItemStack itemStack = item.createItemStack(1, false);
@ -8,25 +8,7 @@
int maxStackSize = itemStack.getMaxStackSize();
int i = maxStackSize * 100;
if (count > i) {
@@ -66,7 +_,7 @@
ItemStack itemStack1 = item.createItemStack(min, false);
boolean flag = serverPlayer.getInventory().add(itemStack1);
if (flag && itemStack1.isEmpty()) {
- ItemEntity itemEntity = serverPlayer.drop(itemStack, false);
+ ItemEntity itemEntity = serverPlayer.drop(itemStack, false, false, false, null); // Paper - do not fire PlayerDropItemEvent for /give command
if (itemEntity != null) {
itemEntity.makeFakeItem();
}
@@ -84,7 +_,7 @@
);
serverPlayer.containerMenu.broadcastChanges();
} else {
- ItemEntity itemEntity = serverPlayer.drop(itemStack1, false);
+ ItemEntity itemEntity = serverPlayer.drop(itemStack1, false, false, false, null); // Paper - do not fire PlayerDropItemEvent for /give command
if (itemEntity != null) {
itemEntity.setNoPickUpDelay();
itemEntity.setTarget(serverPlayer.getUUID());
@@ -95,11 +_,11 @@
@@ -98,11 +_,11 @@
if (targets.size() == 1) {
source.sendSuccess(

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/commands/KickCommand.java
+++ b/net/minecraft/server/commands/KickCommand.java
@@ -48,7 +_,7 @@
@@ -50,7 +_,7 @@
for (ServerPlayer serverPlayer : players) {
if (!source.getServer().isSingleplayerOwner(serverPlayer.getGameProfile())) {

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/commands/LocateCommand.java
+++ b/net/minecraft/server/commands/LocateCommand.java
@@ -202,6 +_,6 @@
@@ -199,6 +_,6 @@
private static float dist(int x1, int z1, int x2, int z2) {
int i = x2 - x1;
int i1 = z2 - z1;

View File

@ -34,4 +34,4 @@
+ // CraftBukkit end
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
dispatcher.register(Commands.literal("reload").requires(source -> source.hasPermission(2)).executes(context -> {
dispatcher.register(Commands.literal("reload").requires(Commands.hasPermission(2)).executes(commandContext -> {

View File

@ -1,11 +1,11 @@
--- a/net/minecraft/server/commands/RideCommand.java
+++ b/net/minecraft/server/commands/RideCommand.java
@@ -58,7 +_,7 @@
@@ -60,7 +_,7 @@
Entity vehicle1 = target.getVehicle();
if (vehicle1 != null) {
throw ERROR_ALREADY_RIDING.create(target.getDisplayName(), vehicle1.getDisplayName());
- } else if (vehicle.getType() == EntityType.PLAYER) {
+ } else if (vehicle.getType() == EntityType.PLAYER && !io.papermc.paper.configuration.GlobalConfiguration.get().commands.rideCommandAllowPlayerAsVehicle) { // Paper - allow player as vehicle
throw ERROR_MOUNTING_PLAYER.create();
} else if (target.getSelfAndPassengers().anyMatch(passenger -> passenger == vehicle)) {
} else if (target.getSelfAndPassengers().anyMatch(entity -> entity == vehicle)) {
throw ERROR_MOUNTING_LOOP.create();

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/commands/WorldBorderCommand.java
+++ b/net/minecraft/server/commands/WorldBorderCommand.java
@@ -135,7 +_,7 @@
@@ -136,7 +_,7 @@
}
private static int setDamageBuffer(CommandSourceStack source, float distance) throws CommandSyntaxException {
@ -9,7 +9,7 @@
if (worldBorder.getDamageSafeZone() == distance) {
throw ERROR_SAME_DAMAGE_BUFFER.create();
} else {
@@ -146,7 +_,7 @@
@@ -147,7 +_,7 @@
}
private static int setDamageAmount(CommandSourceStack source, float damagePerBlock) throws CommandSyntaxException {
@ -18,7 +18,7 @@
if (worldBorder.getDamagePerBlock() == damagePerBlock) {
throw ERROR_SAME_DAMAGE_AMOUNT.create();
} else {
@@ -159,7 +_,7 @@
@@ -160,7 +_,7 @@
}
private static int setWarningTime(CommandSourceStack source, int time) throws CommandSyntaxException {
@ -27,7 +27,7 @@
if (worldBorder.getWarningTime() == time) {
throw ERROR_SAME_WARNING_TIME.create();
} else {
@@ -170,7 +_,7 @@
@@ -171,7 +_,7 @@
}
private static int setWarningDistance(CommandSourceStack source, int distance) throws CommandSyntaxException {
@ -36,7 +36,7 @@
if (worldBorder.getWarningBlocks() == distance) {
throw ERROR_SAME_WARNING_DISTANCE.create();
} else {
@@ -181,13 +_,13 @@
@@ -182,13 +_,13 @@
}
private static int getSize(CommandSourceStack source) {
@ -52,7 +52,7 @@
if (worldBorder.getCenterX() == pos.x && worldBorder.getCenterZ() == pos.y) {
throw ERROR_SAME_CENTER.create();
} else if (!(Math.abs(pos.x) > 2.9999984E7) && !(Math.abs(pos.y) > 2.9999984E7)) {
@@ -205,7 +_,7 @@
@@ -206,7 +_,7 @@
}
private static int setSize(CommandSourceStack source, double newSize, long time) throws CommandSyntaxException {

View File

@ -70,7 +70,7 @@
thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
- thread.start();
+ // thread.start(); // Paper - Enhance console tab completions for brigadier commands; moved down
LOGGER.info("Starting minecraft server version {}", SharedConstants.getCurrentVersion().getName());
LOGGER.info("Starting minecraft server version {}", SharedConstants.getCurrentVersion().name());
if (Runtime.getRuntime().maxMemory() / 1024L / 1024L < 512L) {
LOGGER.warn("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\"");
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/dedicated/DedicatedServerProperties.java
+++ b/net/minecraft/server/dedicated/DedicatedServerProperties.java
@@ -45,6 +_,7 @@
@@ -47,6 +_,7 @@
static final Logger LOGGER = LogUtils.getLogger();
private static final Pattern SHA1 = Pattern.compile("^[a-fA-F0-9]{40}$");
private static final Splitter COMMA_SPLITTER = Splitter.on(',').trimResults();
@ -8,7 +8,7 @@
public final boolean onlineMode = this.get("online-mode", true);
public final boolean preventProxyConnections = this.get("prevent-proxy-connections", false);
public final String serverIp = this.get("server-ip", "");
@@ -85,7 +_,7 @@
@@ -87,7 +_,7 @@
public final boolean broadcastRconToOps = this.get("broadcast-rcon-to-ops", true);
public final boolean broadcastConsoleToOps = this.get("broadcast-console-to-ops", true);
public final int maxWorldSize = this.get("max-world-size", property -> Mth.clamp(property, 1, 29999984), 29999984);
@ -17,7 +17,7 @@
public final String regionFileComression = this.get("region-file-compression", "deflate");
public final boolean enableJmxMonitoring = this.get("enable-jmx-monitoring", false);
public final boolean enableStatus = this.get("enable-status", true);
@@ -99,13 +_,16 @@
@@ -101,13 +_,16 @@
public final Settings<DedicatedServerProperties>.MutableValue<Boolean> whiteList = this.getMutable("white-list", false);
public final boolean enforceSecureProfile = this.get("enforce-secure-profile", true);
public final boolean logIPs = this.get("log-ips", true);
@ -37,7 +37,7 @@
String string = this.get("level-seed", "");
boolean flag = this.get("generate-structures", true);
long l = WorldOptions.parseSeed(string).orElse(WorldOptions.randomSeed());
@@ -126,15 +_,21 @@
@@ -128,15 +_,21 @@
this.get("initial-enabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getEnabled())),
this.get("initial-disabled-packs", String.join(",", WorldDataConfiguration.DEFAULT.dataPacks().getDisabled()))
);

View File

@ -5,7 +5,7 @@
@VisibleForDebug
private NaturalSpawner.SpawnState lastSpawnState;
+ // Paper start
+ private final ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<net.minecraft.world.level.chunk.LevelChunk> fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>();
+ public final ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<net.minecraft.world.level.chunk.LevelChunk> fullChunks = new ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable<>();
+ public int getFullChunksCount() {
+ return this.fullChunks.size();
+ }
@ -146,7 +146,7 @@
+ ProfilerFiller gameprofilerfiller = Profiler.get();
+
+ gameprofilerfiller.push("purge");
+ this.ticketStorage.purgeStaleTickets();
+ this.ticketStorage.purgeStaleTickets(this.chunkMap);
+ this.runDistanceManagerUpdates();
+ gameprofilerfiller.popPush("unload");
+ this.chunkMap.tick(() -> true);
@ -161,7 +161,7 @@
profilerFiller.push("purge");
- if (this.level.tickRateManager().runsNormally() || !tickChunks) {
+ if (this.level.tickRateManager().runsNormally() || !tickChunks || this.level.spigotConfig.unloadFrozenChunks) { // Spigot
this.ticketStorage.purgeStaleTickets();
this.ticketStorage.purgeStaleTickets(this.chunkMap);
}
@@ -388,12 +_,20 @@
@ -188,7 +188,7 @@
} else {
filteredSpawningCategories = List.of();
}
@@ -544,8 +_,13 @@
@@ -547,8 +_,13 @@
@Override
public void setSpawnSettings(boolean spawnSettings) {
@ -203,7 +203,7 @@
}
public String getChunkDebugData(ChunkPos chunkPos) {
@@ -618,12 +_,18 @@
@@ -621,12 +_,18 @@
@Override
public boolean pollTask() {

View File

@ -70,7 +70,7 @@
Packet<?> packet = null;
boolean flag2 = flag1 || this.tickCount % 60 == 0;
boolean flag3 = false;
@@ -223,6 +_,25 @@
@@ -227,6 +_,25 @@
this.tickCount++;
if (this.entity.hurtMarked) {
@ -96,7 +96,7 @@
this.entity.hurtMarked = false;
this.broadcastAndSend(new ClientboundSetEntityMotionPacket(this.entity));
}
@@ -280,7 +_,10 @@
@@ -284,7 +_,10 @@
public void sendPairingData(ServerPlayer player, Consumer<Packet<ClientGamePacketListener>> consumer) {
if (this.entity.isRemoved()) {
@ -108,11 +108,10 @@
}
Packet<ClientGamePacketListener> addEntityPacket = this.entity.getAddEntityPacket(this);
@@ -292,6 +_,12 @@
boolean flag = this.trackDelta;
if (this.entity instanceof LivingEntity) {
Collection<AttributeInstance> syncableAttributes = ((LivingEntity)this.entity).getAttributes().getSyncableAttributes();
+
@@ -295,6 +_,11 @@
if (this.entity instanceof LivingEntity livingEntity) {
Collection<AttributeInstance> syncableAttributes = livingEntity.getAttributes().getSyncableAttributes();
+ // CraftBukkit start - If sending own attributes send scaled health instead of current maximum health
+ if (this.entity.getId() == player.getId()) {
+ ((ServerPlayer) this.entity).getBukkitEntity().injectScaledMaxHealth(syncableAttributes, false);
@ -121,7 +120,7 @@
if (!syncableAttributes.isEmpty()) {
consumer.accept(new ClientboundUpdateAttributesPacket(this.entity.getId(), syncableAttributes));
}
@@ -316,8 +_,9 @@
@@ -311,8 +_,9 @@
}
if (!list.isEmpty()) {
@ -132,7 +131,7 @@
}
if (!this.entity.getPassengers().isEmpty()) {
@@ -364,6 +_,11 @@
@@ -359,6 +_,11 @@
if (this.entity instanceof LivingEntity) {
Set<AttributeInstance> attributesToSync = ((LivingEntity)this.entity).getAttributes().getAttributesToSync();
if (!attributesToSync.isEmpty()) {

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -178,7 +_,7 @@
@@ -180,7 +_,7 @@
final List<ServerPlayer> players = Lists.newArrayList();
public final ServerChunkCache chunkSource;
private final MinecraftServer server;
@ -8,8 +8,8 @@
+ public final net.minecraft.world.level.storage.PrimaryLevelData serverLevelData; // CraftBukkit - type
private int lastSpawnChunkRadius;
final EntityTickList entityTickList = new EntityTickList();
public final PersistentEntitySectionManager<Entity> entityManager;
@@ -205,11 +_,131 @@
private final ServerWaypointManager waypointManager;
@@ -208,11 +_,131 @@
private final boolean tickTime;
private final RandomSequences randomSequences;
@ -142,7 +142,7 @@
ResourceKey<Level> dimension,
LevelStem levelStem,
ChunkProgressListener progressListener,
@@ -217,14 +_,38 @@
@@ -220,14 +_,38 @@
long biomeZoomSeed,
List<CustomSpawner> customSpawners,
boolean tickTime,
@ -183,7 +183,7 @@
boolean flag = server.forceSynchronousWrites();
DataFixer fixerUpper = server.getFixerUpper();
EntityPersistentStorage<Entity> entityPersistentStorage = new EntityStorage(
@@ -246,8 +_,8 @@
@@ -249,8 +_,8 @@
server.getStructureManager(),
dispatcher,
chunkGenerator,
@ -194,7 +194,7 @@
flag,
progressListener,
this.entityManager::updateChunkStatus,
@@ -268,7 +_,7 @@
@@ -271,7 +_,7 @@
this.chunkSource.chunkScanner(),
this.registryAccess(),
server.getStructureManager(),
@ -203,7 +203,7 @@
chunkGenerator,
this.chunkSource.randomState(),
this,
@@ -276,9 +_,9 @@
@@ -279,9 +_,9 @@
seed,
fixerUpper
);
@ -216,10 +216,10 @@
} else {
this.dragonFight = null;
}
@@ -286,7 +_,15 @@
this.sleepStatus = new SleepStatus();
@@ -290,7 +_,15 @@
this.gameEventDispatcher = new GameEventDispatcher(this);
this.randomSequences = Objects.requireNonNullElseGet(randomSequences, () -> this.getDataStorage().computeIfAbsent(RandomSequences.TYPE));
this.waypointManager = new ServerWaypointManager();
- }
+ this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
+ }
@ -233,7 +233,7 @@
@Deprecated
@VisibleForTesting
@@ -298,8 +_,8 @@
@@ -302,8 +_,8 @@
this.serverLevelData.setClearWeatherTime(clearTime);
this.serverLevelData.setRainTime(weatherTime);
this.serverLevelData.setThunderTime(weatherTime);
@ -244,7 +244,7 @@
}
@Override
@@ -326,12 +_,25 @@
@@ -330,12 +_,25 @@
int _int = this.getGameRules().getInt(GameRules.RULE_PLAYERS_SLEEPING_PERCENTAGE);
if (this.sleepStatus.areEnoughSleeping(_int) && this.sleepStatus.areEnoughDeepSleeping(_int, this.players)) {
@ -273,7 +273,7 @@
if (this.getGameRules().getBoolean(GameRules.RULE_WEATHER_CYCLE) && this.isRaining()) {
this.resetWeatherCycle();
}
@@ -346,9 +_,9 @@
@@ -350,9 +_,9 @@
if (!this.isDebug() && runsNormally) {
long l = this.getGameTime();
profilerFiller.push("blockTicks");
@ -285,7 +285,7 @@
profilerFiller.pop();
}
@@ -366,7 +_,7 @@
@@ -370,7 +_,7 @@
this.handlingTick = false;
profilerFiller.pop();
@ -294,7 +294,7 @@
if (flag) {
this.resetEmptyTime();
}
@@ -455,11 +_,13 @@
@@ -459,11 +_,13 @@
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("iceandsnow");
@ -308,7 +308,7 @@
profilerFiller.popPush("tickBlocks");
if (randomTickSpeed > 0) {
@@ -502,12 +_,12 @@
@@ -506,12 +_,12 @@
int minBlockZ = pos.getMinBlockZ();
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("thunder");
@ -323,7 +323,7 @@
&& !this.getBlockState(blockPos.below()).is(Blocks.LIGHTNING_ROD);
if (flag) {
SkeletonHorse skeletonHorse = EntityType.SKELETON_HORSE.create(this, EntitySpawnReason.EVENT);
@@ -515,7 +_,7 @@
@@ -519,7 +_,7 @@
skeletonHorse.setTrap(true);
skeletonHorse.setAge(0);
skeletonHorse.setPos(blockPos.getX(), blockPos.getY(), blockPos.getZ());
@ -332,7 +332,7 @@
}
}
@@ -523,7 +_,7 @@
@@ -527,7 +_,7 @@
if (lightningBolt != null) {
lightningBolt.snapTo(Vec3.atBottomCenterOf(blockPos));
lightningBolt.setVisualOnly(flag);
@ -341,7 +341,7 @@
}
}
}
@@ -537,7 +_,7 @@
@@ -541,7 +_,7 @@
BlockPos blockPos1 = heightmapPos.below();
Biome biome = this.getBiome(heightmapPos).value();
if (biome.shouldFreeze(this, blockPos1)) {
@ -350,7 +350,7 @@
}
if (this.isRaining()) {
@@ -549,10 +_,10 @@
@@ -553,10 +_,10 @@
if (layersValue < Math.min(_int, 8)) {
BlockState blockState1 = blockState.setValue(SnowLayerBlock.LAYERS, layersValue + 1);
Block.pushEntitiesUp(blockState, blockState1, this, heightmapPos);
@ -363,7 +363,7 @@
}
}
@@ -577,6 +_,12 @@
@@ -581,6 +_,12 @@
}
protected BlockPos findLightningTargetAround(BlockPos pos) {
@ -376,7 +376,7 @@
BlockPos heightmapPos = this.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, pos);
Optional<BlockPos> optional = this.findLightningRod(heightmapPos);
if (optional.isPresent()) {
@@ -584,11 +_,12 @@
@@ -588,11 +_,12 @@
} else {
AABB aabb = AABB.encapsulatingFullBlocks(heightmapPos, heightmapPos.atY(this.getMaxY() + 1)).inflate(3.0);
List<LivingEntity> entitiesOfClass = this.getEntitiesOfClass(
@ -390,7 +390,7 @@
if (heightmapPos.getY() == this.getMinY() - 1) {
heightmapPos = heightmapPos.above(2);
}
@@ -675,8 +_,8 @@
@@ -683,8 +_,8 @@
this.serverLevelData.setThunderTime(thunderTime);
this.serverLevelData.setRainTime(rainTime);
this.serverLevelData.setClearWeatherTime(clearWeatherTime);
@ -401,7 +401,7 @@
}
this.oThunderLevel = this.thunderLevel;
@@ -697,6 +_,7 @@
@@ -705,6 +_,7 @@
this.rainLevel = Mth.clamp(this.rainLevel, 0.0F, 1.0F);
}
@ -409,7 +409,7 @@
if (this.oRainLevel != this.rainLevel) {
this.server
.getPlayerList()
@@ -719,14 +_,47 @@
@@ -727,14 +_,47 @@
this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.RAIN_LEVEL_CHANGE, this.rainLevel));
this.server.getPlayerList().broadcastAll(new ClientboundGameEventPacket(ClientboundGameEventPacket.THUNDER_LEVEL_CHANGE, this.thunderLevel));
}
@ -461,7 +461,7 @@
}
public void resetEmptyTime() {
@@ -748,18 +_,46 @@
@@ -756,18 +_,46 @@
}
}
@ -508,7 +508,7 @@
}
private void tickPassenger(Entity ridingEntity, Entity passengerEntity) {
@@ -768,10 +_,12 @@
@@ -776,10 +_,12 @@
} else if (passengerEntity instanceof Player || this.entityTickList.contains(passengerEntity)) {
passengerEntity.setOldPosAndRot();
passengerEntity.tickCount++;
@ -521,7 +521,7 @@
profilerFiller.pop();
for (Entity entity : passengerEntity.getPassengers()) {
@@ -788,6 +_,7 @@
@@ -810,6 +_,7 @@
public void save(@Nullable ProgressListener progress, boolean flush, boolean skipSave) {
ServerChunkCache chunkSource = this.getChunkSource();
if (!skipSave) {
@ -529,7 +529,7 @@
if (progress != null) {
progress.progressStartNoAbort(Component.translatable("menu.savingLevel"));
}
@@ -804,11 +_,19 @@
@@ -826,11 +_,19 @@
this.entityManager.autoSave();
}
}
@ -550,7 +550,7 @@
}
DimensionDataStorage dataStorage = this.getChunkSource().getDataStorage();
@@ -873,18 +_,40 @@
@@ -895,18 +_,40 @@
@Override
public boolean addFreshEntity(Entity entity) {
@ -594,7 +594,7 @@
}
}
@@ -907,40 +_,119 @@
@@ -929,40 +_,119 @@
this.entityManager.addNewEntity(player);
}
@ -719,7 +719,7 @@
if (d * d + d1 * d1 + d2 * d2 < 1024.0) {
serverPlayer.connection.send(new ClientboundBlockDestructionPacket(breakerId, pos, progress));
}
@@ -1015,7 +_,7 @@
@@ -1037,7 +_,7 @@
pos.getX(),
pos.getY(),
pos.getZ(),
@ -728,7 +728,7 @@
this.dimension(),
new ClientboundLevelEventPacket(type, pos, data, false)
);
@@ -1027,6 +_,11 @@
@@ -1049,6 +_,11 @@
@Override
public void gameEvent(Holder<GameEvent> gameEvent, Vec3 pos, GameEvent.Context context) {
@ -740,7 +740,7 @@
this.gameEventDispatcher.post(gameEvent, pos, context);
}
@@ -1039,17 +_,28 @@
@@ -1061,17 +_,28 @@
this.getChunkSource().blockChanged(pos);
this.pathTypesByPosCache.invalidate(pos);
@ -769,7 +769,7 @@
try {
this.isUpdatingNavigations = true;
@@ -1061,15 +_,23 @@
@@ -1083,15 +_,23 @@
this.isUpdatingNavigations = false;
}
}
@ -793,7 +793,7 @@
this.neighborUpdater.updateNeighborsAtExceptFromFacing(pos, block, null, orientation);
}
@@ -1118,6 +_,42 @@
@@ -1140,6 +_,42 @@
ParticleOptions largeExplosionParticles,
Holder<SoundEvent> explosionSound
) {
@ -836,7 +836,7 @@
Explosion.BlockInteraction blockInteraction = switch (explosionInteraction) {
case NONE -> Explosion.BlockInteraction.KEEP;
case BLOCK -> this.getDestroyType(GameRules.RULE_BLOCK_EXPLOSION_DROP_DECAY);
@@ -1126,10 +_,17 @@
@@ -1148,10 +_,17 @@
: Explosion.BlockInteraction.KEEP;
case TNT -> this.getDestroyType(GameRules.RULE_TNT_EXPLOSION_DROP_DECAY);
case TRIGGER -> Explosion.BlockInteraction.TRIGGER_BLOCK;
@ -854,7 +854,7 @@
ParticleOptions particleOptions = serverExplosion.isSmall() ? smallExplosionParticles : largeExplosionParticles;
for (ServerPlayer serverPlayer : this.players) {
@@ -1138,6 +_,8 @@
@@ -1160,6 +_,8 @@
serverPlayer.connection.send(new ClientboundExplodePacket(vec3, optional, particleOptions, explosionSound));
}
}
@ -863,7 +863,7 @@
}
private Explosion.BlockInteraction getDestroyType(GameRules.Key<GameRules.BooleanValue> decayGameRule) {
@@ -1208,7 +_,7 @@
@@ -1230,7 +_,7 @@
public <T extends ParticleOptions> int sendParticles(
T type, double posX, double posY, double posZ, int particleCount, double xOffset, double yOffset, double zOffset, double speed
) {
@ -872,7 +872,7 @@
}
public <T extends ParticleOptions> int sendParticles(
@@ -1224,13 +_,49 @@
@@ -1246,13 +_,49 @@
double zOffset,
double speed
) {
@ -924,7 +924,7 @@
if (this.sendParticles(serverPlayer, overrideLimiter, posX, posY, posZ, clientboundLevelParticlesPacket)) {
i++;
}
@@ -1293,7 +_,7 @@
@@ -1315,7 +_,7 @@
@Nullable
public BlockPos findNearestMapStructure(TagKey<Structure> structureTag, BlockPos pos, int radius, boolean skipExistingChunks) {
@ -933,7 +933,7 @@
return null;
} else {
Optional<HolderSet.Named<Structure>> optional = this.registryAccess().lookupOrThrow(Registries.STRUCTURE).get(structureTag);
@@ -1340,10 +_,36 @@
@@ -1362,10 +_,36 @@
@Nullable
@Override
public MapItemSavedData getMapData(MapId mapId) {
@ -971,7 +971,7 @@
this.getServer().overworld().getDataStorage().set(MapItemSavedData.type(mapId), data);
}
@@ -1355,17 +_,27 @@
@@ -1377,17 +_,27 @@
BlockPos spawnPos = this.levelData.getSpawnPos();
float spawnAngle = this.levelData.getSpawnAngle();
if (!spawnPos.equals(pos) || spawnAngle != angle) {
@ -1001,7 +1001,7 @@
}
this.lastSpawnChunkRadius = i;
@@ -1400,6 +_,11 @@
@@ -1422,6 +_,11 @@
DebugPackets.sendPoiRemovedPacket(this, blockPos);
}));
optional1.ifPresent(holder -> this.getServer().execute(() -> {
@ -1013,7 +1013,7 @@
this.getPoiManager().add(blockPos, (Holder<PoiType>)holder);
DebugPackets.sendPoiAddedPacket(this, blockPos);
}));
@@ -1552,12 +_,12 @@
@@ -1574,12 +_,12 @@
}
public boolean isFlat() {
@ -1028,7 +1028,7 @@
}
@Nullable
@@ -1608,6 +_,7 @@
@@ -1630,6 +_,7 @@
@Override
public LevelEntityGetter<Entity> getEntities() {
@ -1036,7 +1036,7 @@
return this.entityManager.getEntityGetter();
}
@@ -1697,6 +_,28 @@
@@ -1736,6 +_,28 @@
return this.serverLevelData.getGameRules();
}
@ -1065,15 +1065,15 @@
@Override
public CrashReportCategory fillReportDetails(CrashReport report) {
CrashReportCategory crashReportCategory = super.fillReportDetails(report);
@@ -1712,6 +_,7 @@
final class EntityCallbacks implements LevelCallback<Entity> {
@Override
public void onCreated(Entity entity) {
@@ -1754,6 +_,7 @@
if (entity instanceof WaypointTransmitter waypointTransmitter && waypointTransmitter.isTransmittingWaypoint()) {
ServerLevel.this.getWaypointManager().trackWaypoint(waypointTransmitter);
}
+ entity.setOldPosAndRot(); // Paper - update old pos / rot for new entities as it will default to Vec3.ZERO
}
@Override
@@ -1721,24 +_,32 @@
@@ -1767,17 +_,24 @@
@Override
public void onTickingStart(Entity entity) {
@ -1086,8 +1086,7 @@
ServerLevel.this.entityTickList.remove(entity);
+ // Paper start - Reset pearls when they stop being ticked
+ if (ServerLevel.this.paperConfig().fixes.disableUnloadedChunkEnderpearlExploit && ServerLevel.this.paperConfig().misc.legacyEnderPearlBehavior && entity instanceof net.minecraft.world.entity.projectile.ThrownEnderpearl pearl) {
+ pearl.cachedOwner = null;
+ pearl.ownerUUID = null;
+ pearl.setOwner(null);
+ }
+ // Paper end - Reset pearls when they stop being ticked
}
@ -1099,7 +1098,8 @@
+ // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.add(serverPlayer);
ServerLevel.this.updateSleepingPlayerList();
if (serverPlayer.isReceivingWaypoints()) {
@@ -1792,7 +_,7 @@
}
if (entity instanceof Mob mob) {
@ -1108,7 +1108,7 @@
String string = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde(
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
@@ -1755,10 +_,52 @@
@@ -1809,10 +_,52 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
@ -1161,7 +1161,7 @@
ServerLevel.this.getChunkSource().removeEntity(entity);
if (entity instanceof ServerPlayer serverPlayer) {
ServerLevel.this.players.remove(serverPlayer);
@@ -1766,7 +_,7 @@
@@ -1821,7 +_,7 @@
}
if (entity instanceof Mob mob) {
@ -1170,7 +1170,7 @@
String string = "onTrackingStart called during navigation iteration";
Util.logAndPauseIfInIde(
"onTrackingStart called during navigation iteration", new IllegalStateException("onTrackingStart called during navigation iteration")
@@ -1783,6 +_,15 @@
@@ -1838,6 +_,15 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);
@ -1186,7 +1186,7 @@
}
@Override
@@ -1790,4 +_,24 @@
@@ -1845,4 +_,24 @@
entity.updateDynamicGameEventListener(DynamicGameEventListener::move);
}
}

View File

@ -1,14 +1,6 @@
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -65,7 +_,6 @@
import net.minecraft.network.protocol.game.ClientboundHurtAnimationPacket;
import net.minecraft.network.protocol.game.ClientboundMerchantOffersPacket;
import net.minecraft.network.protocol.game.ClientboundOpenBookPacket;
-import net.minecraft.network.protocol.game.ClientboundOpenScreenPacket;
import net.minecraft.network.protocol.game.ClientboundOpenSignEditorPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket;
import net.minecraft.network.protocol.game.ClientboundPlayerCombatEndPacket;
@@ -235,7 +_,8 @@
@@ -245,7 +_,8 @@
private int levitationStartTime;
private boolean disconnected;
private int requestedViewDistance = 2;
@ -18,7 +10,7 @@
@Nullable
private Vec3 startingToFallPosition;
@Nullable
@@ -281,6 +_,13 @@
@@ -291,6 +_,13 @@
}
}
@ -32,7 +24,7 @@
@Override
public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) {
ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(container.containerId, container.incrementStateId(), slot, itemStack));
@@ -316,6 +_,32 @@
@@ -326,6 +_,32 @@
}
}
@ -65,7 +57,7 @@
@Override
public void dataChanged(AbstractContainerMenu containerMenu, int dataSlotIndex, int value) {
}
@@ -344,9 +_,43 @@
@@ -354,9 +_,43 @@
public void sendSystemMessage(Component component) {
ServerPlayer.this.sendSystemMessage(component);
}
@ -108,22 +100,20 @@
+ public @Nullable org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - Add API for quit reason; there are a lot of changes to do if we change all methods leading to the event
public ServerPlayer(MinecraftServer server, ServerLevel level, GameProfile gameProfile, ClientInformation clientInformation) {
super(level, level.getSharedSpawnPos(), level.getSharedSpawnAngle(), gameProfile);
@@ -356,16 +_,22 @@
super(level, gameProfile);
@@ -366,15 +_,21 @@
this.server = server;
this.stats = server.getPlayerList().getPlayerStats(this);
this.advancements = server.getPlayerList().getPlayerAdvancements(this);
- this.snapTo(this.adjustSpawnLocation(level, level.getSharedSpawnPos()).getBottomCenter(), 0.0F, 0.0F);
- this.updateOptions(clientInformation);
+ // this.snapTo(this.adjustSpawnLocation(level, level.getSharedSpawnPos()).getBottomCenter(), 0.0F, 0.0F); // Paper - Don't move existing players to world spawn
+ this.updateOptionsNoEvents(clientInformation); // Paper - don't call options events on login
this.object = null;
+
+ // CraftBukkit start
+ this.displayName = this.getScoreboardName();
+ this.adventure$displayName = net.kyori.adventure.text.Component.text(this.getScoreboardName()); // Paper
+ this.bukkitPickUpLoot = true;
+ this.maxHealthCache = this.getMaxHealth();
+ // CraftBukkit end
}
@Override
@ -135,22 +125,22 @@
int max = Math.max(0, this.server.getSpawnRadius(level));
int floor = Mth.floor(level.getWorldBorder().getDistanceToBorder(pos.getX(), pos.getZ()));
if (floor < max) {
@@ -436,6 +_,7 @@
this.enteredNetherPosition = compound.read("entered_nether_pos", Vec3.CODEC).orElse(null);
this.seenCredits = compound.getBooleanOr("seenCredits", false);
this.recipeBook.fromNbt(compound.getCompoundOrEmpty("recipeBook"), key -> this.server.getRecipeManager().byKey(key).isPresent());
+ this.getBukkitEntity().readExtraData(compound); // CraftBukkit
@@ -446,6 +_,7 @@
this.seenCredits = input.getBooleanOr("seenCredits", false);
input.read("recipeBook", ServerRecipeBook.Packed.CODEC)
.ifPresent(packed -> this.recipeBook.loadUntrusted(packed, key -> this.server.getRecipeManager().byKey(key).isPresent()));
+ this.getBukkitEntity().readExtraData(input); // CraftBukkit
if (this.isSleeping()) {
this.stopSleeping();
}
@@ -459,12 +_,24 @@
compound.putBoolean("spawn_extra_particles_on_fall", this.spawnExtraParticlesOnFall);
compound.storeNullable("raid_omen_position", BlockPos.CODEC, this.raidOmenPosition);
this.saveEnderPearls(compound);
+ this.getBukkitEntity().setExtraData(compound); // CraftBukkit
@@ -469,12 +_,24 @@
output.putBoolean("spawn_extra_particles_on_fall", this.spawnExtraParticlesOnFall);
output.storeNullable("raid_omen_position", BlockPos.CODEC, this.raidOmenPosition);
this.saveEnderPearls(output);
+ this.getBukkitEntity().setExtraData(output); // CraftBukkit
}
private void saveParentVehicle(CompoundTag tag) {
private void saveParentVehicle(ValueOutput output) {
Entity rootVehicle = this.getRootVehicle();
Entity vehicle = this.getVehicle();
- if (vehicle != null && rootVehicle != this && rootVehicle.hasExactlyOnePlayerPassenger()) {
@ -166,19 +156,19 @@
+ }
+ if (persistVehicle && vehicle != null && rootVehicle != this && rootVehicle.hasExactlyOnePlayerPassenger() && !rootVehicle.isRemoved()) { // Paper - Ensure valid vehicle status
+ // CraftBukkit end
CompoundTag compoundTag = new CompoundTag();
CompoundTag compoundTag1 = new CompoundTag();
rootVehicle.save(compoundTag1);
@@ -479,7 +_,7 @@
if (!compound.isEmpty()) {
ServerLevel serverLevel = this.serverLevel();
ValueOutput valueOutput = output.child("RootVehicle");
valueOutput.store("Attach", UUIDUtil.CODEC, vehicle.getUUID());
rootVehicle.save(valueOutput.child("Entity"));
@@ -486,7 +_,7 @@
if (!optional.isEmpty()) {
ServerLevel serverLevel = this.level();
Entity entity = EntityType.loadEntityRecursive(
- compound.get().getCompoundOrEmpty("Entity"), serverLevel, EntitySpawnReason.LOAD, entity2 -> !serverLevel.addWithUUID(entity2) ? null : entity2
+ compound.get().getCompoundOrEmpty("Entity"), serverLevel, EntitySpawnReason.LOAD, entity2 -> !serverLevel.addWithUUID(entity2, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity2 // Paper - Entity#getEntitySpawnReason
- optional.get().childOrEmpty("Entity"), serverLevel, EntitySpawnReason.LOAD, entity2 -> !serverLevel.addWithUUID(entity2) ? null : entity2
+ optional.get().childOrEmpty("Entity"), serverLevel, EntitySpawnReason.LOAD, entity2 -> !serverLevel.addWithUUID(entity2, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.MOUNT) ? null : entity2 // Paper - Entity#getEntitySpawnReason
);
if (entity != null) {
UUID uuid = compound.get().read("Attach", UUIDUtil.CODEC).orElse(null);
@@ -496,10 +_,10 @@
UUID uuid = optional.get().read("Attach", UUIDUtil.CODEC).orElse(null);
@@ -503,10 +_,10 @@
if (!this.isPassenger()) {
LOGGER.warn("Couldn't reattach entity to player");
@ -191,15 +181,15 @@
}
}
}
@@ -511,6 +_,7 @@
ListTag listTag = new ListTag();
@@ -518,6 +_,7 @@
ValueOutput.ValueOutputList valueOutputList = output.childrenList("ender_pearls");
for (ThrownEnderpearl thrownEnderpearl : this.enderPearls) {
+ if (thrownEnderpearl.level().paperConfig().misc.legacyEnderPearlBehavior) continue; // Paper - Allow using old ender pearl behavior
if (thrownEnderpearl.isRemoved()) {
LOGGER.warn("Trying to save removed ender pearl, skipping");
} else {
@@ -546,6 +_,16 @@
@@ -550,6 +_,16 @@
}
}
@ -216,7 +206,7 @@
public void setExperiencePoints(int experiencePoints) {
float f = this.getXpNeededForNextLevel();
float f1 = (f - 1.0F) / f;
@@ -603,6 +_,11 @@
@@ -607,6 +_,11 @@
@Override
public void tick() {
@ -228,7 +218,7 @@
this.tickClientLoadTimeout();
this.gameMode.tick();
this.wardenSpawnTracker.tick();
@@ -610,9 +_,14 @@
@@ -614,9 +_,14 @@
this.invulnerableTime--;
}
@ -246,7 +236,7 @@
this.containerMenu = this.inventoryMenu;
}
@@ -662,7 +_,7 @@
@@ -675,7 +_,7 @@
public void doTick() {
try {
@ -255,7 +245,7 @@
super.tick();
}
@@ -676,7 +_,7 @@
@@ -689,7 +_,7 @@
if (this.getHealth() != this.lastSentHealth
|| this.lastSentFood != this.foodData.getFoodLevel()
|| this.foodData.getSaturationLevel() == 0.0F != this.lastFoodSaturationZero) {
@ -264,7 +254,7 @@
this.lastSentHealth = this.getHealth();
this.lastSentFood = this.foodData.getFoodLevel();
this.lastFoodSaturationZero = this.foodData.getSaturationLevel() == 0.0F;
@@ -707,6 +_,12 @@
@@ -720,6 +_,12 @@
this.updateScoreForCriteria(ObjectiveCriteria.EXPERIENCE, Mth.ceil((float)this.lastRecordedExperience));
}
@ -277,7 +267,7 @@
if (this.experienceLevel != this.lastRecordedLevel) {
this.lastRecordedLevel = this.experienceLevel;
this.updateScoreForCriteria(ObjectiveCriteria.LEVEL, Mth.ceil((float)this.lastRecordedLevel));
@@ -720,6 +_,21 @@
@@ -733,6 +_,21 @@
if (this.tickCount % 20 == 0) {
CriteriaTriggers.LOCATION.trigger(this);
}
@ -299,8 +289,8 @@
} catch (Throwable var4) {
CrashReport crashReport = CrashReport.forThrowable(var4, "Ticking player");
CrashReportCategory crashReportCategory = crashReport.addCategory("Player being ticked");
@@ -744,7 +_,7 @@
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.serverLevel().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) {
@@ -757,7 +_,7 @@
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) {
if (this.tickCount % 20 == 0) {
if (this.getHealth() < this.getMaxHealth()) {
- this.heal(1.0F);
@ -308,7 +298,7 @@
}
float saturationLevel = this.foodData.getSaturationLevel();
@@ -793,15 +_,36 @@
@@ -806,15 +_,36 @@
}
private void updateScoreForCriteria(ObjectiveCriteria criteria, int points) {
@ -318,7 +308,7 @@
- @Override
- public void die(DamageSource cause) {
- this.gameEvent(GameEvent.ENTITY_DIE);
- boolean _boolean = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES);
- boolean _boolean = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES);
- if (_boolean) {
- Component deathMessage = this.getCombatTracker().getDeathMessage();
+ this.level().getCraftServer().getScoreboardManager().forAllObjectives(criteria, this, score -> score.set(points)); // CraftBukkit - Use our scores instead
@ -354,7 +344,7 @@
this.connection
.send(
new ClientboundPlayerCombatKillPacket(this.getId(), deathMessage),
@@ -818,6 +_,65 @@
@@ -831,6 +_,65 @@
}
)
);
@ -366,13 +356,13 @@
+ @Override
+ public void die(DamageSource cause) {
+ // this.gameEvent(GameEvent.ENTITY_DIE); // Paper - move below event cancellation check
+ boolean _boolean = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); final boolean showDeathMessage = _boolean; // Paper - OBFHELPER
+ boolean _boolean = this.level().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); final boolean showDeathMessage = _boolean; // Paper - OBFHELPER
+ // CraftBukkit start - fire PlayerDeathEvent
+ if (this.isRemoved()) {
+ return;
+ }
+ List<DefaultDrop> loot = new java.util.ArrayList<>(this.getInventory().getContainerSize()); // Paper - Restore vanilla drops behavior
+ boolean keepInventory = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator();
+ boolean keepInventory = this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || this.isSpectator();
+ if (!keepInventory) {
+ for (ItemStack item : this.getInventory().getContents()) {
+ if (!item.isEmpty() && !EnchantmentHelper.has(item, net.minecraft.world.item.enchantment.EnchantmentEffectComponents.PREVENT_EQUIPMENT_DROP)) {
@ -380,9 +370,9 @@
+ }
+ }
+ }
+ if (this.shouldDropLoot() && this.serverLevel().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - fix player loottables running when mob loot gamerule is false
+ if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { // Paper - fix player loottables running when mob loot gamerule is false
+ // SPIGOT-5071: manually add player loot tables (SPIGOT-5195 - ignores keepInventory rule)
+ this.dropFromLootTable(this.serverLevel(), cause, this.lastHurtByPlayerMemoryTime > 0);
+ this.dropFromLootTable(this.level(), cause, this.lastHurtByPlayerMemoryTime > 0);
+ // Paper - Restore vanilla drops behaviour; custom death loot is a noop on server player, remove.
+ loot.addAll(this.drops);
+ this.drops.clear(); // SPIGOT-5188: make sure to clear
@ -420,7 +410,7 @@
Team team = this.getTeam();
if (team == null || team.getDeathMessageVisibility() == Team.Visibility.ALWAYS) {
this.server.getPlayerList().broadcastSystemMessage(deathMessage, false);
@@ -827,7 +_,7 @@
@@ -840,7 +_,7 @@
this.server.getPlayerList().broadcastSystemToAllExceptTeam(this, deathMessage);
}
} else {
@ -429,14 +419,14 @@
}
this.removeEntitiesOnShoulder();
@@ -835,11 +_,35 @@
@@ -848,11 +_,35 @@
this.tellNeutralMobsThatIDied();
}
- if (!this.isSpectator()) {
- this.dropAllDeathLoot(this.serverLevel(), cause);
- this.dropAllDeathLoot(this.level(), cause);
+ // SPIGOT-5478 must be called manually now
+ if (event.shouldDropExperience()) this.dropExperience(this.serverLevel(), cause.getEntity()); // Paper - tie to event
+ if (event.shouldDropExperience()) this.dropExperience(this.level(), cause.getEntity()); // Paper - tie to event
+ // we clean the player's inventory after the EntityDeathEvent is called so plugins can get the exact state of the inventory.
+ if (!event.getKeepInventory()) {
+ // Paper start - PlayerDeathEvent#getItemsToKeep
@ -468,7 +458,7 @@
LivingEntity killCredit = this.getKillCredit();
if (killCredit != null) {
this.awardStat(Stats.ENTITY_KILLED_BY.get(killCredit.getType()));
@@ -872,10 +_,10 @@
@@ -885,10 +_,10 @@
public void awardKillScore(Entity entity, DamageSource damageSource) {
if (entity != this) {
super.awardKillScore(entity, damageSource);
@ -481,7 +471,7 @@
} else {
this.awardStat(Stats.MOB_KILLS);
}
@@ -891,7 +_,7 @@
@@ -904,7 +_,7 @@
if (playersTeam != null) {
int id = playersTeam.getColor().getId();
if (id >= 0 && id < crtieria.length) {
@ -490,7 +480,7 @@
}
}
}
@@ -902,9 +_,20 @@
@@ -915,9 +_,20 @@
return false;
} else {
Entity entity = damageSource.getEntity();
@ -513,7 +503,7 @@
}
}
@@ -914,23 +_,77 @@
@@ -927,23 +_,77 @@
}
private boolean isPvpAllowed() {
@ -596,8 +586,8 @@
+ // CraftBukkit end
}
public static Optional<ServerPlayer.RespawnPosAngle> findRespawnAndUseSpawnBlock(
@@ -947,10 +_,10 @@
public boolean isReceivingWaypoints() {
@@ -978,10 +_,10 @@
level.setBlock(blockPos, blockState.setValue(RespawnAnchorBlock.CHARGE, blockState.getValue(RespawnAnchorBlock.CHARGE) - 1), 3);
}
@ -610,7 +600,7 @@
} else if (!flag) {
return Optional.empty();
} else {
@@ -958,7 +_,7 @@
@@ -989,7 +_,7 @@
BlockState blockState1 = level.getBlockState(blockPos.above());
boolean isPossibleToRespawnInThis1 = blockState1.getBlock().isPossibleToRespawnInThis(blockState1);
return isPossibleToRespawnInThis && isPossibleToRespawnInThis1
@ -619,7 +609,7 @@
: Optional.empty();
}
}
@@ -976,6 +_,7 @@
@@ -1007,6 +_,7 @@
@Nullable
@Override
public ServerPlayer teleport(TeleportTransition teleportTransition) {
@ -627,10 +617,10 @@
if (this.isRemoved()) {
return null;
} else {
@@ -985,17 +_,52 @@
@@ -1016,17 +_,52 @@
ServerLevel level = teleportTransition.newLevel();
ServerLevel serverLevel = this.serverLevel();
ServerLevel serverLevel = this.level();
- ResourceKey<Level> resourceKey = serverLevel.dimension();
+ // CraftBukkit start
+ ResourceKey<net.minecraft.world.level.dimension.LevelStem> resourceKey = serverLevel.getTypeKey();
@ -640,8 +630,8 @@
+ org.bukkit.Location exit = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(absolutePosition.position(), level.getWorld(), absolutePosition.yRot(), absolutePosition.xRot());
+ org.bukkit.event.player.PlayerTeleportEvent tpEvent = new org.bukkit.event.player.PlayerTeleportEvent(this.getBukkitEntity(), enter, exit.clone(), teleportTransition.cause());
+ // Paper start - gateway-specific teleport event
+ if (this.portalProcess != null && this.portalProcess.isSamePortal(((net.minecraft.world.level.block.EndGatewayBlock) net.minecraft.world.level.block.Blocks.END_GATEWAY)) && this.serverLevel().getBlockEntity(this.portalProcess.getEntryPosition()) instanceof net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity theEndGatewayBlockEntity) {
+ tpEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(this.getBukkitEntity(), enter, exit.clone(), new org.bukkit.craftbukkit.block.CraftEndGateway(this.serverLevel().getWorld(), theEndGatewayBlockEntity));
+ if (this.portalProcess != null && this.portalProcess.isSamePortal(((net.minecraft.world.level.block.EndGatewayBlock) net.minecraft.world.level.block.Blocks.END_GATEWAY)) && this.level().getBlockEntity(this.portalProcess.getEntryPosition()) instanceof net.minecraft.world.level.block.entity.TheEndGatewayBlockEntity theEndGatewayBlockEntity) {
+ tpEvent = new com.destroystokyo.paper.event.player.PlayerTeleportEndGatewayEvent(this.getBukkitEntity(), enter, exit.clone(), new org.bukkit.craftbukkit.block.CraftEndGateway(this.level().getWorld(), theEndGatewayBlockEntity));
+ }
+ // Paper end - gateway-specific teleport event
+ org.bukkit.Bukkit.getServer().getPluginManager().callEvent(tpEvent);
@ -683,7 +673,7 @@
this.isChangingDimension = true;
LevelData levelData = level.getLevelData();
this.connection.send(new ClientboundRespawnPacket(this.createCommonSpawnInfo(level), (byte)3));
@@ -1004,16 +_,30 @@
@@ -1035,16 +_,30 @@
playerList.sendPlayerPermissionLevel(this);
serverLevel.removePlayerImmediately(this, Entity.RemovalReason.CHANGED_DIMENSION);
this.unsetRemoved();
@ -716,12 +706,10 @@
this.connection.resetPosition();
level.addDuringTeleport(this);
profilerFiller.pop();
@@ -1027,10 +_,39 @@
this.lastSentExp = -1;
@@ -1059,10 +_,37 @@
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
+
+
this.teleportSpectators(teleportTransition, serverLevel);
+ // CraftBukkit start
+ org.bukkit.event.player.PlayerChangedWorldEvent changeEvent = new org.bukkit.event.player.PlayerChangedWorldEvent(this.getBukkitEntity(), serverLevel.getWorld());
+ this.level().getCraftServer().getPluginManager().callEvent(changeEvent);
@ -756,7 +744,7 @@
@Override
public void forceSetRotation(float yRot, float xRot) {
@@ -1040,12 +_,26 @@
@@ -1072,12 +_,26 @@
public void triggerDimensionChangeTriggers(ServerLevel level) {
ResourceKey<Level> resourceKey = level.dimension();
ResourceKey<Level> resourceKey1 = this.level().dimension();
@ -786,7 +774,7 @@
this.enteredNetherPosition = null;
}
}
@@ -1061,19 +_,18 @@
@@ -1093,19 +_,18 @@
this.containerMenu.broadcastChanges();
}
@ -810,7 +798,7 @@
if (this.level().isBrightOutside()) {
return Either.left(Player.BedSleepingProblem.NOT_POSSIBLE_NOW);
} else {
@@ -1092,7 +_,34 @@
@@ -1124,7 +_,34 @@
}
}
@ -846,7 +834,7 @@
this.awardStat(Stats.SLEEP_IN_BED);
CriteriaTriggers.SLEPT_IN_BED.trigger(this);
});
@@ -1128,21 +_,29 @@
@@ -1160,21 +_,29 @@
@Override
public void stopSleepInBed(boolean wakeImmediately, boolean updateLevelForSleepingPlayers) {
@ -859,7 +847,7 @@
+ }
+ // CraftBukkit end
if (this.isSleeping()) {
this.serverLevel().getChunkSource().broadcastAndSend(this, new ClientboundAnimatePacket(this, 2));
this.level().getChunkSource().broadcastAndSend(this, new ClientboundAnimatePacket(this, 2));
}
super.stopSleepInBed(wakeImmediately, updateLevelForSleepingPlayers);
@ -879,8 +867,8 @@
}
@Override
@@ -1185,8 +_,9 @@
this.connection.send(new ClientboundOpenSignEditorPacket(signEntity.getBlockPos(), isFrontText));
@@ -1222,8 +_,9 @@
this.connection.send(new ClientboundShowDialogPacket(dialog));
}
- public void nextContainerCounter() {
@ -890,7 +878,7 @@
}
@Override
@@ -1194,12 +_,39 @@
@@ -1231,12 +_,39 @@
if (menu == null) {
return OptionalInt.empty();
} else {
@ -931,7 +919,7 @@
if (abstractContainerMenu == null) {
if (this.isSpectator()) {
this.displayClientMessage(Component.translatable("container.spectatorCantOpen").withStyle(ChatFormatting.RED), true);
@@ -1207,10 +_,14 @@
@@ -1244,10 +_,14 @@
return OptionalInt.empty();
} else {
@ -948,7 +936,7 @@
return OptionalInt.of(this.containerCounter);
}
}
@@ -1223,14 +_,25 @@
@@ -1260,14 +_,25 @@
@Override
public void openHorseInventory(AbstractHorse horse, Container inventory) {
@ -977,7 +965,7 @@
this.initMenu(this.containerMenu);
}
@@ -1252,10 +_,30 @@
@@ -1289,10 +_,30 @@
@Override
public void closeContainer() {
@ -1008,7 +996,7 @@
@Override
public void doCloseContainer() {
this.containerMenu.removed(this);
@@ -1278,19 +_,19 @@
@@ -1315,19 +_,19 @@
int rounded = Math.round((float)Math.sqrt(dx * dx + dy * dy + dz * dz) * 100.0F);
if (rounded > 0) {
this.awardStat(Stats.SWIM_ONE_CM, rounded);
@ -1031,7 +1019,7 @@
}
} else if (this.onClimbable()) {
if (dy > 0.0) {
@@ -1301,13 +_,13 @@
@@ -1338,13 +_,13 @@
if (rounded > 0) {
if (this.isSprinting()) {
this.awardStat(Stats.SPRINT_ONE_CM, rounded);
@ -1048,7 +1036,7 @@
}
}
} else if (this.isFallFlying()) {
@@ -1347,13 +_,13 @@
@@ -1386,13 +_,13 @@
@Override
public void awardStat(Stat<?> stat, int amount) {
this.stats.increment(this, stat, amount);
@ -1064,7 +1052,7 @@
}
@Override
@@ -1384,9 +_,9 @@
@@ -1423,9 +_,9 @@
super.jumpFromGround();
this.awardStat(Stats.JUMP);
if (this.isSprinting()) {
@ -1076,7 +1064,7 @@
}
}
@@ -1399,6 +_,13 @@
@@ -1438,6 +_,13 @@
public void disconnect() {
this.disconnected = true;
this.ejectPassengers();
@ -1090,7 +1078,7 @@
if (this.isSleeping()) {
this.stopSleepInBed(true, false);
}
@@ -1410,6 +_,7 @@
@@ -1449,6 +_,7 @@
public void resetSentInfo() {
this.lastSentHealth = -1.0E8F;
@ -1098,7 +1086,7 @@
}
@Override
@@ -1444,12 +_,12 @@
@@ -1483,12 +_,12 @@
this.onUpdateAbilities();
if (keepEverything) {
this.getAttributes().assignBaseValues(that.getAttributes());
@ -1113,16 +1101,16 @@
}
this.getInventory().replaceWith(that.getInventory());
@@ -1460,7 +_,7 @@
@@ -1499,7 +_,7 @@
this.portalProcess = that.portalProcess;
} else {
this.getAttributes().assignBaseValues(that.getAttributes());
- this.setHealth(this.getMaxHealth());
+ // this.setHealth(this.getMaxHealth()); // CraftBukkit
if (this.serverLevel().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || that.isSpectator()) {
if (this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) || that.isSpectator()) {
this.getInventory().replaceWith(that.getInventory());
this.experienceLevel = that.experienceLevel;
@@ -1476,7 +_,7 @@
@@ -1515,7 +_,7 @@
this.lastSentExp = -1;
this.lastSentHealth = -1.0F;
this.lastSentFood = -1;
@ -1131,7 +1119,7 @@
this.seenCredits = that.seenCredits;
this.enteredNetherPosition = that.enteredNetherPosition;
this.chunkTrackingView = that.chunkTrackingView;
@@ -1529,7 +_,7 @@
@@ -1568,7 +_,7 @@
}
@Override
@ -1140,7 +1128,7 @@
if (this.isSleeping()) {
this.stopSleepInBed(true, true);
}
@@ -1538,7 +_,7 @@
@@ -1577,7 +_,7 @@
this.setCamera(this);
}
@ -1149,7 +1137,7 @@
if (flag) {
this.setYHeadRot(relativeMovements.contains(Relative.Y_ROT) ? this.getYHeadRot() + yaw : yaw);
}
@@ -1575,9 +_,17 @@
@@ -1615,9 +_,17 @@
}
public boolean setGameMode(GameType gameMode) {
@ -1169,7 +1157,7 @@
} else {
this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, gameMode.getId()));
if (gameMode == GameType.SPECTATOR) {
@@ -1593,7 +_,7 @@
@@ -1633,7 +_,7 @@
this.onUpdateAbilities();
this.updateEffectVisibility();
@ -1178,7 +1166,7 @@
}
}
@@ -1649,8 +_,13 @@
@@ -1689,8 +_,13 @@
}
public void sendChatMessage(OutgoingChatMessage message, boolean filtered, ChatType.Bound boundType) {
@ -1193,7 +1181,7 @@
}
}
@@ -1661,7 +_,42 @@
@@ -1701,7 +_,42 @@
}
public void updateOptions(ClientInformation clientInformation) {
@ -1236,7 +1224,7 @@
this.requestedViewDistance = clientInformation.viewDistance();
this.chatVisibility = clientInformation.chatVisibility();
this.canChatColor = clientInformation.chatColors();
@@ -1747,8 +_,23 @@
@@ -1787,8 +_,23 @@
Entity camera = this.getCamera();
this.camera = (Entity)(entityToSpectate == null ? this : entityToSpectate);
if (camera != this.camera) {
@ -1261,7 +1249,7 @@
}
if (entityToSpectate != null) {
@@ -1782,11 +_,11 @@
@@ -1822,11 +_,11 @@
@Nullable
public Component getTabListDisplayName() {
@ -1275,7 +1263,7 @@
}
@Override
@@ -1817,11 +_,56 @@
@@ -1857,11 +_,56 @@
}
public void setRespawnPosition(@Nullable ServerPlayer.RespawnConfig respawnConfig, boolean displayInChat) {
@ -1334,7 +1322,7 @@
}
public SectionPos getLastSectionPos() {
@@ -1851,16 +_,23 @@
@@ -1891,16 +_,23 @@
}
@Override
@ -1362,24 +1350,24 @@
return itemEntity;
}
@@ -1888,6 +_,16 @@
@@ -1928,6 +_,16 @@
}
public void loadGameTypes(@Nullable CompoundTag tag) {
public void loadGameTypes(@Nullable ValueInput input) {
+ // Paper start - Expand PlayerGameModeChangeEvent
+ if (this.server.getForcedGameType() != null && this.server.getForcedGameType() != readPlayerMode(tag, "playerGameType")) {
+ if (this.server.getForcedGameType() != null && this.server.getForcedGameType() != readPlayerMode(input, "playerGameType")) {
+ if (new org.bukkit.event.player.PlayerGameModeChangeEvent(this.getBukkitEntity(), org.bukkit.GameMode.getByValue(this.server.getDefaultGameType().getId()), org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null).callEvent()) {
+ this.gameMode.setGameModeForPlayer(this.server.getForcedGameType(), GameType.DEFAULT_MODE);
+ } else {
+ this.gameMode.setGameModeForPlayer(readPlayerMode(tag,"playerGameType"), readPlayerMode(tag, "previousPlayerGameType"));
+ this.gameMode.setGameModeForPlayer(readPlayerMode(input, "playerGameType"), readPlayerMode(input, "previousPlayerGameType"));
+ }
+ return;
+ }
+ // Paper end - Expand PlayerGameModeChangeEvent
this.gameMode
.setGameModeForPlayer(this.calculateGameModeForNewPlayer(readPlayerMode(tag, "playerGameType")), readPlayerMode(tag, "previousPlayerGameType"));
.setGameModeForPlayer(this.calculateGameModeForNewPlayer(readPlayerMode(input, "playerGameType")), readPlayerMode(input, "previousPlayerGameType"));
}
@@ -1989,8 +_,14 @@
@@ -2029,8 +_,14 @@
@Override
public void removeVehicle() {
@ -1395,7 +1383,7 @@
if (vehicle instanceof LivingEntity livingEntity) {
for (MobEffectInstance mobEffectInstance : livingEntity.getActiveEffects()) {
this.connection.send(new ClientboundRemoveMobEffectPacket(vehicle.getId(), mobEffectInstance.getEffect()));
@@ -2089,7 +_,7 @@
@@ -2129,7 +_,7 @@
}
public static long placeEnderPearlTicket(ServerLevel level, ChunkPos pos) {
@ -1404,7 +1392,7 @@
return TicketType.ENDER_PEARL.timeout();
}
@@ -2113,9 +_,11 @@
@@ -2153,9 +_,11 @@
}
}
@ -1419,7 +1407,7 @@
}
private static float calculateLookAtYaw(Vec3 position, BlockPos towardsPos) {
@@ -2123,4 +_,143 @@
@@ -2163,4 +_,143 @@
return (float)Mth.wrapDegrees(Mth.atan2(vec3.z, vec3.x) * 180.0F / (float)Math.PI - 90.0);
}
}

View File

@ -9,7 +9,7 @@
public ServerPlayerGameMode(ServerPlayer player) {
this.player = player;
this.level = player.serverLevel();
this.level = player.level();
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper
@ -40,8 +40,8 @@
+ // CraftBukkit end
+ this.setGameModeForPlayer(gameModeForPlayer, this.gameModeForPlayer); // Paper - Fix MC-259571
this.player.onUpdateAbilities();
this.player
.server
this.level
.getServer()
.getPlayerList()
- .broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player));
+ .broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -27,30 +_,67 @@
@@ -29,30 +_,67 @@
import net.minecraft.util.profiling.Profiler;
import org.slf4j.Logger;
@ -73,7 +73,7 @@
private void close() {
if (!this.closed) {
@@ -61,6 +_,12 @@
@@ -63,6 +_,12 @@
@Override
public void onDisconnect(DisconnectionDetails details) {
@ -86,7 +86,7 @@
if (this.isSingleplayerOwner()) {
LOGGER.info("Stopping singleplayer server as player logged out");
this.server.halt(false);
@@ -80,7 +_,7 @@
@@ -82,7 +_,7 @@
this.latency = (this.latency * 3 + i) / 4;
this.keepAlivePending = false;
} else if (!this.isSingleplayerOwner()) {
@ -95,7 +95,7 @@
}
}
@@ -88,30 +_,123 @@
@@ -90,9 +_,73 @@
public void handlePong(ServerboundPongPacket packet) {
}
@ -114,7 +114,7 @@
+ return;
+ }
+
+ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
+ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+
+ final net.minecraft.resources.ResourceLocation identifier = packet.payload().type().id();
+ final byte[] data = discardedPayload.data();
@ -169,7 +169,8 @@
+ // Paper end
@Override
public void handleResourcePackResponse(ServerboundResourcePackPacket packet) {
public void handleCustomClickAction(ServerboundCustomClickActionPacket packet) {
@@ -105,21 +_,50 @@
PacketUtils.ensureRunningOnSameThread(packet, this, this.server);
if (packet.action() == ServerboundResourcePackPacket.Action.DECLINED && this.server.isResourcePackRequired()) {
LOGGER.info("Disconnecting {} due to resource pack {} rejection", this.playerProfile().getName(), packet.id());
@ -225,7 +226,7 @@
} else if (this.checkIfClosed(millis)) {
this.keepAlivePending = true;
this.keepAliveTime = millis;
@@ -126,7 +_,7 @@
@@ -134,7 +_,7 @@
private boolean checkIfClosed(long time) {
if (this.closed) {
if (time - this.closedListenerTime >= 15000L) {
@ -234,10 +235,10 @@
}
return false;
@@ -149,6 +_,13 @@
@@ -157,6 +_,13 @@
}
public void send(Packet<?> packet, @Nullable PacketSendListener listener) {
public void send(Packet<?> packet, @Nullable ChannelFutureListener channelFutureListener) {
+ // CraftBukkit start
+ if (packet == null || this.processedDisconnect) { // Spigot
+ return;
@ -248,7 +249,7 @@
if (packet.isTerminal()) {
this.close();
}
@@ -165,19 +_,115 @@
@@ -173,19 +_,115 @@
}
}

View File

@ -46,7 +46,7 @@
}
@Override
@@ -139,16 +_,21 @@
@@ -139,16 +_,22 @@
return;
}
@ -57,9 +57,10 @@
return;
}
- ServerPlayer playerForLogin = playerList.getPlayerForLogin(this.gameProfile, this.clientInformation);
+ ServerPlayer playerForLogin = playerList.getPlayerForLogin(this.gameProfile, this.clientInformation, this.player); // CraftBukkit
playerList.placeNewPlayer(this.connection, playerForLogin, this.createCookie(this.clientInformation));
- ServerPlayer serverPlayer = new ServerPlayer(this.server, this.server.overworld(), this.gameProfile, this.clientInformation);
+ ServerPlayer serverPlayer = this.player; // Paper
+ this.player.updateOptions(this.clientInformation); // Paper - Of course, we reuse the player
playerList.placeNewPlayer(this.connection, serverPlayer, this.createCookie(this.clientInformation));
} catch (Exception var5) {
LOGGER.error("Couldn't place player in world", (Throwable)var5);
+ // Paper start - Debugging

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -204,6 +_,39 @@
@@ -208,6 +_,38 @@
import net.minecraft.world.phys.shapes.VoxelShape;
import org.slf4j.Logger;
@ -33,14 +33,13 @@
+import org.bukkit.event.player.PlayerSwapHandItemsEvent;
+import org.bukkit.event.player.PlayerTeleportEvent;
+import org.bukkit.event.player.PlayerToggleFlightEvent;
+import org.bukkit.event.player.PlayerToggleSneakEvent;
+import org.bukkit.event.player.PlayerToggleSprintEvent;
+// CraftBukkit end
+
public class ServerGamePacketListenerImpl
extends ServerCommonPacketListenerImpl
implements GameProtocols.Context,
@@ -222,7 +_,9 @@
@@ -226,7 +_,9 @@
private int tickCount;
private int ackBlockChangesUpTo = -1;
private final TickThrottler chatSpamThrottler = new TickThrottler(20, 200);
@ -50,7 +49,7 @@
private double firstGoodX;
private double firstGoodY;
private double firstGoodZ;
@@ -248,23 +_,42 @@
@@ -252,23 +_,42 @@
private int receivedMovePacketCount;
private int knownMovePacketCount;
private boolean receivedMovementThisTick;
@ -95,7 +94,7 @@
}
@Override
@@ -284,8 +_,8 @@
@@ -288,8 +_,8 @@
this.knownMovePacketCount = this.receivedMovePacketCount;
if (this.clientIsFloating && !this.player.isSleeping() && !this.player.isPassenger() && !this.player.isDeadOrDying()) {
if (++this.aboveGroundTickCount > this.getMaximumFlyingTicks(this.player)) {
@ -106,7 +105,7 @@
return;
}
} else {
@@ -303,8 +_,8 @@
@@ -307,8 +_,8 @@
this.vehicleLastGoodZ = this.lastVehicle.getZ();
if (this.clientVehicleIsFloating && this.lastVehicle.getControllingPassenger() == this.player) {
if (++this.aboveGroundVehicleTickCount > this.getMaximumFlyingTicks(this.lastVehicle)) {
@ -117,7 +116,7 @@
return;
}
} else {
@@ -320,11 +_,20 @@
@@ -324,11 +_,20 @@
this.keepConnectionAlive();
this.chatSpamThrottler.tick();
this.dropSpamThrottler.tick();
@ -141,22 +140,49 @@
}
private int getMaximumFlyingTicks(Entity entity) {
@@ -384,6 +_,12 @@
@@ -388,11 +_,37 @@
@Override
public void handlePlayerInput(ServerboundPlayerInputPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ // CraftBukkit start
+ if (!packet.input().equals(this.player.getLastClientInput())) {
+ PlayerInputEvent event = new PlayerInputEvent(this.player.getBukkitEntity(), new org.bukkit.craftbukkit.CraftInput(packet.input()));
+ this.cserver.getPluginManager().callEvent(event);
+ }
+ // CraftBukkit end
+ // Paper start - PlayerToggleSneakEvent
+ net.minecraft.world.entity.player.Input lastInput = this.player.getLastClientInput();
+ boolean shiftKeyDown = packet.input().shift();
+ if (lastInput.shift() != packet.input().shift()) {
+ // Has sneak changed
+ org.bukkit.event.player.PlayerToggleSneakEvent event = new org.bukkit.event.player.PlayerToggleSneakEvent(this.getCraftPlayer(), packet.input().shift());
+ this.cserver.getPluginManager().callEvent(event);
+
+ // Technically the player input and the flag is desynced, but this is previous behavior.. so should be fine?
+ if (event.isCancelled()) {
+ shiftKeyDown = this.player.isShiftKeyDown();
+ }
+ }
+ // Paper end - PlayerToggleSneakEvent
this.player.setLastClientInput(packet.input());
if (this.player.hasClientLoaded()) {
this.player.resetLastActionTime();
- this.player.setShiftKeyDown(packet.input().shift());
- }
+ this.player.setShiftKeyDown(shiftKeyDown); // Paper
+ }
+ // Paper start - Add option to make parrots stay
+ if (packet.input().shift() && this.player.level().paperConfig().entities.behavior.parrotsAreUnaffectedByPlayerMovement) {
+ this.player.removeEntitiesOnShoulder();
+ }
+ // Paper end - Add option to make parrots stay
+
}
@@ -403,17 +_,29 @@
private static boolean containsInvalidValues(double x, double y, double z, float yRot, float xRot) {
@@ -411,17 +_,29 @@
public void handleMoveVehicle(ServerboundMoveVehiclePacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
if (containsInvalidValues(packet.position().x(), packet.position().y(), packet.position().z(), packet.yRot(), packet.xRot())) {
- this.disconnect(Component.translatable("multiplayer.disconnect.invalid_vehicle_movement"));
+ this.disconnect(Component.translatable("multiplayer.disconnect.invalid_vehicle_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_VEHICLE_MOVEMENT); // Paper - kick event cause
@ -168,7 +194,7 @@
+ }
+ // Paper end - Don't allow vehicle movement from players while teleporting
if (rootVehicle != this.player && rootVehicle.getControllingPassenger() == this.player && rootVehicle == this.lastVehicle) {
ServerLevel serverLevel = this.player.serverLevel();
ServerLevel serverLevel = this.player.level();
+ // CraftBukkit - store current player position
+ double prevX = this.player.getX();
+ double prevY = this.player.getY();
@ -188,7 +214,7 @@
float f = Mth.wrapDegrees(packet.yRot());
float f1 = Mth.wrapDegrees(packet.xRot());
double d3 = d - this.vehicleFirstGoodX;
@@ -421,7 +_,52 @@
@@ -429,7 +_,52 @@
double d5 = d2 - this.vehicleFirstGoodZ;
double d6 = rootVehicle.getDeltaMovement().lengthSqr();
double d7 = d3 * d3 + d4 * d4 + d5 * d5;
@ -242,48 +268,34 @@
LOGGER.warn(
"{} (vehicle of {}) moved too quickly! {},{},{}", rootVehicle.getName().getString(), this.player.getName().getString(), d3, d4, d5
);
@@ -430,15 +_,16 @@
@@ -438,9 +_,9 @@
}
boolean flag = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625));
AABB boundingBox = rootVehicle.getBoundingBox();
- d3 = d - this.vehicleLastGoodX;
- d4 = d1 - this.vehicleLastGoodY;
- d5 = d2 - this.vehicleLastGoodZ;
+ d3 = d - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above
+ d4 = d1 - this.vehicleLastGoodY; // Paper - diff on change, used for checking large move vectors above
+ d5 = d2 - this.vehicleLastGoodZ; // Paper - diff on change, used for checking large move vectors above
boolean flag1 = rootVehicle.verticalCollisionBelow;
boolean flag = rootVehicle.verticalCollisionBelow;
if (rootVehicle instanceof LivingEntity livingEntity && livingEntity.onClimbable()) {
livingEntity.resetFallDistance();
}
rootVehicle.move(MoverType.PLAYER, new Vec3(d3, d4, d5));
+ double verticalDelta = d4; // Paper - Decompile fix: lvt reassignment lost
d3 = d - rootVehicle.getX();
d4 = d1 - rootVehicle.getY();
if (d4 > -0.5 || d4 < 0.5) {
@@ -448,27 +_,80 @@
@@ -457,7 +_,7 @@
d5 = d2 - rootVehicle.getZ();
d7 = d3 * d3 + d4 * d4 + d5 * d5;
boolean flag2 = false;
boolean flag1 = false;
- if (d7 > 0.0625) {
+ if (d7 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot
flag2 = true;
flag1 = true;
LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", rootVehicle.getName().getString(), this.player.getName().getString(), Math.sqrt(d7));
}
@@ -471,6 +_,57 @@
}
rootVehicle.absSnapTo(d, d1, d2, f, f1);
+ this.player.absSnapTo(d, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
boolean flag3 = serverLevel.noCollision(rootVehicle, rootVehicle.getBoundingBox().deflate(0.0625));
if (flag && (flag2 || !flag3)) {
rootVehicle.absSnapTo(x, y, z, f, f1);
+ this.player.absSnapTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // CraftBukkit
this.send(ClientboundMoveVehiclePacket.fromEntity(rootVehicle));
rootVehicle.removeLatestMovementRecordingBatch();
return;
}
+ // CraftBukkit start - fire PlayerMoveEvent
+ // CraftBukkit start - fire PlayerMoveEvent TODO: this should be removed.
+ this.player.absSnapTo(x, y, z, this.player.getYRot(), this.player.getXRot()); // Paper - TODO: This breaks alot of stuff
+ org.bukkit.entity.Player player = this.getCraftPlayer();
+ if (!this.hasMoved) {
+ this.lastPosX = prevX;
@ -333,20 +345,11 @@
+ }
+ }
+ // CraftBukkit end
+
this.player.serverLevel().getChunkSource().move(this.player);
this.player.level().getChunkSource().move(this.player);
Vec3 vec3 = new Vec3(rootVehicle.getX() - x, rootVehicle.getY() - y, rootVehicle.getZ() - z);
this.handlePlayerKnownMovement(vec3);
rootVehicle.setOnGroundWithMovement(packet.onGround(), vec3);
rootVehicle.doCheckFallDamage(vec3.x, vec3.y, vec3.z, packet.onGround());
this.player.checkMovementStatistics(vec3.x, vec3.y, vec3.z);
- this.clientVehicleIsFloating = d4 >= -0.03125
+ this.clientVehicleIsFloating = verticalDelta >= -0.03125 // Paper - Decompile fix
&& !flag1
&& !this.server.isFlightAllowed()
&& !rootVehicle.isNoGravity()
@@ -491,12 +_,12 @@
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
@@ -501,12 +_,12 @@
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
if (packet.getId() == this.awaitingTeleport) {
if (this.awaitingPositionFromClient == null) {
- this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"));
@ -360,17 +363,17 @@
this.awaitingPositionFromClient.x,
this.awaitingPositionFromClient.y,
this.awaitingPositionFromClient.z,
@@ -508,12 +_,20 @@
@@ -518,12 +_,20 @@
this.lastGoodZ = this.awaitingPositionFromClient.z;
this.player.hasChangedDimension();
this.awaitingPositionFromClient = null;
+ this.player.serverLevel().getChunkSource().move(this.player); // CraftBukkit
+ this.player.level().getChunkSource().move(this.player); // CraftBukkit
}
}
@Override
public void handleAcceptPlayerLoad(ServerboundPlayerLoadedPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ // Paper start - PlayerLoadedWorldEvent
+ if (this.player.hasClientLoaded()) {
+ return;
@ -381,15 +384,15 @@
this.player.setClientLoaded(true);
}
@@ -535,6 +_,7 @@
@@ -545,6 +_,7 @@
@Override
public void handleRecipeBookChangeSettingsPacket(ServerboundRecipeBookChangeSettingsPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ CraftEventFactory.callRecipeBookSettingsEvent(this.player, packet.getBookType(), packet.isOpen(), packet.isFiltering()); // CraftBukkit
this.player.getRecipeBook().setBookSetting(packet.getBookType(), packet.isOpen(), packet.isFiltering());
}
@@ -550,25 +_,110 @@
@@ -560,25 +_,110 @@
}
}
@ -400,8 +403,8 @@
+
@Override
public void handleCustomCommandSuggestions(ServerboundCommandSuggestionPacket packet) {
- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
+ // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // Paper - AsyncTabCompleteEvent; run this async
- PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ // PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level()); // Paper - AsyncTabCompleteEvent; run this async
+ // CraftBukkit start
+ if (!this.tabSpamThrottler.isIncrementAndUnderThreshold() && !this.server.getPlayerList().isOp(this.player.getGameProfile()) && !this.server.isSingleplayerOwner(this.player.getGameProfile())) { // Paper - configurable tab spam limits
+ this.disconnectAsync(Component.translatable("disconnect.spam"), org.bukkit.event.player.PlayerKickEvent.Cause.SPAM); // Paper - Kick event cause // Paper - add proper async disconnect
@ -505,8 +508,8 @@
}
);
}
@@ -578,7 +_,7 @@
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
@@ -588,7 +_,7 @@
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
if (!this.server.isCommandBlockEnabled()) {
this.player.sendSystemMessage(Component.translatable("advMode.notEnabled"));
- } else if (!this.player.canUseGameMasterBlocks()) {
@ -514,8 +517,8 @@
this.player.sendSystemMessage(Component.translatable("advMode.notAllowed"));
} else {
BaseCommandBlock baseCommandBlock = null;
@@ -633,7 +_,7 @@
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
@@ -643,7 +_,7 @@
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
if (!this.server.isCommandBlockEnabled()) {
this.player.sendSystemMessage(Component.translatable("advMode.notEnabled"));
- } else if (!this.player.canUseGameMasterBlocks()) {
@ -523,7 +526,7 @@
this.player.sendSystemMessage(Component.translatable("advMode.notAllowed"));
} else {
BaseCommandBlock commandBlock = packet.getCommandBlock(this.player.level());
@@ -661,11 +_,11 @@
@@ -671,11 +_,11 @@
boolean flag = this.player.hasInfiniteMaterials() && packet.includeData();
ItemStack cloneItemStack = blockState.getCloneItemStack(serverLevel, blockPos, flag);
if (!cloneItemStack.isEmpty()) {
@ -537,7 +540,7 @@
}
}
}
@@ -689,27 +_,40 @@
@@ -702,27 +_,40 @@
if (entityOrPart != null && this.player.canInteractWithEntity(entityOrPart, 3.0)) {
ItemStack pickResult = entityOrPart.getPickResult();
if (pickResult != null && !pickResult.isEmpty()) {
@ -578,14 +581,14 @@
+ inventory.addAndPickItem(stack, event.getTargetSlot()); // Paper - Add PlayerPickItemEvent
}
this.player.connection.send(new ClientboundSetHeldSlotPacket(inventory.getSelectedSlot()));
this.send(new ClientboundSetHeldSlotPacket(inventory.getSelectedSlot()));
this.player.inventoryMenu.broadcastChanges();
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
}
}
@@ -887,6 +_,13 @@
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
@@ -900,6 +_,13 @@
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
int item = packet.getItem();
if (this.player.containerMenu instanceof MerchantMenu merchantMenu) {
+ // CraftBukkit start
@ -598,7 +601,7 @@
if (!merchantMenu.stillValid(this.player)) {
LOGGER.debug("Player {} interacted with invalid menu {}", this.player, merchantMenu);
return;
@@ -899,6 +_,51 @@
@@ -912,6 +_,51 @@
@Override
public void handleEditBook(ServerboundEditBookPacket packet) {
@ -650,7 +653,7 @@
int slot = packet.slot();
if (Inventory.isHotbarSlot(slot) || slot == 40) {
List<String> list = Lists.newArrayList();
@@ -913,10 +_,14 @@
@@ -926,10 +_,14 @@
}
private void updateBookContents(List<FilteredText> pages, int index) {
@ -666,7 +669,7 @@
}
}
@@ -930,7 +_,8 @@
@@ -943,7 +_,8 @@
DataComponents.WRITTEN_BOOK_CONTENT,
new WrittenBookContent(this.filterableFromOutgoing(title), this.player.getName().getString(), 0, list, true)
);
@ -676,14 +679,14 @@
}
}
@@ -974,27 +_,35 @@
@@ -991,27 +_,35 @@
public void handleMovePlayer(ServerboundMovePlayerPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
if (containsInvalidValues(packet.getX(0.0), packet.getY(0.0), packet.getZ(0.0), packet.getYRot(0.0F), packet.getXRot(0.0F))) {
- this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"));
+ this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause
} else {
ServerLevel serverLevel = this.player.serverLevel();
ServerLevel serverLevel = this.player.level();
- if (!this.player.wonGame) {
+ if (!this.player.wonGame && !this.player.isImmobile()) { // CraftBukkit
if (this.tickCount == 0) {
@ -706,7 +709,7 @@
+ double d2 = clampHorizontal(packet.getZ(this.player.getZ())); final double toZ = d2; // Paper - OBFHELPER
if (this.player.isPassenger()) {
this.player.absSnapTo(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1);
this.player.serverLevel().getChunkSource().move(this.player);
this.player.level().getChunkSource().move(this.player);
+ this.allowedPlayerTicks = 20; // CraftBukkit
} else {
+ // CraftBukkit - Make sure the move is valid but then reset it for plugins to modify
@ -719,7 +722,7 @@
double x = this.player.getX();
double y = this.player.getY();
double z = this.player.getZ();
@@ -1003,6 +_,16 @@
@@ -1020,6 +_,16 @@
double d5 = d2 - this.firstGoodZ;
double d6 = this.player.getDeltaMovement().lengthSqr();
double d7 = d3 * d3 + d4 * d4 + d5 * d5;
@ -736,7 +739,7 @@
if (this.player.isSleeping()) {
if (d7 > 1.0) {
this.teleport(this.player.getX(), this.player.getY(), this.player.getZ(), f, f1);
@@ -1012,36 +_,109 @@
@@ -1029,36 +_,108 @@
if (serverLevel.tickRateManager().runsNormally()) {
this.receivedMovePacketCount++;
int i = this.receivedMovePacketCount - this.knownMovePacketCount;
@ -853,11 +856,10 @@
+ return; // ... thanks Mojang for letting move calls teleport across dimensions.
+ }
+ // Paper end - prevent position desync
+ double verticalDelta = d4; // Paper - Decompile fix: lvt reassignment lost
double verticalDelta = d4;
d3 = d - this.player.getX();
d4 = d1 - this.player.getY();
if (d4 > -0.5 || d4 < 0.5) {
@@ -1050,23 +_,104 @@
@@ -1068,20 +_,100 @@
d5 = d2 - this.player.getZ();
d7 = d3 * d3 + d4 * d4 + d5 * d5;
@ -883,20 +885,20 @@
- if (this.player.noPhysics
- || this.player.isSleeping()
- || (!flag2 || !serverLevel.noCollision(this.player, boundingBox))
- && !this.isPlayerCollidingWithAnythingNew(serverLevel, boundingBox, d, d1, d2)) {
- && !this.isEntityCollidingWithAnythingNew(serverLevel, this.player, boundingBox, d, d1, d2)) {
+ } // Paper
+ }
+
+ // Paper start - Add fail move event
+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && serverLevel.noCollision(this.player, boundingBox) || this.isPlayerCollidingWithAnythingNew(serverLevel, boundingBox, d, d1, d2));
+ if (teleportBack) {
+ boolean allowMovement = this.player.noPhysics || this.player.isSleeping() || (!movedWrongly || !serverLevel.noCollision(this.player, boundingBox)) && !this.isEntityCollidingWithAnythingNew(serverLevel, this.player, boundingBox, d, d1, d2);
+ if (!allowMovement) {
+ io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
+ toX, toY, toZ, toYaw, toPitch, false);
+ if (event.isAllowed()) {
+ teleportBack = false;
+ allowMovement = true;
+ }
+ }
+ if (!teleportBack) {
+ if (allowMovement) {
+ // Paper end - Add fail move event
+ // CraftBukkit start - fire PlayerMoveEvent
+ // Reset to old location first
@ -911,7 +913,6 @@
+ this.lastPitch = prevPitch;
+ this.hasMoved = true;
+ }
+
+ Location from = new Location(player.getWorld(), this.lastPosX, this.lastPosY, this.lastPosZ, this.lastYaw, this.lastPitch); // Get the Players previous Event location.
+ Location to = player.getLocation().clone(); // Start off the To location as the Players current location.
+
@ -964,24 +965,20 @@
+ return;
+ }
+ }
+ // CraftBukkit end
+ // Paper end
this.player.absSnapTo(d, d1, d2, f, f1);
boolean isAutoSpinAttack = this.player.isAutoSpinAttack();
- this.clientIsFloating = d4 >= -0.03125
+ this.clientIsFloating = verticalDelta >= -0.03125 // Paper - Decompile fix
&& !flag1
&& !this.player.isSpectator()
&& !this.server.isFlightAllowed()
@@ -1098,7 +_,7 @@
this.clientIsFloating = verticalDelta >= -0.03125
@@ -1116,7 +_,7 @@
this.lastGoodY = this.player.getY();
this.lastGoodZ = this.player.getZ();
} else {
- this.teleport(x, y, z, f, f1);
+ this.internalTeleport(x, y, z, f, f1); // CraftBukkit - SPIGOT-1807: Don't call teleport event, when the client thinks the player is falling, because the chunks are not loaded on the client yet.
this.player.doCheckFallDamage(this.player.getX() - x, this.player.getY() - y, this.player.getZ() - z, packet.isOnGround());
this.player.removeLatestMovementRecordingBatch();
this.player.removeLatestMovementRecording();
}
@@ -1134,6 +_,7 @@
@@ -1152,6 +_,7 @@
this.player.getXRot()
);
}
@ -989,7 +986,7 @@
return true;
} else {
@@ -1157,10 +_,77 @@
@@ -1175,10 +_,77 @@
}
public void teleport(double x, double y, double z, float yaw, float pitch) {
@ -1068,7 +1065,7 @@
this.awaitingTeleportTime = this.tickCount;
if (++this.awaitingTeleport == Integer.MAX_VALUE) {
this.awaitingTeleport = 0;
@@ -1168,12 +_,20 @@
@@ -1186,12 +_,20 @@
this.player.teleportSetPosition(posMoveRotation, relatives);
this.awaitingPositionFromClient = this.player.position();
@ -1079,17 +1076,17 @@
+ this.lastYaw = this.player.getYRot();
+ this.lastPitch = this.player.getXRot();
+ // CraftBukkit end
this.player.connection.send(ClientboundPlayerPositionPacket.of(this.awaitingTeleport, posMoveRotation, relatives));
this.send(ClientboundPlayerPositionPacket.of(this.awaitingTeleport, posMoveRotation, relatives));
}
@Override
public void handlePlayerAction(ServerboundPlayerActionPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ if (this.player.isImmobile()) return; // CraftBukkit
if (this.player.hasClientLoaded()) {
BlockPos pos = packet.getPos();
this.player.resetLastActionTime();
@@ -1182,32 +_,95 @@
@@ -1200,32 +_,95 @@
case SWAP_ITEM_WITH_OFFHAND:
if (!this.player.isSpectator()) {
ItemStack itemInHand = this.player.getItemInHand(InteractionHand.OFF_HAND);
@ -1167,7 +1164,7 @@
+ this.player.gameMode.captureSentBlockEntities = true;
+ // Paper end - Send block entities after destroy prediction
this.player.gameMode.handleBlockBreakAction(pos, action, packet.getDirection(), this.player.level().getMaxY(), packet.getSequence());
this.player.connection.ackBlockChangesUpTo(packet.getSequence());
this.ackBlockChangesUpTo(packet.getSequence());
+ // Paper start - Send block entities after destroy prediction
+ this.player.gameMode.captureSentBlockEntities = false;
+ // If a block entity was modified speedup the block change ack to avoid the block entity
@ -1188,7 +1185,7 @@
return;
default:
throw new IllegalArgumentException("Invalid player action");
@@ -1224,9 +_,31 @@
@@ -1242,9 +_,31 @@
}
}
@ -1214,13 +1211,13 @@
+
@Override
public void handleUseItemOn(ServerboundUseItemOnPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ if (this.player.isImmobile()) return; // CraftBukkit
+ if (!this.checkLimit(packet.timestamp)) return; // Spigot - check limit
if (this.player.hasClientLoaded()) {
this.player.connection.ackBlockChangesUpTo(packet.getSequence());
ServerLevel serverLevel = this.player.serverLevel();
@@ -1235,6 +_,11 @@
this.ackBlockChangesUpTo(packet.getSequence());
ServerLevel serverLevel = this.player.level();
@@ -1253,6 +_,11 @@
if (itemInHand.isItemEnabled(serverLevel.enabledFeatures())) {
BlockHitResult hitResult = packet.getHitResult();
Vec3 location = hitResult.getLocation();
@ -1232,7 +1229,7 @@
BlockPos blockPos = hitResult.getBlockPos();
if (this.player.canInteractWithBlock(blockPos, 1.0)) {
Vec3 vec3 = location.subtract(Vec3.atCenterOf(blockPos));
@@ -1244,7 +_,8 @@
@@ -1262,7 +_,8 @@
this.player.resetLastActionTime();
int maxY = this.player.level().getMaxY();
if (blockPos.getY() <= maxY) {
@ -1242,7 +1239,7 @@
InteractionResult interactionResult = this.player.gameMode.useItemOn(this.player, serverLevel, itemInHand, hand, hitResult);
if (interactionResult.consumesAction()) {
CriteriaTriggers.ANY_BLOCK_USE.trigger(this.player, hitResult.getBlockPos(), itemInHand.copy());
@@ -1257,10 +_,10 @@
@@ -1275,10 +_,10 @@
Component component = Component.translatable("build.tooHigh", maxY).withStyle(ChatFormatting.RED);
this.player.sendSystemMessage(component, true);
} else if (interactionResult instanceof InteractionResult.Success success
@ -1255,10 +1252,10 @@
} else {
Component component1 = Component.translatable("build.tooHigh", maxY).withStyle(ChatFormatting.RED);
this.player.sendSystemMessage(component1, true);
@@ -1268,13 +_,7 @@
@@ -1286,13 +_,8 @@
this.player.connection.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos));
this.player.connection.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos.relative(direction)));
this.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos));
this.send(new ClientboundBlockUpdatePacket(serverLevel, blockPos.relative(direction)));
- } else {
- LOGGER.warn(
- "Rejecting UseItemOnPacket from {}: Location {} too far away from hit block {}.",
@ -1267,19 +1264,20 @@
- blockPos
- );
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.updateEquipmentOnPlayerActions) this.player.detectEquipmentUpdates(); // Paper - Force update attributes.
+ // Paper - Remove unused warning
}
}
}
@@ -1284,6 +_,8 @@
@@ -1302,6 +_,8 @@
@Override
public void handleUseItem(ServerboundUseItemPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ if (this.player.isImmobile()) return; // CraftBukkit
+ if (!this.checkLimit(packet.timestamp)) return; // Spigot - check limit
if (this.player.hasClientLoaded()) {
this.ackBlockChangesUpTo(packet.getSequence());
ServerLevel serverLevel = this.player.serverLevel();
@@ -1297,6 +_,48 @@
ServerLevel serverLevel = this.player.level();
@@ -1315,6 +_,48 @@
this.player.absSnapRotationTo(f, f1);
}
@ -1328,7 +1326,7 @@
if (this.player.gameMode.useItem(this.player, serverLevel, itemInHand, hand) instanceof InteractionResult.Success success
&& success.swingSource() == InteractionResult.SwingSource.SERVER) {
this.player.swing(hand, true);
@@ -1312,7 +_,7 @@
@@ -1330,7 +_,7 @@
for (ServerLevel serverLevel : this.server.getAllLevels()) {
Entity entity = packet.getEntity(serverLevel);
if (entity != null) {
@ -1337,7 +1335,7 @@
return;
}
}
@@ -1329,24 +_,54 @@
@@ -1347,24 +_,54 @@
@Override
public void onDisconnect(DisconnectionDetails details) {
@ -1395,10 +1393,10 @@
throw new IllegalArgumentException("Expected packet sequence nr >= 0");
} else {
this.ackBlockChangesUpTo = Math.max(sequence, this.ackBlockChangesUpTo);
@@ -1356,20 +_,38 @@
@@ -1374,20 +_,38 @@
@Override
public void handleSetCarriedItem(ServerboundSetCarriedItemPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ if (this.player.isImmobile()) return; // CraftBukkit
if (packet.getSlot() >= 0 && packet.getSlot() < Inventory.getSelectionSize()) {
+ if (packet.getSlot() == this.player.getInventory().getSelectedSlot()) { return; } // Paper - don't fire itemheldevent when there wasn't a slot change
@ -1434,7 +1432,7 @@
Optional<LastSeenMessages> optional = this.unpackAndApplyLastSeen(packet.lastSeenMessages());
if (!optional.isEmpty()) {
this.tryHandleChat(packet.message(), () -> {
@@ -1381,25 +_,45 @@
@@ -1399,25 +_,45 @@
return;
}
@ -1487,7 +1485,7 @@
ParseResults<CommandSourceStack> parseResults = this.parseCommand(command);
if (this.server.enforceSecureProfile() && SignableCommand.hasSignableArguments(parseResults)) {
LOGGER.error(
@@ -1416,28 +_,57 @@
@@ -1434,28 +_,57 @@
Optional<LastSeenMessages> optional = this.unpackAndApplyLastSeen(packet.lastSeenMessages());
if (!optional.isEmpty()) {
this.tryHandleChat(packet.command(), () -> {
@ -1548,7 +1546,7 @@
}
private void handleMessageDecodeFailure(SignedMessageChain.DecodeException exception) {
@@ -1501,14 +_,20 @@
@@ -1519,14 +_,20 @@
return dispatcher.parse(command, this.player.createCommandSourceStack());
}
@ -1573,7 +1571,7 @@
}
}
@@ -1520,7 +_,7 @@
@@ -1538,7 +_,7 @@
var10000 = Optional.of(lastSeenMessages);
} catch (LastSeenMessagesValidator.ValidationException var5) {
LOGGER.error("Failed to validate message acknowledgements from {}: {}", this.player.getName().getString(), var5.getMessage());
@ -1582,7 +1580,7 @@
return Optional.empty();
}
@@ -1538,22 +_,81 @@
@@ -1556,22 +_,81 @@
return false;
}
@ -1670,7 +1668,7 @@
}
}
@@ -1564,7 +_,7 @@
@@ -1582,7 +_,7 @@
this.lastSeenMessages.applyOffset(packet.offset());
} catch (LastSeenMessagesValidator.ValidationException var5) {
LOGGER.error("Failed to validate message acknowledgement offset from {}: {}", this.player.getName().getString(), var5.getMessage());
@ -1679,10 +1677,10 @@
}
}
}
@@ -1572,7 +_,40 @@
@@ -1590,7 +_,40 @@
@Override
public void handleAnimate(ServerboundSwingPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ if (this.player.isImmobile()) return; // CraftBukkit
this.player.resetLastActionTime();
+ // CraftBukkit start - Raytrace to look for 'rogue armswings'
@ -1720,23 +1718,13 @@
this.player.swing(packet.getHand());
}
@@ -1580,10 +_,41 @@
@@ -1598,6 +_,22 @@
public void handlePlayerCommand(ServerboundPlayerCommandPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
if (this.player.hasClientLoaded()) {
+ // CraftBukkit start
+ if (this.player.isRemoved()) return;
+ switch (packet.getAction()) {
+ case PRESS_SHIFT_KEY:
+ case RELEASE_SHIFT_KEY: {
+ PlayerToggleSneakEvent event = new PlayerToggleSneakEvent(this.getCraftPlayer(), packet.getAction() == ServerboundPlayerCommandPacket.Action.PRESS_SHIFT_KEY);
+ this.cserver.getPluginManager().callEvent(event);
+
+ if (event.isCancelled()) {
+ return;
+ }
+ break;
+ }
+ case START_SPRINTING:
+ case STOP_SPRINTING: {
+ PlayerToggleSprintEvent event = new PlayerToggleSprintEvent(this.getCraftPlayer(), packet.getAction() == ServerboundPlayerCommandPacket.Action.START_SPRINTING);
@ -1752,17 +1740,8 @@
+
this.player.resetLastActionTime();
switch (packet.getAction()) {
case PRESS_SHIFT_KEY:
this.player.setShiftKeyDown(true);
+ // Paper start - Add option to make parrots stay
+ if (this.player.level().paperConfig().entities.behavior.parrotsAreUnaffectedByPlayerMovement) {
+ this.player.removeEntitiesOnShoulder();
+ }
+ // Paper end - Add option to make parrots stay
break;
case RELEASE_SHIFT_KEY:
this.player.setShiftKeyDown(false);
@@ -1630,6 +_,14 @@
case START_SPRINTING:
@@ -1642,6 +_,14 @@
}
public void sendPlayerChatMessage(PlayerChatMessage chatMessage, ChatType.Bound boundType) {
@ -1777,7 +1756,7 @@
this.send(
new ClientboundPlayerChatPacket(
this.nextChatIndex++,
@@ -1652,9 +_,11 @@
@@ -1664,9 +_,11 @@
}
if (i > 4096) {
@ -1790,7 +1769,7 @@
}
public void sendDisguisedChatMessage(Component message, ChatType.Bound boundType) {
@@ -1665,6 +_,17 @@
@@ -1677,6 +_,17 @@
return this.connection.getRemoteAddress();
}
@ -1808,13 +1787,13 @@
public void switchToConfig() {
this.waitingForSwitchToConfig = true;
this.removePlayerFromWorld();
@@ -1680,9 +_,16 @@
@@ -1692,9 +_,16 @@
@Override
public void handleInteract(ServerboundInteractPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ if (this.player.isImmobile()) return; // CraftBukkit
if (this.player.hasClientLoaded()) {
final ServerLevel serverLevel = this.player.serverLevel();
final ServerLevel serverLevel = this.player.level();
final Entity target = packet.getTarget(serverLevel);
+ // Spigot start
+ if (target == this.player && !this.player.isSpectator()) {
@ -1825,7 +1804,7 @@
this.player.resetLastActionTime();
this.player.setShiftKeyDown(packet.isUsingSecondaryAction());
if (target != null) {
@@ -1691,16 +_,58 @@
@@ -1703,16 +_,58 @@
}
AABB boundingBox = target.getBoundingBox();
@ -1889,7 +1868,7 @@
ItemStack itemStack1 = success.wasItemInteraction() ? itemStack : ItemStack.EMPTY;
CriteriaTriggers.PLAYER_INTERACTED_WITH_ENTITY.trigger(ServerGamePacketListenerImpl.this.player, itemStack1, target);
if (success.swingSource() == InteractionResult.SwingSource.SERVER) {
@@ -1712,13 +_,13 @@
@@ -1724,13 +_,13 @@
@Override
public void onInteraction(InteractionHand hand) {
@ -1905,7 +1884,7 @@
);
}
@@ -1726,14 +_,19 @@
@@ -1738,14 +_,19 @@
public void onAttack() {
if (!(target instanceof ItemEntity)
&& !(target instanceof ExperienceOrb)
@ -1927,7 +1906,7 @@
ServerGamePacketListenerImpl.LOGGER
.warn("Player {} tried to attack an invalid entity", ServerGamePacketListenerImpl.this.player.getName().getString());
}
@@ -1742,6 +_,27 @@
@@ -1754,6 +_,27 @@
);
}
}
@ -1955,7 +1934,7 @@
}
}
@@ -1754,7 +_,7 @@
@@ -1766,7 +_,7 @@
case PERFORM_RESPAWN:
if (this.player.wonGame) {
this.player.wonGame = false;
@ -1964,7 +1943,7 @@
this.resetPosition();
CriteriaTriggers.CHANGED_DIMENSION.trigger(this.player, Level.END, Level.OVERWORLD);
} else {
@@ -1762,11 +_,11 @@
@@ -1774,11 +_,11 @@
return;
}
@ -1973,13 +1952,13 @@
this.resetPosition();
if (this.server.isHardcore()) {
- this.player.setGameMode(GameType.SPECTATOR);
- this.player.serverLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS).set(false, this.server);
- this.player.level().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS).set(false, this.server);
+ this.player.setGameMode(GameType.SPECTATOR, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.HARDCORE_DEATH, null); // Paper - Expand PlayerGameModeChangeEvent
+ this.player.serverLevel().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS).set(false, this.player.serverLevel()); // CraftBukkit - per-world
+ this.player.level().getGameRules().getRule(GameRules.RULE_SPECTATORSGENERATECHUNKS).set(false, this.player.level()); // CraftBukkit - per-world
}
}
break;
@@ -1777,16 +_,28 @@
@@ -1789,16 +_,27 @@
@Override
public void handleContainerClose(ServerboundContainerClosePacket packet) {
@ -1989,17 +1968,16 @@
+
+ public void handleContainerClose(ServerboundContainerClosePacket packet, org.bukkit.event.inventory.InventoryCloseEvent.Reason reason) {
+ // Paper end - Inventory close reason
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+
+ if (this.player.isImmobile()) return; // CraftBukkit
+ CraftEventFactory.handleInventoryCloseEvent(this.player, reason); // CraftBukkit // Paper
+
this.player.doCloseContainer();
}
@Override
public void handleContainerClick(ServerboundContainerClickPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ if (this.player.isImmobile()) return; // CraftBukkit
this.player.resetLastActionTime();
- if (this.player.containerMenu.containerId == packet.containerId()) {
@ -2010,7 +1988,7 @@
this.player.containerMenu.sendAllDataToRemote();
} else if (!this.player.containerMenu.stillValid(this.player)) {
LOGGER.debug("Player {} interacted with invalid menu {}", this.player, this.player.containerMenu);
@@ -1799,7 +_,340 @@
@@ -1811,7 +_,340 @@
} else {
boolean flag = packet.stateId() != this.player.containerMenu.getStateId();
this.player.containerMenu.suppressRemoteUpdates();
@ -2352,7 +2330,7 @@
for (Entry<HashedStack> entry : Int2ObjectMaps.fastIterable(packet.changedSlots())) {
this.player.containerMenu.setRemoteSlotUnsafe(entry.getIntKey(), entry.getValue());
@@ -1812,6 +_,7 @@
@@ -1824,6 +_,7 @@
} else {
this.player.containerMenu.broadcastChanges();
}
@ -2360,7 +2338,7 @@
}
}
}
@@ -1819,6 +_,14 @@
@@ -1831,6 +_,14 @@
@Override
public void handlePlaceRecipe(ServerboundPlaceRecipePacket packet) {
@ -2372,10 +2350,10 @@
+ }
+ }
+ // Paper end - auto recipe limit
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
this.player.resetLastActionTime();
if (!this.player.isSpectator() && this.player.containerMenu.containerId == packet.containerId()) {
@@ -1835,9 +_,44 @@
@@ -1847,9 +_,44 @@
return;
}
@ -2414,22 +2392,22 @@
+ }
+
RecipeBookMenu.PostPlaceAction postPlaceAction = recipeBookMenu.handlePlacement(
- packet.useMaxItems(), this.player.isCreative(), recipeHolder, this.player.serverLevel(), this.player.getInventory()
+ makeAll, this.player.isCreative(), recipeHolder, this.player.serverLevel(), this.player.getInventory()
- packet.useMaxItems(), this.player.isCreative(), recipeHolder, this.player.level(), this.player.getInventory()
+ makeAll, this.player.isCreative(), recipeHolder, this.player.level(), this.player.getInventory()
);
+ // CraftBukkit end
if (postPlaceAction == RecipeBookMenu.PostPlaceAction.PLACE_GHOST_RECIPE) {
this.player
.connection
@@ -1853,6 +_,7 @@
this.send(new ClientboundPlaceGhostRecipePacket(this.player.containerMenu.containerId, recipeFromDisplay.display().display()));
}
@@ -1863,6 +_,7 @@
@Override
public void handleContainerButtonClick(ServerboundContainerButtonClickPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ if (this.player.isImmobile()) return; // CraftBukkit
this.player.resetLastActionTime();
if (this.player.containerMenu.containerId == packet.containerId() && !this.player.isSpectator()) {
if (!this.player.containerMenu.stillValid(this.player)) {
@@ -1862,6 +_,7 @@
@@ -1872,6 +_,7 @@
if (flag) {
this.player.containerMenu.broadcastChanges();
}
@ -2437,7 +2415,7 @@
}
}
}
@@ -1878,10 +_,48 @@
@@ -1888,10 +_,48 @@
boolean flag1 = packet.slotNum() >= 1 && packet.slotNum() <= 45;
boolean flag2 = itemStack.isEmpty() || itemStack.getCount() <= itemStack.getMaxStackSize();
@ -2486,7 +2464,7 @@
} else if (flag && flag2) {
if (this.dropSpamThrottler.isUnderThreshold()) {
this.dropSpamThrottler.increment();
@@ -1895,15 +_,38 @@
@@ -1905,15 +_,38 @@
@Override
public void handleSignUpdate(ServerboundSignUpdatePacket packet) {
@ -2510,7 +2488,7 @@
private void updateSignText(ServerboundSignUpdatePacket packet, List<FilteredText> filteredText) {
+ if (this.player.isImmobile()) return; // CraftBukkit
this.player.resetLastActionTime();
ServerLevel serverLevel = this.player.serverLevel();
ServerLevel serverLevel = this.player.level();
BlockPos pos = packet.getPos();
if (serverLevel.hasChunkAt(pos)) {
+ // Paper start - Add API for client-side signs
@ -2526,10 +2504,10 @@
if (!(serverLevel.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity)) {
return;
}
@@ -1915,14 +_,32 @@
@@ -1925,14 +_,32 @@
@Override
public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
- this.player.getAbilities().flying = packet.isFlying() && this.player.getAbilities().mayfly;
+ // CraftBukkit start
+ if (this.player.getAbilities().mayfly && this.player.getAbilities().flying != packet.isFlying()) {
@ -2546,7 +2524,7 @@
@Override
public void handleClientInformation(ServerboundClientInformationPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ // Paper start - do not accept invalid information
+ if (packet.information().viewDistance() < 0) {
+ LOGGER.warn("Disconnecting {} for invalid view distance: {}", this.player.getScoreboardName(), packet.information().viewDistance());
@ -2560,16 +2538,16 @@
if (this.player.isModelPartShown(PlayerModelPart.HAT) != isModelPartShown) {
this.server.getPlayerList().broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_HAT, this.player));
}
@@ -1932,7 +_,7 @@
public void handleChangeDifficulty(ServerboundChangeDifficultyPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
if (this.player.hasPermissions(2) || this.isSingleplayerOwner()) {
- this.server.setDifficulty(packet.getDifficulty(), false);
+ // this.server.setDifficulty(packet.getDifficulty(), false); // Paper - per level difficulty; don't allow clients to change this
@@ -1948,7 +_,7 @@
packet.difficulty().getDisplayName()
);
} else {
- this.server.setDifficulty(packet.difficulty(), false);
+ // this.server.setDifficulty(packet.difficulty(), false); // Paper - per level difficulty; don't allow clients to change this
}
}
@@ -1952,7 +_,7 @@
@@ -1982,7 +_,7 @@
ProfilePublicKey.Data data2 = data.profilePublicKey();
if (!Objects.equals(data1, data2)) {
if (data1 != null && data2.expiresAt().isBefore(data1.expiresAt())) {
@ -2578,7 +2556,7 @@
} else {
try {
SignatureValidator profileKeySignatureValidator = this.server.getProfileKeySignatureValidator();
@@ -1963,8 +_,8 @@
@@ -1993,8 +_,8 @@
this.resetPlayerChatState(data.validate(this.player.getGameProfile(), profileKeySignatureValidator));
} catch (ProfilePublicKey.ValidationException var6) {
@ -2589,7 +2567,7 @@
}
}
}
@@ -1978,7 +_,7 @@
@@ -2008,7 +_,7 @@
this.connection
.setupInboundProtocol(
ConfigurationProtocols.SERVERBOUND,
@ -2598,7 +2576,7 @@
);
}
}
@@ -1997,27 +_,32 @@
@@ -2027,27 +_,32 @@
private void resetPlayerChatState(RemoteChatSession chatSession) {
this.chatSession = chatSession;
@ -2627,12 +2605,12 @@
@Override
public void handleClientTickEnd(ServerboundClientTickEndPacket packet) {
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel());
PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level());
+ this.tickEndEvent.callEvent(); // Paper - add client tick end event
if (!this.receivedMovementThisTick) {
this.player.setKnownMovement(Vec3.ZERO);
}
@@ -2048,4 +_,17 @@
@@ -2078,4 +_,17 @@
interface EntityInteraction {
InteractionResult run(ServerPlayer player, Entity entity, InteractionHand hand);
}

View File

@ -73,16 +73,16 @@
+ org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t);
+ }
+ // Paper end - Connection throttle
if (packet.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) {
if (packet.protocolVersion() != SharedConstants.getCurrentVersion().protocolVersion()) {
- Component component;
- if (packet.protocolVersion() < 754) {
- component = Component.translatable("multiplayer.disconnect.outdated_client", SharedConstants.getCurrentVersion().getName());
- component = Component.translatable("multiplayer.disconnect.outdated_client", SharedConstants.getCurrentVersion().name());
+ net.kyori.adventure.text.Component adventureComponent; // Paper - Fix hex colors not working in some kick messages
+ if (packet.protocolVersion() < SharedConstants.getCurrentVersion().getProtocolVersion()) { // Spigot - SPIGOT-7546: Handle version check correctly for outdated client message
+ adventureComponent = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(java.text.MessageFormat.format(org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName())); // Spigot // Paper - Fix hex colors not working in some kick messages
+ if (packet.protocolVersion() < SharedConstants.getCurrentVersion().protocolVersion()) { // Spigot - SPIGOT-7546: Handle version check correctly for outdated client message
+ adventureComponent = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(java.text.MessageFormat.format(org.spigotmc.SpigotConfig.outdatedClientMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().name())); // Spigot // Paper - Fix hex colors not working in some kick messages
} else {
- component = Component.translatable("multiplayer.disconnect.incompatible", SharedConstants.getCurrentVersion().getName());
+ adventureComponent = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(java.text.MessageFormat.format(org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().getName())); // Spigot // Paper - Fix hex colors not working in some kick messages
- component = Component.translatable("multiplayer.disconnect.incompatible", SharedConstants.getCurrentVersion().name());
+ adventureComponent = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserialize(java.text.MessageFormat.format(org.spigotmc.SpigotConfig.outdatedServerMessage.replaceAll("'", "''"), SharedConstants.getCurrentVersion().name())); // Spigot // Paper - Fix hex colors not working in some kick messages
}
+ Component component = io.papermc.paper.adventure.PaperAdventure.asVanilla(adventureComponent); // Paper - Fix hex colors not working in some kick messages

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/packs/PathPackResources.java
+++ b/net/minecraft/server/packs/PathPackResources.java
@@ -103,6 +_,12 @@
@@ -112,6 +_,12 @@
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path)) {
for (Path path1 : directoryStream) {
String string = path1.getFileName().toString();

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -112,14 +_,16 @@
@@ -111,14 +_,16 @@
private static final int SEND_PLAYER_INFO_INTERVAL = 600;
private static final SimpleDateFormat BAN_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
private final MinecraftServer server;
@ -20,7 +20,7 @@
public final PlayerDataStorage playerIo;
private boolean doWhiteList;
private final LayeredRegistryAccess<RegistryLayer> registries;
@@ -130,14 +_,26 @@
@@ -129,14 +_,26 @@
private static final boolean ALLOW_LOGOUTIVATOR = false;
private int sendAllPlayerInfoIn;
@ -47,259 +47,262 @@
GameProfile gameProfile = player.getGameProfile();
GameProfileCache profileCache = this.server.getProfileCache();
String string;
@@ -150,30 +_,94 @@
@@ -149,20 +_,66 @@
}
Optional<CompoundTag> optional = this.load(player);
- ResourceKey<Level> resourceKey = optional.<ResourceKey<Level>>flatMap(
- compoundTag -> DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, compoundTag.get("Dimension"))).resultOrPartial(LOGGER::error)
+ // CraftBukkit start - Better rename detection
+ if (optional.isPresent()) {
+ string = optional.flatMap(t -> t.getCompound("bukkit")).flatMap(t -> t.getString("lastKnownName")).orElse(string);
+ }
+ // CraftBukkit end
+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID & reset to main world spawn if no valid world is found
+ ResourceKey<Level> resourceKey = null; // Paper
+ boolean[] invalidPlayerWorld = {false};
+ bukkitData: if (optional.isPresent()) {
+ // The main way for bukkit worlds to store the world is the world UUID despite mojang adding custom worlds
+ final org.bukkit.World bWorld;
+ final CompoundTag playerData = optional.get();
+ // TODO maybe convert this to a codec and use compoundTag#read, we need silent variants of that method first.
+ final Optional<Long> worldUUIDMost = playerData.getLong("WorldUUIDMost");
+ final Optional<Long> worldUUIDLeast = playerData.getLong("WorldUUIDLeast");
+ final java.util.Optional<String> worldName = playerData.getString("world");
+ if (worldUUIDMost.isPresent() && worldUUIDLeast.isPresent()) {
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(new UUID(worldUUIDMost.get(), worldUUIDLeast.get()));
+ } else if (worldName.isPresent()) { // Paper - legacy bukkit world name
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(worldName.get());
+ } else {
+ break bukkitData; // if neither of the bukkit data points exist, proceed to the vanilla migration section
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(player.problemPath(), LOGGER)) {
- Optional<ValueInput> optional1 = this.load(player, scopedCollector);
- ResourceKey<Level> resourceKey = optional1.<ResourceKey<Level>>flatMap(valueInput -> valueInput.read("Dimension", Level.RESOURCE_KEY_CODEC))
- .orElse(Level.OVERWORLD);
+ Optional<ValueInput> optional1 = this.load(player, scopedCollector); final Optional<ValueInput> loadedPlayerData = optional1; // Paper - OBFHELPER
+ // CraftBukkit start - Better rename detection
+ if (loadedPlayerData.isPresent()) {
+ string = loadedPlayerData.flatMap(t -> t.child("bukkit")).flatMap(t -> t.getString("lastKnownName")).orElse(string);
+ }
+ if (bWorld != null) {
+ resourceKey = ((org.bukkit.craftbukkit.CraftWorld) bWorld).getHandle().dimension();
+ } else {
+ resourceKey = Level.OVERWORLD;
+ invalidPlayerWorld[0] = true;
+ }
+ }
+ if (resourceKey == null) { // only run the vanilla logic if we haven't found a world from the bukkit data
+ // Below is the vanilla way of getting the dimension, this is for migration from vanilla servers
+ resourceKey = optional.<ResourceKey<Level>>flatMap(
+ compoundTag -> {
+ com.mojang.serialization.DataResult<ResourceKey<Level>> dataResult = DimensionType.parseLegacy(new Dynamic<>(NbtOps.INSTANCE, compoundTag.get("Dimension")));
+ final Optional<ResourceKey<Level>> result = dataResult.resultOrPartial(LOGGER::error);
+ invalidPlayerWorld[0] = result.isEmpty(); // reset to main world spawn if no valid world is found
+ return result;
+ }
)
- .orElse(Level.OVERWORLD);
+ .orElse(Level.OVERWORLD); // revert to vanilla default main world, this isn't an "invalid world" since no player data existed
+ }
+ // Paper end
ServerLevel level = this.server.getLevel(resourceKey);
ServerLevel serverLevel;
if (level == null) {
LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourceKey);
serverLevel = this.server.overworld();
+ invalidPlayerWorld[0] = true; // Paper - reset to main world if no world with parsed value is found
} else {
serverLevel = level;
}
+ // Paper start - Entity#getEntitySpawnReason
+ if (optional.isEmpty()) {
+ player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login
+ // Paper start - reset to main world spawn if first spawn or invalid world
+ }
+ if (optional.isEmpty() || invalidPlayerWorld[0]) {
+ // Paper end - reset to main world spawn if first spawn or invalid world
+ player.snapTo(player.adjustSpawnLocation(serverLevel, serverLevel.getSharedSpawnPos()).getBottomCenter(), serverLevel.getSharedSpawnAngle(), 0.0F); // Paper - MC-200092 - fix first spawn pos yaw being ignored
+ }
+ // Paper end - Entity#getEntitySpawnReason
player.setServerLevel(serverLevel);
String loggableAddress = connection.getLoggableAddress(this.server.logIPs());
- LOGGER.info(
- "{}[{}] logged in with entity id {} at ({}, {}, {})",
- player.getName().getString(),
- loggableAddress,
- player.getId(),
- player.getX(),
- player.getY(),
- player.getZ()
- );
+ // Spigot start - spawn location event
+ org.bukkit.entity.Player spawnPlayer = player.getBukkitEntity();
+ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(spawnPlayer, spawnPlayer.getLocation());
+ this.cserver.getPluginManager().callEvent(ev);
+
+ org.bukkit.Location loc = ev.getSpawnLocation();
+ serverLevel = ((org.bukkit.craftbukkit.CraftWorld) loc.getWorld()).getHandle();
+
+ player.spawnIn(serverLevel);
+ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world)
+ player.setPosRaw(loc.getX(), loc.getY(), loc.getZ());
+ player.setRot(loc.getYaw(), loc.getPitch());
+ // Paper end - set raw so we aren't fully joined to the world
+ // Spigot end
+ // LOGGER.info( // CraftBukkit - Moved message to after join
+ // "{}[{}] logged in with entity id {} at ({}, {}, {})",
+ // player.getName().getString(),
+ // loggableAddress,
+ // player.getId(),
+ // player.getX(),
+ // player.getY(),
+ // player.getZ()
+ // );
LevelData levelData = serverLevel.getLevelData();
player.loadGameTypes(optional.orElse(null));
ServerGamePacketListenerImpl serverGamePacketListenerImpl = new ServerGamePacketListenerImpl(this.server, connection, player, cookie);
@@ -191,8 +_,8 @@
levelData.isHardcore(),
this.server.levelKeys(),
this.getMaxPlayers(),
- this.viewDistance,
- this.simulationDistance,
+ serverLevel.spigotConfig.viewDistance,// Spigot - view distance
+ serverLevel.spigotConfig.simulationDistance,
_boolean1,
!_boolean,
_boolean2,
@@ -200,6 +_,7 @@
this.server.enforceSecureProfile()
)
);
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
serverGamePacketListenerImpl.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
serverGamePacketListenerImpl.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
serverGamePacketListenerImpl.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
@@ -219,26 +_,119 @@
mutableComponent = Component.translatable("multiplayer.player.joined.renamed", player.getDisplayName(), string);
}
- this.broadcastSystemMessage(mutableComponent.withStyle(ChatFormatting.YELLOW), false);
+ // CraftBukkit start
+ mutableComponent.withStyle(ChatFormatting.YELLOW);
+ Component joinMessage = mutableComponent; // Paper - Adventure
serverGamePacketListenerImpl.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
ServerStatus status = this.server.getStatus();
if (status != null && !cookie.transferred()) {
player.sendServerStatus(status);
}
- player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players));
+ // player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
this.players.add(player);
+ this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
this.playersByUUID.put(player.getUUID(), player);
- this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)));
- this.sendLevelInfo(player, serverLevel);
+ // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below
+ // Paper start - Fire PlayerJoinEvent when Player is actually ready; correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks
+ player.supressTrackerForLogin = true;
serverLevel.addNewPlayer(player);
- this.server.getCustomBossEvents().onPlayerConnect(player);
- this.sendActivePlayerEffects(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below serverLevel.addPlayerJoin(player);
+ // Paper end - Fire PlayerJoinEvent when Player is actually ready
optional.ifPresent(compoundTag -> {
player.loadAndSpawnEnderPearls(compoundTag);
player.loadAndSpawnParentVehicle(compoundTag);
});
+ // CraftBukkit start
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
+
+ // Ensure that player inventory is populated with its viewer
+ player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
+
+ org.bukkit.event.player.PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(bukkitPlayer, io.papermc.paper.adventure.PaperAdventure.asAdventure(mutableComponent)); // Paper - Adventure
+ this.cserver.getPluginManager().callEvent(playerJoinEvent);
+
+ if (!player.connection.isAcceptingMessages()) {
+ return;
+ }
+
+ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
+
+ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
+ joinMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(jm); // Paper - Adventure
+ this.server.getPlayerList().broadcastSystemMessage(joinMessage, false); // Paper - Adventure
+ }
+ // CraftBukkit end
+
+ // CraftBukkit start - sendAll above replaced with this loop
+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player
+
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join
+ for (int i = 0; i < this.players.size(); ++i) {
+ ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
+
+ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
+ // Paper start - Add Listing API for Player
+ if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) {
+ // Paper end - Add Listing API for Player
+ entityplayer1.connection.send(packet);
+ // Paper start - Add Listing API for Player
+ // CraftBukkit end
+ // Paper start - move logic in Entity to here, to use bukkit supplied world UUID & reset to main world spawn if no valid world is found
+ ResourceKey<Level> resourceKey = null; // Paper
+ boolean[] invalidPlayerWorld = {false};
+ bukkitData: if (loadedPlayerData.isPresent()) {
+ // The main way for bukkit worlds to store the world is the world UUID despite mojang adding custom worlds
+ final org.bukkit.World bWorld;
+ final ValueInput playerData = loadedPlayerData.get();
+ // TODO maybe convert this to a codec and use compoundTag#read, we need silent variants of that method first.
+ final Optional<Long> worldUUIDMost = playerData.getLong("WorldUUIDMost");
+ final Optional<Long> worldUUIDLeast = playerData.getLong("WorldUUIDLeast");
+ final java.util.Optional<String> worldName = playerData.getString("world");
+ if (worldUUIDMost.isPresent() && worldUUIDLeast.isPresent()) {
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(new UUID(worldUUIDMost.get(), worldUUIDLeast.get()));
+ } else if (worldName.isPresent()) { // Paper - legacy bukkit world name
+ bWorld = org.bukkit.Bukkit.getServer().getWorld(worldName.get());
+ } else {
+ entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false));
+ break bukkitData; // if neither of the bukkit data points exist, proceed to the vanilla migration section
+ }
+ // Paper end - Add Listing API for Player
+ if (bWorld != null) {
+ resourceKey = ((org.bukkit.craftbukkit.CraftWorld) bWorld).getHandle().dimension();
+ } else {
+ resourceKey = Level.OVERWORLD;
+ invalidPlayerWorld[0] = true;
+ }
+ }
+ if (resourceKey == null) { // only run the vanilla logic if we haven't found a world from the bukkit data
+ // Below is the vanilla way of getting the dimension, this is for migration from vanilla servers
+ resourceKey = loadedPlayerData.<ResourceKey<Level>>flatMap(
+ compoundTag -> {
+ Optional<ResourceKey<Level>> result = compoundTag.read("Dimension", Level.RESOURCE_KEY_CODEC);
+ invalidPlayerWorld[0] = result.isEmpty(); // reset to main world spawn if no valid world is found
+ return result;
+ }
+ )
+ .orElse(Level.OVERWORLD); // revert to vanilla default main world, this isn't an "invalid world" since no player data existed
+ }
+ // Paper end
ServerLevel level = this.server.getLevel(resourceKey);
ServerLevel serverLevel;
if (level == null) {
LOGGER.warn("Unknown respawn dimension {}, defaulting to overworld", resourceKey);
serverLevel = this.server.overworld();
+ invalidPlayerWorld[0] = true; // Paper - reset to main world if no world with parsed value is found
} else {
serverLevel = level;
}
+ // Paper start - Entity#getEntitySpawnReason
+ if (loadedPlayerData.isEmpty()) {
+ player.spawnReason = org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT; // set Player SpawnReason to DEFAULT on first login
+ }
+ // Paper end - Entity#getEntitySpawnReason
player.setServerLevel(serverLevel);
- if (optional1.isEmpty()) {
+ if (loadedPlayerData.isEmpty() || invalidPlayerWorld[0]) { // Paper - reset to main world spawn if first spawn or invalid world
player.snapTo(
player.adjustSpawnLocation(serverLevel, serverLevel.getSharedSpawnPos()).getBottomCenter(), serverLevel.getSharedSpawnAngle(), 0.0F
);
@@ -170,15 +_,29 @@
serverLevel.waitForChunkAndEntities(player.chunkPosition(), 1);
String loggableAddress = connection.getLoggableAddress(this.server.logIPs());
- LOGGER.info(
- "{}[{}] logged in with entity id {} at ({}, {}, {})",
- player.getName().getString(),
- loggableAddress,
- player.getId(),
- player.getX(),
- player.getY(),
- player.getZ()
- );
+ // Spigot start - spawn location event
+ org.bukkit.entity.Player spawnPlayer = player.getBukkitEntity();
+ org.spigotmc.event.player.PlayerSpawnLocationEvent ev = new org.spigotmc.event.player.PlayerSpawnLocationEvent(spawnPlayer, spawnPlayer.getLocation());
+ this.cserver.getPluginManager().callEvent(ev);
+
+ org.bukkit.Location loc = ev.getSpawnLocation();
+ serverLevel = ((org.bukkit.craftbukkit.CraftWorld) loc.getWorld()).getHandle();
+
+ player.spawnIn(serverLevel);
+ // Paper start - set raw so we aren't fully joined to the world (not added to chunk or world)
+ player.setPosRaw(loc.getX(), loc.getY(), loc.getZ());
+ player.setRot(loc.getYaw(), loc.getPitch());
+ // Paper end - set raw so we aren't fully joined to the world
+ // Spigot end
+ // LOGGER.info( // CraftBukkit - Moved message to after join
+ // "{}[{}] logged in with entity id {} at ({}, {}, {})",
+ // player.getName().getString(),
+ // loggableAddress,
+ // player.getId(),
+ // player.getX(),
+ // player.getY(),
+ // player.getZ()
+ // );
LevelData levelData = serverLevel.getLevelData();
player.loadGameTypes(optional1.orElse(null));
ServerGamePacketListenerImpl serverGamePacketListenerImpl = new ServerGamePacketListenerImpl(this.server, connection, player, cookie);
@@ -196,8 +_,8 @@
levelData.isHardcore(),
this.server.levelKeys(),
this.getMaxPlayers(),
- this.viewDistance,
- this.simulationDistance,
+ serverLevel.spigotConfig.viewDistance, // Spigot - view distance
+ serverLevel.spigotConfig.simulationDistance, // Spigot - simulation distance
_boolean1,
!_boolean,
_boolean2,
@@ -205,6 +_,7 @@
this.server.enforceSecureProfile()
)
);
+ player.getBukkitEntity().sendSupportedChannels(); // CraftBukkit
serverGamePacketListenerImpl.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
serverGamePacketListenerImpl.send(new ClientboundPlayerAbilitiesPacket(player.getAbilities()));
serverGamePacketListenerImpl.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
@@ -224,26 +_,119 @@
mutableComponent = Component.translatable("multiplayer.player.joined.renamed", player.getDisplayName(), string);
}
- this.broadcastSystemMessage(mutableComponent.withStyle(ChatFormatting.YELLOW), false);
+ // CraftBukkit start
+ mutableComponent.withStyle(ChatFormatting.YELLOW);
+ Component joinMessage = mutableComponent; // Paper - Adventure
serverGamePacketListenerImpl.teleport(player.getX(), player.getY(), player.getZ(), player.getYRot(), player.getXRot());
ServerStatus status = this.server.getStatus();
if (status != null && !cookie.transferred()) {
player.sendServerStatus(status);
}
- player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players));
+ // player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(this.players)); // CraftBukkit - replaced with loop below
this.players.add(player);
+ this.playersByName.put(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT), player); // Spigot
this.playersByUUID.put(player.getUUID(), player);
- this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)));
- this.sendLevelInfo(player, serverLevel);
+ // this.broadcastAll(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player))); // CraftBukkit - replaced with loop below
+ // Paper start - Fire PlayerJoinEvent when Player is actually ready; correctly register player BEFORE PlayerJoinEvent, so the entity is valid and doesn't require tick delay hacks
+ player.supressTrackerForLogin = true;
serverLevel.addNewPlayer(player);
- this.server.getCustomBossEvents().onPlayerConnect(player);
- this.sendActivePlayerEffects(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player); // see commented out section below serverLevel.addPlayerJoin(player);
+ // Paper end - Fire PlayerJoinEvent when Player is actually ready
optional1.ifPresent(valueInput -> {
player.loadAndSpawnEnderPearls(valueInput);
player.loadAndSpawnParentVehicle(valueInput);
});
+ // CraftBukkit start
+ org.bukkit.craftbukkit.entity.CraftPlayer bukkitPlayer = player.getBukkitEntity();
+
+ // Ensure that player inventory is populated with its viewer
+ player.containerMenu.transferTo(player.containerMenu, bukkitPlayer);
+
+ org.bukkit.event.player.PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(bukkitPlayer, io.papermc.paper.adventure.PaperAdventure.asAdventure(mutableComponent)); // Paper - Adventure
+ this.cserver.getPluginManager().callEvent(playerJoinEvent);
+
+ if (!player.connection.isAcceptingMessages()) {
+ return;
+ }
+
+ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player
+ continue;
+ final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage();
+
+ if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure
+ joinMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(jm); // Paper - Adventure
+ this.server.getPlayerList().broadcastSystemMessage(joinMessage, false); // Paper - Adventure
+ }
+ // CraftBukkit end
+
+ // CraftBukkit start - sendAll above replaced with this loop
+ ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player
+
+ final List<ServerPlayer> onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join
+ for (int i = 0; i < this.players.size(); ++i) {
+ ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i);
+
+ if (entityplayer1.getBukkitEntity().canSee(bukkitPlayer)) {
+ // Paper start - Add Listing API for Player
+ if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) {
+ // Paper end - Add Listing API for Player
+ entityplayer1.connection.send(packet);
+ // Paper start - Add Listing API for Player
+ } else {
+ entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false));
+ }
+ // Paper end - Add Listing API for Player
+ }
+
+ if (entityplayer1 == player || !bukkitPlayer.canSee(entityplayer1.getBukkitEntity())) { // Paper - Use single player info update packet on join; Don't include joining player
+ continue;
+ }
+
+ onlinePlayers.add(entityplayer1); // Paper - Use single player info update packet on join
+ }
+ // Paper start - Use single player info update packet on join
+ if (!onlinePlayers.isEmpty()) {
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player
+ }
+ // Paper end - Use single player info update packet on join
+ player.sentListPacket = true;
+ player.supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
+ ((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 // Paper - THIS IS NOT NEEDED ANYMORE
+
+ this.sendLevelInfo(player, serverLevel);
+
+ // CraftBukkit start - Only add if the player wasn't moved in the event
+ if (player.level() == serverLevel && !serverLevel.players().contains(player)) {
+ serverLevel.addNewPlayer(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player);
+ }
+
+ onlinePlayers.add(entityplayer1); // Paper - Use single player info update packet on join
+ }
+ // Paper start - Use single player info update packet on join
+ if (!onlinePlayers.isEmpty()) {
+ player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player
+ }
+ // Paper end - Use single player info update packet on join
+ player.sentListPacket = true;
+ player.supressTrackerForLogin = false; // Paper - Fire PlayerJoinEvent when Player is actually ready
+ ((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 // Paper - THIS IS NOT NEEDED ANYMORE
+
+ this.sendLevelInfo(player, serverLevel);
+
+ // CraftBukkit start - Only add if the player wasn't moved in the event
+ if (player.level() == serverLevel && !serverLevel.players().contains(player)) {
+ serverLevel.addNewPlayer(player);
+ this.server.getCustomBossEvents().onPlayerConnect(player);
+ }
+
+ serverLevel = player.serverLevel(); // CraftBukkit - Update in case join event changed it
+ // CraftBukkit end
+ this.sendActivePlayerEffects(player);
+ // Paper - move loading pearls / parent vehicle up
player.initInventoryMenu();
+ // CraftBukkit - Moved from above, added world
+ // Paper start - Configurable player collision; Add to collideRule team if needed
+ final net.minecraft.world.scores.Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard();
+ final PlayerTeam collideRuleTeam = scoreboard.getPlayerTeam(this.collideRuleTeamName);
+ if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) {
+ scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam);
+ }
+ // Paper end - Configurable player collision
+ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), loggableAddress, player.getId(), serverLevel.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ());
+ // Paper start - Send empty chunk, so players aren't stuck in the world loading screen with our chunk system not sending chunks when dead
+ if (player.isDeadOrDying()) {
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = serverLevel.registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.BIOME)
+ serverLevel = player.level(); // CraftBukkit - Update in case join event changed it
+ // CraftBukkit end
+ this.sendActivePlayerEffects(player);
+ // Paper - move loading pearls / parent vehicle up
player.initInventoryMenu();
+ // CraftBukkit - Moved from above, added world
+ // Paper start - Configurable player collision; Add to collideRule team if needed
+ final net.minecraft.world.scores.Scoreboard scoreboard = this.getServer().getLevel(Level.OVERWORLD).getScoreboard();
+ final PlayerTeam collideRuleTeam = scoreboard.getPlayerTeam(this.collideRuleTeamName);
+ if (this.collideRuleTeamName != null && collideRuleTeam != null && player.getTeam() == null) {
+ scoreboard.addPlayerToTeam(player.getScoreboardName(), collideRuleTeam);
+ }
+ // Paper end - Configurable player collision
+ PlayerList.LOGGER.info("{}[{}] logged in with entity id {} at ([{}]{}, {}, {})", player.getName().getString(), loggableAddress, player.getId(), serverLevel.serverLevelData.getLevelName(), player.getX(), player.getY(), player.getZ());
+ // Paper start - Send empty chunk, so players aren't stuck in the world loading screen with our chunk system not sending chunks when dead
+ if (player.isDeadOrDying()) {
+ net.minecraft.core.Holder<net.minecraft.world.level.biome.Biome> plains = serverLevel.registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.BIOME)
+ .getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
+ player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
+ new net.minecraft.world.level.chunk.EmptyLevelChunk(serverLevel, player.chunkPosition(), plains),
+ serverLevel.getLightEngine(), (java.util.BitSet)null, (java.util.BitSet) null)
+ );
+ }
+ // Paper end - Send empty chunk
+ );
+ }
+ // Paper end - Send empty chunk
}
}
public void updateEntireScoreboard(ServerScoreboard scoreboard, ServerPlayer player) {
@@ -261,30 +_,31 @@
@@ -267,30 +_,31 @@
}
public void addWorldborderListener(ServerLevel level) {
@ -336,7 +339,7 @@
}
@Override
@@ -312,56 +_,156 @@
@@ -319,56 +_,156 @@
}
protected void save(ServerPlayer player) {
@ -362,7 +365,7 @@
+ }
+ public @Nullable net.kyori.adventure.text.Component remove(ServerPlayer player, net.kyori.adventure.text.Component leaveMessage) {
+ // Paper end - Fix kick event leave message not being sent
ServerLevel serverLevel = player.serverLevel();
ServerLevel serverLevel = player.level();
player.awardStat(Stats.LEAVE_GAME);
+ // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it
+ // See SPIGOT-5799, SPIGOT-6145
@ -423,7 +426,7 @@
+ if (!thrownEnderpearl.level().paperConfig().misc.legacyEnderPearlBehavior) {
+ thrownEnderpearl.setRemoved(Entity.RemovalReason.UNLOADED_WITH_PLAYER, org.bukkit.event.entity.EntityRemoveEvent.Cause.PLAYER_QUIT); // CraftBukkit - add Bukkit remove cause
+ } else {
+ thrownEnderpearl.cachedOwner = null;
+ thrownEnderpearl.setOwner(null);
+ }
+ // Paper end - Allow using old ender pearl behavior
}
@ -495,7 +498,7 @@
+ // depending on the outcome.
+ SocketAddress socketAddress = loginlistener.connection.getRemoteAddress();
+
+ ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameProfile, ClientInformation.createDefault());
+ ServerPlayer entity = new ServerPlayer(this.server, this.server.getLevel(Level.OVERWORLD), gameProfile, net.minecraft.server.level.ClientInformation.createDefault());
+ entity.transferCookieConnection = loginlistener;
+ org.bukkit.entity.Player player = entity.getBukkitEntity();
+ org.bukkit.event.player.PlayerLoginEvent event = new org.bukkit.event.player.PlayerLoginEvent(player, loginlistener.connection.hostname, ((java.net.InetSocketAddress) socketAddress).getAddress(), ((java.net.InetSocketAddress) loginlistener.connection.channel.remoteAddress()).getAddress());
@ -507,7 +510,7 @@
MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned.reason", userBanListEntry.getReason());
if (userBanListEntry.getExpires() != null) {
mutableComponent.append(
@@ -369,10 +_,12 @@
@@ -376,10 +_,12 @@
);
}
@ -524,7 +527,7 @@
IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress);
MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason());
if (ipBanListEntry.getExpires() != null) {
@@ -381,69 +_,131 @@
@@ -388,65 +_,124 @@
);
}
@ -538,10 +541,6 @@
- }
- }
-
- public ServerPlayer getPlayerForLogin(GameProfile gameProfile, ClientInformation clientInformation) {
- return new ServerPlayer(this.server, this.server.overworld(), gameProfile, clientInformation);
- }
-
- public boolean disconnectAllPlayersWithProfile(GameProfile gameProfile) {
- UUID id = gameProfile.getId();
- Set<ServerPlayer> set = Sets.newIdentityHashSet();
@ -578,13 +577,6 @@
+ return entity;
+ }
+
+ // CraftBukkit start - added EntityPlayer
+ public ServerPlayer getPlayerForLogin(GameProfile gameProfile, ClientInformation clientInformation, ServerPlayer player) {
+ player.updateOptions(clientInformation);
+ return player;
+ // CraftBukkit end
+ }
+
+ public boolean disconnectAllPlayersWithProfile(GameProfile gameProfile, ServerPlayer player) { // CraftBukkit - added ServerPlayer
+ // CraftBukkit start - Moved up
+ // UUID id = gameProfile.getId();
@ -619,7 +611,7 @@
+ player.stopRiding(); // CraftBukkit
this.players.remove(player);
+ this.playersByName.remove(player.getScoreboardName().toLowerCase(java.util.Locale.ROOT)); // Spigot
player.serverLevel().removePlayerImmediately(player, reason);
player.level().removePlayerImmediately(player, reason);
- TeleportTransition teleportTransition = player.findRespawnPositionAndUseSpawnBlock(!keepInventory, TeleportTransition.DO_NOTHING);
- ServerLevel level = teleportTransition.newLevel();
- ServerPlayer serverPlayer = new ServerPlayer(this.server, level, player.getGameProfile(), player.clientInformation());
@ -686,7 +678,7 @@
}
byte b = (byte)(keepInventory ? 1 : 0);
ServerLevel serverLevel = serverPlayer.serverLevel();
ServerLevel serverLevel = serverPlayer.level();
LevelData levelData = serverLevel.getLevelData();
serverPlayer.connection.send(new ClientboundRespawnPacket(serverPlayer.createCommonSpawnInfo(serverLevel), b));
- serverPlayer.connection.teleport(serverPlayer.getX(), serverPlayer.getY(), serverPlayer.getZ(), serverPlayer.getYRot(), serverPlayer.getXRot());
@ -697,7 +689,7 @@
serverPlayer.connection.send(new ClientboundSetDefaultSpawnPositionPacket(level.getSharedSpawnPos(), level.getSharedSpawnAngle()));
serverPlayer.connection.send(new ClientboundChangeDifficultyPacket(levelData.getDifficulty(), levelData.isDifficultyLocked()));
serverPlayer.connection
@@ -451,10 +_,13 @@
@@ -454,10 +_,13 @@
this.sendActivePlayerEffects(serverPlayer);
this.sendLevelInfo(serverPlayer, level);
this.sendPlayerPermissionLevel(serverPlayer);
@ -715,7 +707,7 @@
serverPlayer.setHealth(serverPlayer.getHealth());
ServerPlayer.RespawnConfig respawnConfig = serverPlayer.getRespawnConfig();
if (!keepInventory && respawnConfig != null) {
@@ -477,8 +_,52 @@
@@ -480,8 +_,52 @@
)
);
}
@ -768,7 +760,7 @@
return serverPlayer;
}
@@ -488,24 +_,59 @@
@@ -491,24 +_,59 @@
}
public void sendActiveEffects(LivingEntity entity, ServerGamePacketListenerImpl connection) {
@ -831,7 +823,7 @@
public void broadcastAll(Packet<?> packet) {
for (ServerPlayer serverPlayer : this.players) {
serverPlayer.connection.send(packet);
@@ -581,6 +_,12 @@
@@ -584,6 +_,12 @@
}
private void sendPlayerPermissionLevel(ServerPlayer player, int permLevel) {
@ -844,7 +836,7 @@
if (player.connection != null) {
byte b;
if (permLevel <= 0) {
@@ -594,11 +_,33 @@
@@ -597,11 +_,33 @@
player.connection.send(new ClientboundEntityEventPacket(player, b));
}
@ -879,7 +871,7 @@
}
public boolean isOp(GameProfile profile) {
@@ -609,21 +_,17 @@
@@ -612,21 +_,17 @@
@Nullable
public ServerPlayer getPlayerByName(String username) {
@ -907,7 +899,7 @@
if (serverPlayer != except && serverPlayer.level().dimension() == dimension) {
double d = x - serverPlayer.getX();
double d1 = y - serverPlayer.getY();
@@ -636,9 +_,11 @@
@@ -639,9 +_,11 @@
}
public void saveAll() {
@ -919,7 +911,7 @@
}
public UserWhiteList getWhiteList() {
@@ -661,14 +_,18 @@
@@ -664,14 +_,18 @@
}
public void sendLevelInfo(ServerPlayer player, ServerLevel level) {
@ -942,7 +934,7 @@
}
player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.LEVEL_CHUNKS_LOAD_START, 0.0F));
@@ -677,8 +_,21 @@
@@ -680,8 +_,21 @@
public void sendAllPlayerInfo(ServerPlayer player) {
player.inventoryMenu.sendAllDataToRemote();
@ -957,15 +949,15 @@
+ player.refreshEntityData(player); // CraftBukkit - SPIGOT-7218: sync metadata
player.connection.send(new ClientboundSetHeldSlotPacket(player.getInventory().getSelectedSlot()));
+ // CraftBukkit start - from GameRules
+ int i = player.serverLevel().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23;
+ int i = player.level().getGameRules().getBoolean(GameRules.RULE_REDUCEDDEBUGINFO) ? 22 : 23;
+ player.connection.send(new ClientboundEntityEventPacket(player, (byte) i));
+ float immediateRespawn = player.serverLevel().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN) ? 1.0F: 0.0F;
+ float immediateRespawn = player.level().getGameRules().getBoolean(GameRules.RULE_DO_IMMEDIATE_RESPAWN) ? 1.0F: 0.0F;
+ player.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.IMMEDIATE_RESPAWN, immediateRespawn));
+ // CraftBukkit end
}
public int getPlayerCount() {
@@ -694,6 +_,7 @@
@@ -697,6 +_,7 @@
}
public void setUsingWhiteList(boolean whitelistEnabled) {
@ -973,7 +965,7 @@
this.doWhiteList = whitelistEnabled;
}
@@ -731,10 +_,35 @@
@@ -734,10 +_,35 @@
}
public void removeAll() {
@ -1013,7 +1005,7 @@
public void broadcastSystemMessage(Component message, boolean bypassHiddenChat) {
this.broadcastSystemMessage(message, serverPlayer -> message, bypassHiddenChat);
@@ -756,20 +_,39 @@
@@ -759,20 +_,39 @@
}
public void broadcastChatMessage(PlayerChatMessage message, ServerPlayer sender, ChatType.Bound boundChatType) {
@ -1056,7 +1048,7 @@
flag1 |= flag2 && message.isFullyFiltered();
}
@@ -782,14 +_,21 @@
@@ -785,14 +_,21 @@
return message.hasSignature() && !message.hasExpiredServer(Instant.now());
}
@ -1082,7 +1074,7 @@
Path path = file2.toPath();
if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(file.getPath()) && file2.isFile()) {
file2.renameTo(file1);
@@ -797,7 +_,7 @@
@@ -800,7 +_,7 @@
}
serverStatsCounter = new ServerStatsCounter(this.server, file1);
@ -1091,7 +1083,7 @@
}
return serverStatsCounter;
@@ -805,11 +_,11 @@
@@ -808,11 +_,11 @@
public PlayerAdvancements getPlayerAdvancements(ServerPlayer player) {
UUID uuid = player.getUUID();
@ -1105,7 +1097,7 @@
}
playerAdvancements.setPlayer(player);
@@ -852,11 +_,34 @@
@@ -855,11 +_,34 @@
}
public void reloadResources() {

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/stats/ServerRecipeBook.java
+++ b/net/minecraft/stats/ServerRecipeBook.java
@@ -66,7 +_,7 @@
@@ -63,7 +_,7 @@
for (RecipeHolder<?> recipeHolder : recipes) {
ResourceKey<Recipe<?>> resourceKey = recipeHolder.id();
@ -9,7 +9,7 @@
this.add(resourceKey);
this.addHighlight(resourceKey);
this.displayResolver
@@ -77,7 +_,7 @@
@@ -74,7 +_,7 @@
}
}
@ -18,7 +18,7 @@
player.connection.send(new ClientboundRecipeBookAddPacket(list, false));
}
@@ -95,7 +_,7 @@
@@ -92,7 +_,7 @@
}
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/stats/ServerStatsCounter.java
+++ b/net/minecraft/stats/ServerStatsCounter.java
@@ -70,9 +_,21 @@
@@ -68,9 +_,21 @@
LOGGER.error("Couldn't parse statistics file {}", file, var5);
}
}
@ -22,7 +22,7 @@
try {
FileUtils.writeStringToFile(this.file, this.toJson());
} catch (IOException var2) {
@@ -82,6 +_,8 @@
@@ -80,6 +_,8 @@
@Override
public void setValue(Player player, Stat<?> stat, int i) {

View File

@ -0,0 +1,16 @@
--- a/net/minecraft/util/PlaceholderLookupProvider.java
+++ b/net/minecraft/util/PlaceholderLookupProvider.java
@@ -52,6 +_,13 @@
)
);
}
+
+ // Paper start add method to get the value for pre-filling builders in the reg mod API
+ @Override
+ public HolderLookup.Provider lookupForValueCopyViaBuilders() {
+ return PlaceholderLookupProvider.this.context;
+ }
+ // Paper end - add method to get the value for pre-filling builders in the reg mod API
}
);
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/util/datafix/DataFixers.java
+++ b/net/minecraft/util/datafix/DataFixers.java
@@ -541,6 +_,24 @@
@@ -515,6 +_,24 @@
Schema schema44 = builder.addSchema(1456, SAME_NAMESPACED);
builder.addFixer(new EntityItemFrameDirectionFix(schema44, false));
Schema schema45 = builder.addSchema(1458, V1458::new);

View File

@ -1,10 +0,0 @@
--- a/net/minecraft/util/datafix/fixes/RaidRenamesDataFix.java
+++ b/net/minecraft/util/datafix/fixes/RaidRenamesDataFix.java
@@ -39,6 +_,6 @@
.renameField("PostRaidTicks", "post_raid_ticks")
.renameField("TotalHealth", "total_health")
.renameField("NumGroups", "group_count")
- .renameField("Status", "status");
+ .renameField("Status", "status").renameField("HeroesOfTheVillage", "heroes_of_the_village"); // Paper - Add missing rename
}
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/world/RandomizableContainer.java
+++ b/net/minecraft/world/RandomizableContainer.java
@@ -26,7 +_,7 @@
@@ -27,7 +_,7 @@
void setLootTable(@Nullable ResourceKey<LootTable> lootTable);
@ -9,25 +9,25 @@
this.setLootTable(lootTable);
this.setLootTableSeed(seed);
}
@@ -49,8 +_,9 @@
default boolean tryLoadLootTable(CompoundTag tag) {
ResourceKey<LootTable> resourceKey = tag.read("LootTable", LootTable.KEY_CODEC).orElse(null);
@@ -50,8 +_,9 @@
default boolean tryLoadLootTable(ValueInput input) {
ResourceKey<LootTable> resourceKey = input.read("LootTable", LootTable.KEY_CODEC).orElse(null);
this.setLootTable(resourceKey);
+ if (this.lootableData() != null && resourceKey != null) this.lootableData().loadNbt(tag); // Paper - LootTable API
this.setLootTableSeed(tag.getLongOr("LootTableSeed", 0L));
+ if (this.lootableData() != null && resourceKey != null) this.lootableData().loadNbt(input); // Paper - LootTable API
this.setLootTableSeed(input.getLongOr("LootTableSeed", 0L));
- return resourceKey != null;
+ return resourceKey != null && this.lootableData() == null; // Paper - only track the loot table if there is chance for replenish
}
default boolean trySaveLootTable(CompoundTag tag) {
@@ -59,26 +_,42 @@
default boolean trySaveLootTable(ValueOutput output) {
@@ -60,26 +_,42 @@
return false;
} else {
tag.store("LootTable", LootTable.KEY_CODEC, lootTable);
+ if (this.lootableData() != null) this.lootableData().saveNbt(tag); // Paper - LootTable API
output.store("LootTable", LootTable.KEY_CODEC, lootTable);
+ if (this.lootableData() != null) this.lootableData().saveNbt(output); // Paper - LootTable API
long lootTableSeed = this.getLootTableSeed();
if (lootTableSeed != 0L) {
tag.putLong("LootTableSeed", lootTableSeed);
output.putLong("LootTableSeed", lootTableSeed);
}
- return true;
@ -65,7 +65,7 @@
LootParams.Builder builder = new LootParams.Builder((ServerLevel)level).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(blockPos));
if (player != null) {
builder.withLuck(player.getLuck()).withParameter(LootContextParams.THIS_ENTITY, player);
@@ -87,4 +_,17 @@
@@ -88,4 +_,17 @@
lootTable1.fill(this, builder.create(LootContextParamSets.CHEST), this.getLootTableSeed());
}
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/AgeableMob.java
+++ b/net/minecraft/world/entity/AgeableMob.java
@@ -22,6 +_,7 @@
@@ -23,6 +_,7 @@
protected int age = 0;
protected int forcedAge = 0;
protected int forcedAgeTimer;
@ -8,40 +8,31 @@
protected AgeableMob(EntityType<? extends AgeableMob> entityType, Level level) {
super(entityType, level);
@@ -68,13 +_,15 @@
@@ -69,6 +_,7 @@
}
public void ageUp(int amount, boolean forced) {
+ if (this.ageLocked) return; // Paper - Honor ageLock
int age = this.getAge();
+ int previousAge = age; // Paper - Decompile fix: lvt reassignment lost
int previousAge = age;
age += amount * 20;
if (age > 0) {
age = 0;
}
- int i1 = age - age;
+ int i1 = age - previousAge; // Paper - Decompile fix
this.setAge(age);
if (forced) {
this.forcedAge += i1;
@@ -106,6 +_,7 @@
super.addAdditionalSaveData(compound);
compound.putInt("Age", this.getAge());
compound.putInt("ForcedAge", this.forcedAge);
+ compound.putBoolean("AgeLocked", this.ageLocked); // CraftBukkit
@@ -108,6 +_,7 @@
super.addAdditionalSaveData(output);
output.putInt("Age", this.getAge());
output.putInt("ForcedAge", this.forcedAge);
+ output.putBoolean("AgeLocked", this.ageLocked); // CraftBukkit
}
@Override
@@ -113,6 +_,7 @@
super.readAdditionalSaveData(compound);
this.setAge(compound.getIntOr("Age", 0));
this.forcedAge = compound.getIntOr("ForcedAge", 0);
+ this.ageLocked = compound.getBooleanOr("AgeLocked", false); // CraftBukkit
@@ -115,6 +_,7 @@
super.readAdditionalSaveData(input);
this.setAge(input.getIntOr("Age", 0));
this.forcedAge = input.getIntOr("ForcedAge", 0);
+ this.ageLocked = input.getBooleanOr("AgeLocked", false); // CraftBukkit
}
@Override
@@ -127,7 +_,7 @@
@@ -129,7 +_,7 @@
@Override
public void aiStep() {
super.aiStep();

View File

@ -1,24 +1,15 @@
--- a/net/minecraft/world/entity/AreaEffectCloud.java
+++ b/net/minecraft/world/entity/AreaEffectCloud.java
@@ -59,7 +_,7 @@
public float radiusOnUse = 0.0F;
public float radiusPerTick = 0.0F;
@Nullable
- private LivingEntity owner;
+ private net.minecraft.world.entity.LivingEntity owner;
@Nullable
public UUID ownerUUID;
@@ -193,7 +_,7 @@
@@ -191,7 +_,7 @@
private void serverTick(ServerLevel level) {
if (this.duration != -1 && this.tickCount >= this.waitTime + this.duration) {
if (this.duration != -1 && this.tickCount - this.waitTime >= this.duration) {
- this.discard();
+ this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
} else {
boolean isWaiting = this.isWaiting();
boolean flag = this.tickCount < this.waitTime;
@@ -206,7 +_,7 @@
@@ -204,7 +_,7 @@
if (this.radiusPerTick != 0.0F) {
radius += this.radiusPerTick;
if (radius < 0.5F) {
@ -27,7 +18,7 @@
return;
}
@@ -222,6 +_,7 @@
@@ -220,6 +_,7 @@
this.potionContents.forEachEffect(list::add, this.potionDurationScale);
List<LivingEntity> entitiesOfClass = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox());
if (!entitiesOfClass.isEmpty()) {
@ -35,7 +26,7 @@
for (LivingEntity livingEntity : entitiesOfClass) {
if (!this.victims.containsKey(livingEntity)
&& livingEntity.isAffectedByPotions()
@@ -230,6 +_,17 @@
@@ -228,6 +_,17 @@
double d1 = livingEntity.getZ() - this.getZ();
double d2 = d * d + d1 * d1;
if (d2 <= radius * radius) {
@ -53,7 +44,7 @@
this.victims.put(livingEntity, this.tickCount + this.reapplicationDelay);
for (MobEffectInstance mobEffectInstance : list) {
@@ -238,14 +_,14 @@
@@ -236,14 +_,14 @@
.value()
.applyInstantenousEffect(level, this, this.getOwner(), livingEntity, mobEffectInstance.getAmplifier(), 0.5);
} else {
@ -70,7 +61,7 @@
return;
}
@@ -255,7 +_,7 @@
@@ -253,7 +_,7 @@
if (this.durationOnUse != 0 && this.duration != -1) {
this.duration = this.duration + this.durationOnUse;
if (this.duration <= 0) {

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/ConversionType.java
+++ b/net/minecraft/world/entity/ConversionType.java
@@ -21,7 +_,7 @@
@@ -24,7 +_,7 @@
for (Entity entity : newMob.getPassengers()) {
entity.stopRiding();
@ -9,7 +9,7 @@
}
firstPassenger.startRiding(newMob);
@@ -70,6 +_,7 @@
@@ -73,6 +_,7 @@
if (leashHolder != null) {
oldMob.dropLeash();
}

View File

@ -2,7 +2,7 @@
+++ b/net/minecraft/world/entity/EntitySelector.java
@@ -17,6 +_,22 @@
public static final Predicate<Entity> NO_SPECTATORS = entity -> !entity.isSpectator();
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = NO_SPECTATORS.and(Entity::canBeCollidedWith);
public static final Predicate<Entity> CAN_BE_COLLIDED_WITH = NO_SPECTATORS.and(entity -> entity.canBeCollidedWith(null));
public static final Predicate<Entity> CAN_BE_PICKED = NO_SPECTATORS.and(Entity::isPickable);
+ // Paper start - Ability to control player's insomnia and phantoms
+ public static Predicate<Player> IS_INSOMNIAC = (player) -> {
@ -38,12 +38,13 @@
return (Predicate<Entity>)(collisionRule == Team.CollisionRule.NEVER
? Predicates.alwaysFalse()
: NO_SPECTATORS.and(
pushedEntity -> {
- if (!pushedEntity.isPushable()) {
- entity1 -> {
- if (!entity1.isPushable()) {
+ entity1 -> { final Entity pushedEntity = entity1; // Paper - OBFHELPER
+ if (!pushedEntity.isCollidable(ignoreClimbing) || !pushedEntity.canCollideWithBukkit(entity) || !entity.canCollideWithBukkit(pushedEntity)) { // CraftBukkit - collidable API // Paper - Climbing should not bypass cramming gamerule
return false;
} else if (!entity.level().isClientSide || pushedEntity instanceof Player player && player.isLocalPlayer()) {
Team team1 = pushedEntity.getTeam();
} else if (!entity.level().isClientSide || entity1 instanceof Player player && player.isLocalPlayer()) {
Team team1 = entity1.getTeam();
Team.CollisionRule collisionRule1 = team1 == null ? Team.CollisionRule.ALWAYS : team1.getCollisionRule();
- if (collisionRule1 == Team.CollisionRule.NEVER) {
+ if (collisionRule1 == Team.CollisionRule.NEVER || (pushedEntity instanceof Player && !io.papermc.paper.configuration.GlobalConfiguration.get().collisions.enablePlayerCollisions)) { // Paper - Configurable player collision

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -216,7 +_,7 @@
@@ -217,7 +_,7 @@
.fireImmune()
.sized(6.0F, 0.5F)
.clientTrackingRange(10)
@ -9,7 +9,7 @@
);
public static final EntityType<Armadillo> ARMADILLO = register(
"armadillo", EntityType.Builder.of(Armadillo::new, MobCategory.CREATURE).sized(0.7F, 0.65F).eyeHeight(0.26F).clientTrackingRange(10)
@@ -1145,6 +_,22 @@
@@ -1155,6 +_,22 @@
boolean shouldOffsetY,
boolean shouldOffsetYMore
) {
@ -32,7 +32,7 @@
Consumer<T> consumer;
if (spawnedFrom != null) {
consumer = createDefaultStackConfig(level, spawnedFrom, owner);
@@ -1152,7 +_,7 @@
@@ -1162,7 +_,7 @@
consumer = entity -> {};
}
@ -41,7 +41,7 @@
}
public static <T extends Entity> Consumer<T> createDefaultStackConfig(Level level, ItemStack stack, @Nullable LivingEntity owner) {
@@ -1169,19 +_,56 @@
@@ -1179,19 +_,56 @@
public static <T extends Entity> Consumer<T> appendCustomEntityStackConfig(Consumer<T> consumer, Level level, ItemStack stack, @Nullable LivingEntity owner) {
CustomData customData = stack.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY);
@ -101,7 +101,7 @@
if (entity instanceof Mob mob) {
mob.playAmbientSound();
}
@@ -1237,6 +_,15 @@
@@ -1247,6 +_,15 @@
if (level.isClientSide
|| !entity.getType().onlyOpCanSetNbt()
|| owner instanceof Player player && server.getPlayerList().isOp(player.getGameProfile())) {
@ -117,25 +117,25 @@
customData.loadInto(entity);
}
}
@@ -1308,9 +_,20 @@
@@ -1318,9 +_,20 @@
}
public static Optional<Entity> create(CompoundTag tag, Level level, EntitySpawnReason spawnReason) {
public static Optional<Entity> create(ValueInput input, Level level, EntitySpawnReason spawnReason) {
+ // Paper start - Don't fire sync event during generation
+ return create(tag, level, spawnReason, false);
+ return create(input, level, spawnReason, false);
+ }
+
+ public static Optional<Entity> create(CompoundTag tag, Level level, EntitySpawnReason spawnReason, boolean generation) {
+ public static Optional<Entity> create(ValueInput input, Level level, EntitySpawnReason spawnReason, boolean generation) {
+ // Paper end - Don't fire sync event during generation
return Util.ifElse(
by(tag).map(entityType -> entityType.create(level, spawnReason)),
- entity -> entity.load(tag),
+ // Paper start - Don't fire sync event during generation
+ entity -> {
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
+ entity.load(tag);
+ },
+ // Paper end - Don't fire sync event during generation
() -> LOGGER.warn("Skipping Entity with id {}", tag.getStringOr("id", "[invalid]"))
by(input).map(entityType -> entityType.create(level, spawnReason)),
- entity -> entity.load(input),
+ // Paper start - Don't fire sync event during generation
+ entity -> {
+ if (generation) entity.generation = true; // Paper - Don't fire sync event during generation
+ entity.load(input);
+ },
+ // Paper end - Don't fire sync event during generation
() -> LOGGER.warn("Skipping Entity with id {}", input.getStringOr("id", "[invalid]"))
);
}

View File

@ -1,62 +1,67 @@
--- a/net/minecraft/world/entity/ExperienceOrb.java
+++ b/net/minecraft/world/entity/ExperienceOrb.java
@@ -41,9 +_,54 @@
@@ -44,13 +_,59 @@
@Nullable
private Player followingPlayer;
private final InterpolationHandler interpolation = new InterpolationHandler(this);
-
+ // Paper start
+ @Nullable
+ public java.util.UUID sourceEntityId;
+ @Nullable
+ public java.util.UUID triggerEntityId;
+ public org.bukkit.entity.ExperienceOrb.SpawnReason spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
+
+ private void loadPaperNBT(CompoundTag tag) {
+ CompoundTag expData = tag.getCompoundOrEmpty("Paper.ExpData");
+ if (expData.isEmpty()) {
+ return;
+ }
+
+ this.sourceEntityId = expData.read("source", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ this.triggerEntityId = expData.read("trigger", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ expData.getString("reason").ifPresent(reason -> {
+ try {
+ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason);
+ } catch (Exception e) {
+ this.level().getCraftServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason);
+ }
+ private void loadPaperNBT(ValueInput input) {
+ input.read("Paper.ExpData", net.minecraft.nbt.CompoundTag.CODEC).ifPresent(expData -> {
+ this.sourceEntityId = expData.read("source", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ this.triggerEntityId = expData.read("trigger", net.minecraft.core.UUIDUtil.CODEC).orElse(null);
+ expData.getString("reason").ifPresent(reason -> {
+ try {
+ this.spawnReason = org.bukkit.entity.ExperienceOrb.SpawnReason.valueOf(reason);
+ } catch (Exception e) {
+ this.level().getCraftServer().getLogger().warning("Invalid spawnReason set for experience orb: " + e.getMessage() + " - " + reason);
+ }
+ });
+ });
+ }
+ private void savePaperNBT(CompoundTag tag) {
+ CompoundTag expData = new CompoundTag();
+ private void savePaperNBT(ValueOutput output) {
+ net.minecraft.nbt.CompoundTag expData = new net.minecraft.nbt.CompoundTag();
+ expData.storeNullable("source", net.minecraft.core.UUIDUtil.CODEC, this.sourceEntityId);
+ expData.storeNullable("trigger", net.minecraft.core.UUIDUtil.CODEC, this.triggerEntityId);
+ if (this.spawnReason != org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN) {
+ expData.putString("reason", this.spawnReason.name());
+ }
+ tag.put("Paper.ExpData", expData);
+ output.store("Paper.ExpData", net.minecraft.nbt.CompoundTag.CODEC, expData);
+ }
+
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
+ // Paper end
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - overload ctor
public ExperienceOrb(Level level, double x, double y, double z, int value) {
+ this(level, x, y, z, value, null, null);
- this(level, new Vec3(x, y, z), Vec3.ZERO, value);
+ // Paper start - add reasons for orbs
+ this(level, x, y, z, value, null, null, null);
+ }
+
+ public ExperienceOrb(Level level, double x, double y, double z, int value, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId) {
+ this(level, x, y, z, value, reason, triggerId, null);
+ }
+
+ public ExperienceOrb(Level level, double x, double y, double z, int value, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId, @Nullable Entity sourceId) {
+ this(level, new Vec3(x, y, z), Vec3.ZERO, value, reason, triggerId, sourceId);
+ // Paper end - add reasons for orbs
}
+ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper - overload ctor
public ExperienceOrb(Level level, Vec3 pos, Vec3 direction, int value) {
+ // Paper start - add reasons for orbs
+ this(level, pos, direction, value, null, null, null);
+ }
+ public ExperienceOrb(Level level, Vec3 pos, Vec3 direction, int value, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId, @Nullable Entity sourceId) {
+ // Paper end - add reasons for orbs
this(EntityType.EXPERIENCE_ORB, level);
+ // Paper start - add reasons for orbs
+ this.sourceEntityId = sourceId != null ? sourceId.getUUID() : null;
+ this.triggerEntityId = triggerId != null ? triggerId.getUUID() : null;
+ this.spawnReason = reason != null ? reason : org.bukkit.entity.ExperienceOrb.SpawnReason.UNKNOWN;
+ // Paper end
this.setPos(x, y, z);
if (!this.level().isClientSide) {
this.setYRot((float)(this.random.nextDouble() * 360.0));
@@ -119,12 +_,13 @@
+ // Paper end - add reasons for orbs
this.setPos(pos);
if (!level.isClientSide) {
this.setYRot(this.random.nextFloat() * 360.0F);
@@ -147,12 +_,13 @@
this.age++;
if (this.age >= 6000) {
@ -71,7 +76,7 @@
if (this.followingPlayer == null || this.followingPlayer.isSpectator() || this.followingPlayer.distanceToSqr(this) > 64.0) {
Player nearestPlayer = this.level().getNearestPlayer(this, 8.0);
if (nearestPlayer != null && !nearestPlayer.isSpectator() && !nearestPlayer.isDeadOrDying()) {
@@ -134,7 +_,24 @@
@@ -162,7 +_,24 @@
}
}
@ -97,26 +102,21 @@
Vec3 vec3 = new Vec3(
this.followingPlayer.getX() - this.getX(),
this.followingPlayer.getY() + this.followingPlayer.getEyeHeight() / 2.0 - this.getY(),
@@ -161,18 +_,29 @@
@@ -193,18 +_,24 @@
}
public static void award(ServerLevel level, Vec3 pos, int amount) {
+ // Paper start - add reasons for orbs
+ award(level, pos, amount, null, null, null);
public static void awardWithDirection(ServerLevel level, Vec3 pos, Vec3 direction, int amount) {
+ // Paper start - add reason to orbs
+ awardWithDirection(level, pos, direction, amount, null, null, null);
+ }
+
+ public static void award(ServerLevel level, Vec3 pos, int amount, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId) {
+ award(level, pos, amount, reason, triggerId, null);
+ }
+
+ public static void award(ServerLevel level, Vec3 pos, int amount, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId, @Nullable Entity sourceId) {
+ // Paper end - add reasons for orbs
+ public static void awardWithDirection(ServerLevel level, Vec3 pos, Vec3 direction, int amount, @Nullable org.bukkit.entity.ExperienceOrb.SpawnReason reason, @Nullable Entity triggerId, @Nullable Entity sourceId) {
+ // Paper end - add reason to orbs
while (amount > 0) {
int experienceValue = getExperienceValue(amount);
amount -= experienceValue;
if (!tryMergeToExisting(level, pos, experienceValue)) {
- level.addFreshEntity(new ExperienceOrb(level, pos.x(), pos.y(), pos.z(), experienceValue));
+ level.addFreshEntity(new ExperienceOrb(level, pos.x(), pos.y(), pos.z(), experienceValue, reason, triggerId, sourceId)); // Paper - add reason
- level.addFreshEntity(new ExperienceOrb(level, pos, direction, experienceValue));
+ level.addFreshEntity(new ExperienceOrb(level, pos, direction, experienceValue, reason, triggerId, sourceId)); // Paper - add reason to orbs
}
}
}
@ -126,10 +126,10 @@
AABB aabb = AABB.ofSize(pos, 1.0, 1.0, 1.0);
- int randomInt = level.getRandom().nextInt(40);
+ int randomInt = level.getRandom().nextInt(io.papermc.paper.configuration.GlobalConfiguration.get().misc.xpOrbGroupsPerArea.or(ORB_GROUPS_PER_AREA)); // Paper - Configure how many orb groups per area
List<ExperienceOrb> entities = level.getEntities(EntityTypeTest.forClass(ExperienceOrb.class), aabb, orb -> canMerge(orb, randomInt, amount));
if (!entities.isEmpty()) {
ExperienceOrb experienceOrb = entities.get(0);
@@ -189,13 +_,18 @@
List<ExperienceOrb> entities = level.getEntities(
EntityTypeTest.forClass(ExperienceOrb.class), aabb, experienceOrb1 -> canMerge(experienceOrb1, randomInt, amount)
);
@@ -223,13 +_,18 @@
}
private static boolean canMerge(ExperienceOrb orb, int amount, int other) {
@ -150,7 +150,7 @@
}
private void setUnderwaterMovement() {
@@ -220,7 +_,7 @@
@@ -254,7 +_,7 @@
this.markHurt();
this.health = (int)(this.health - amount);
if (this.health <= 0) {
@ -159,24 +159,24 @@
}
return true;
@@ -231,32 +_,34 @@
public void addAdditionalSaveData(CompoundTag compound) {
compound.putShort("Health", (short)this.health);
compound.putShort("Age", (short)this.age);
- compound.putShort("Value", (short)this.getValue());
+ compound.putInt("Value", this.getValue()); // Paper - save as Integer
compound.putInt("Count", this.count);
+ this.savePaperNBT(compound); // Paper
@@ -265,32 +_,34 @@
protected void addAdditionalSaveData(ValueOutput output) {
output.putShort("Health", (short)this.health);
output.putShort("Age", (short)this.age);
- output.putShort("Value", (short)this.getValue());
+ output.putInt("Value", this.getValue()); // Paper - save as Integer
output.putInt("Count", this.count);
+ this.savePaperNBT(output); // Paper
}
@Override
public void readAdditionalSaveData(CompoundTag compound) {
this.health = compound.getShortOr("Health", (short)5);
this.age = compound.getShortOr("Age", (short)0);
- this.setValue(compound.getShortOr("Value", (short)0));
+ this.setValue(compound.getIntOr("Value", 0)); // Paper - load as Integer
this.count = compound.read("Count", ExtraCodecs.POSITIVE_INT).orElse(1);
+ this.loadPaperNBT(compound); // Paper
protected void readAdditionalSaveData(ValueInput input) {
this.health = input.getShortOr("Health", (short)5);
this.age = input.getShortOr("Age", (short)0);
- this.setValue(input.getShortOr("Value", (short)0));
+ this.setValue(input.getIntOr("Value", 0)); // Paper - load as Integer
this.count = input.read("Count", ExtraCodecs.POSITIVE_INT).orElse(1);
+ this.loadPaperNBT(input); // Paper
}
@Override
@ -200,9 +200,9 @@
}
}
}
@@ -270,9 +_,19 @@
@@ -304,9 +_,19 @@
ItemStack itemStack = randomItemWith.get().itemStack();
int i = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.serverLevel(), itemStack, value);
int i = EnchantmentHelper.modifyDurabilityToRepairFromXp(player.level(), itemStack, value);
int min = Math.min(i, itemStack.getDamageValue());
+ // CraftBukkit start
+ // Paper start - mending event
@ -221,7 +221,7 @@
if (i1 > 0) {
return this.repairPlayerItems(player, i1);
}
@@ -318,6 +_,24 @@
@@ -352,6 +_,24 @@
}
public static int getExperienceValue(int expValue) {

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/Interaction.java
+++ b/net/minecraft/world/entity/Interaction.java
@@ -100,9 +_,16 @@
@@ -101,9 +_,16 @@
@Override
public boolean skipAttackInteraction(Entity entity) {
if (entity instanceof Player player) {

View File

@ -1,18 +1,18 @@
--- a/net/minecraft/world/entity/Leashable.java
+++ b/net/minecraft/world/entity/Leashable.java
@@ -56,6 +_,11 @@
@@ -80,6 +_,11 @@
}
default void writeLeashData(CompoundTag tag, @Nullable Leashable.LeashData leashData) {
default void writeLeashData(ValueOutput output, @Nullable Leashable.LeashData leashData) {
+ // CraftBukkit start - SPIGOT-7487: Don't save (and possible drop) leash, when the holder was removed by a plugin
+ if (leashData != null && leashData.leashHolder != null && leashData.leashHolder.pluginRemoved) {
+ return;
+ }
+ // CraftBukkit end
tag.storeNullable("leash", Leashable.LeashData.CODEC, leashData);
output.storeNullable("leash", Leashable.LeashData.CODEC, leashData);
}
@@ -75,7 +_,9 @@
@@ -99,7 +_,9 @@
}
if (entity.tickCount > 100) {
@ -22,7 +22,7 @@
entity.setLeashData(null);
}
}
@@ -99,7 +_,9 @@
@@ -123,7 +_,9 @@
entity.onLeashRemoved();
if (entity.level() instanceof ServerLevel serverLevel) {
if (dropItem) {
@ -32,7 +32,7 @@
}
if (broadcastPacket) {
@@ -117,7 +_,15 @@
@@ -143,7 +_,15 @@
if (leashData != null && leashData.leashHolder != null) {
if (!entity.isAlive() || !leashData.leashHolder.isAlive()) {
@ -49,16 +49,29 @@
entity.dropLeash();
} else {
entity.removeLeash();
@@ -131,7 +_,7 @@
return;
}
- if (f > 10.0) {
+ if (f > entity.level().paperConfig().misc.maxLeashDistance.or(LEASH_TOO_FAR_DIST)) { // Paper - Configurable max leash distance
@@ -154,7 +_,7 @@
if (leashHolder != null && leashHolder.level() == entity.level()) {
double d = entity.leashDistanceTo(leashHolder);
entity.whenLeashedTo(leashHolder);
- if (d > entity.leashSnapDistance()) {
+ if (d > entity.leashSnapDistanceOrConfig()) { // Paper - Configurable max leash distance
level.playSound(null, leashHolder.getX(), leashHolder.getY(), leashHolder.getZ(), SoundEvents.LEAD_BREAK, SoundSource.NEUTRAL, 1.0F, 1.0F);
entity.leashTooFarBehaviour();
} else if (f > 6.0) {
entity.elasticRangeLeashBehaviour(leashHolder, f);
@@ -148,7 +_,21 @@
} else if (d > entity.leashElasticDistance() - leashHolder.getBbWidth() - entity.getBbWidth()
@@ -175,6 +_,12 @@
entity.checkFallDistanceAccumulation();
}
+ // Paper start - Configurable max leash distance
+ default double leashSnapDistanceOrConfig() {
+ if (!(this instanceof final Entity entity)) return leashSnapDistance();
+ return entity.level().paperConfig().misc.maxLeashDistance.or(leashSnapDistance());
+ }
+ // Paper end - Configurable max leash distance
default double leashSnapDistance() {
return 12.0;
}
@@ -196,7 +_,21 @@
}
default void leashTooFarBehaviour() {

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/LightningBolt.java
+++ b/net/minecraft/world/entity/LightningBolt.java
@@ -39,6 +_,7 @@
@@ -40,6 +_,7 @@
private ServerPlayer cause;
private final Set<Entity> hitEntities = Sets.newHashSet();
private int blocksSetOnFire;
@ -8,7 +8,7 @@
public LightningBolt(EntityType<? extends LightningBolt> entityType, Level level) {
super(entityType, level);
@@ -76,7 +_,7 @@
@@ -77,7 +_,7 @@
@Override
public void tick() {
super.tick();
@ -17,7 +17,7 @@
if (this.level().isClientSide()) {
this.level()
.playLocalSound(
@@ -107,7 +_,7 @@
@@ -108,7 +_,7 @@
}
this.powerLightningRod();
@ -26,7 +26,7 @@
this.gameEvent(GameEvent.LIGHTNING_STRIKE);
}
}
@@ -130,7 +_,7 @@
@@ -131,7 +_,7 @@
}
}
@ -35,7 +35,7 @@
} else if (this.life < -this.random.nextInt(10)) {
this.flashes--;
this.life = 1;
@@ -139,10 +_,10 @@
@@ -140,10 +_,10 @@
}
}
@ -48,7 +48,7 @@
List<Entity> entities = this.level()
.getEntities(
this,
@@ -168,26 +_,34 @@
@@ -169,26 +_,34 @@
}
private void spawnFire(int extraIgnitions) {
@ -89,7 +89,7 @@
BlockState blockState = level.getBlockState(pos);
BlockPos blockPos;
BlockState blockState1;
@@ -200,22 +_,27 @@
@@ -201,22 +_,27 @@
}
if (blockState1.getBlock() instanceof WeatheringCopper) {
@ -121,7 +121,7 @@
if (optional.isEmpty()) {
break;
}
@@ -224,11 +_,17 @@
@@ -225,11 +_,17 @@
}
}

View File

@ -1,6 +1,6 @@
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -135,6 +_,17 @@
@@ -138,6 +_,17 @@
import org.jetbrains.annotations.Contract;
import org.slf4j.Logger;
@ -15,13 +15,13 @@
+import org.bukkit.event.entity.EntityResurrectEvent;
+// CraftBukkit end
+
public abstract class LivingEntity extends Entity implements Attackable {
public abstract class LivingEntity extends Entity implements Attackable, WaypointTransmitter {
private static final Logger LOGGER = LogUtils.getLogger();
private static final String TAG_ACTIVE_EFFECTS = "active_effects";
@@ -251,11 +_,25 @@
EquipmentSlot.class
@@ -264,11 +_,25 @@
);
protected final EntityEquipment equipment;
private Waypoint.Icon locatorBarIcon = new Waypoint.Icon();
+ // CraftBukkit start
+ public int expToDrop;
+ public List<DefaultDrop> drops = new java.util.ArrayList<>(); // Paper - Restore vanilla drops behavior
@ -45,7 +45,7 @@
this.equipment = this.createEquipment();
this.blocksBuilding = true;
this.reapplyPosition();
@@ -350,7 +_,13 @@
@@ -364,7 +_,13 @@
double d1 = Math.min(0.2F + d / 15.0, 2.5);
int i = (int)(150.0 * d1);
@ -60,7 +60,7 @@
}
}
@@ -535,7 +_,7 @@
@@ -549,7 +_,7 @@
this.deathTime++;
if (this.deathTime >= 20 && !this.level().isClientSide() && !this.isRemoved()) {
this.level().broadcastEntityEvent(this, (byte)60);
@ -69,7 +69,7 @@
}
}
@@ -640,7 +_,7 @@
@@ -654,7 +_,7 @@
}
public boolean shouldDiscardFriction() {
@ -78,7 +78,7 @@
}
public void setDiscardFriction(boolean discardFriction) {
@@ -652,10 +_,15 @@
@@ -666,10 +_,15 @@
}
public void onEquipItem(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem) {
@ -95,7 +95,7 @@
this.level()
.playSeededSound(
null,
@@ -682,12 +_,12 @@
@@ -696,12 +_,12 @@
}
@Override
@ -110,7 +110,7 @@
this.brain.clearMemories();
}
@@ -696,11 +_,17 @@
@@ -718,11 +_,17 @@
mobEffectInstance.onMobRemoved(level, this, removalReason);
}
@ -119,16 +119,16 @@
}
@Override
public void addAdditionalSaveData(CompoundTag compound) {
protected void addAdditionalSaveData(ValueOutput output) {
+ // Paper start - Friction API
+ if (this.frictionState != net.kyori.adventure.util.TriState.NOT_SET) {
+ compound.putString("Paper.FrictionState", this.frictionState.toString());
+ output.putString("Paper.FrictionState", this.frictionState.toString());
+ }
+ // Paper end - Friction API
compound.putFloat("Health", this.getHealth());
compound.putShort("HurtTime", (short)this.hurtTime);
compound.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp);
@@ -731,8 +_,15 @@
output.putFloat("Health", this.getHealth());
output.putShort("HurtTime", (short)this.hurtTime);
output.putInt("HurtByTimestamp", this.lastHurtByMobTimestamp);
@@ -756,8 +_,15 @@
}
}
@ -146,7 +146,7 @@
if (stack.isEmpty()) {
return null;
} else if (this.level().isClientSide) {
@@ -741,6 +_,31 @@
@@ -766,6 +_,31 @@
} else {
ItemEntity itemEntity = this.createItemStackToDrop(stack, randomizeMotion, includeThrower);
if (itemEntity != null) {
@ -178,20 +178,20 @@
this.level().addFreshEntity(itemEntity);
}
@@ -750,7 +_,22 @@
@@ -775,7 +_,22 @@
@Override
public void readAdditionalSaveData(CompoundTag compound) {
- this.internalSetAbsorptionAmount(compound.getFloatOr("AbsorptionAmount", 0.0F));
protected void readAdditionalSaveData(ValueInput input) {
- this.internalSetAbsorptionAmount(input.getFloatOr("AbsorptionAmount", 0.0F));
+ // Paper start - Check for NaN
+ float absorptionAmount = compound.getFloatOr("AbsorptionAmount", 0.0F);
+ float absorptionAmount = input.getFloatOr("AbsorptionAmount", 0.0F);
+ if (Float.isNaN(absorptionAmount)) {
+ absorptionAmount = 0;
+ }
+ this.internalSetAbsorptionAmount(absorptionAmount);
+ // Paper end - Check for NaN
+ // Paper start - Friction API
+ compound.getString("Paper.FrictionState").ifPresent(frictionState -> {
+ input.getString("Paper.FrictionState").ifPresent(frictionState -> {
+ try {
+ this.frictionState = net.kyori.adventure.util.TriState.valueOf(frictionState);
+ } catch (Exception ignored) {
@ -200,32 +200,32 @@
+ });
+ // Paper end - Friction API
if (this.level() != null && !this.level().isClientSide) {
compound.getList("attributes").ifPresent(this.getAttributes()::load);
input.read("attributes", AttributeInstance.Packed.LIST_CODEC).ifPresent(this.getAttributes()::apply);
}
@@ -763,6 +_,11 @@
@@ -787,6 +_,11 @@
this.activeEffects.put(mobEffectInstance.getEffect(), mobEffectInstance);
}
+ // CraftBukkit start
+ compound.getDouble("Bukkit.MaxHealth").ifPresent(maxHealth -> {
+ input.read("Bukkit.MaxHealth", com.mojang.serialization.Codec.DOUBLE).ifPresent(maxHealth -> {
+ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(maxHealth);
+ });
+ // CraftBukkit end
this.setHealth(compound.getFloatOr("Health", this.getMaxHealth()));
this.hurtTime = compound.getShortOr("HurtTime", (short)0);
this.deathTime = compound.getShortOr("DeathTime", (short)0);
@@ -770,6 +_,7 @@
compound.getString("Team").ifPresent(string -> {
this.setHealth(input.getFloatOr("Health", this.getMaxHealth()));
this.hurtTime = input.getShortOr("HurtTime", (short)0);
this.deathTime = input.getShortOr("DeathTime", (short)0);
@@ -794,6 +_,7 @@
input.getString("Team").ifPresent(string -> {
Scoreboard scoreboard = this.level().getScoreboard();
PlayerTeam playerTeam = scoreboard.getPlayerTeam(string);
+ if (!this.level().paperConfig().scoreboards.allowNonPlayerEntitiesOnScoreboards && !(this instanceof net.minecraft.world.entity.player.Player)) { playerTeam = null; } // Paper - Perf: Disable Scoreboards for non players by default
boolean flag = playerTeam != null && scoreboard.addPlayerToTeam(this.getStringUUID(), playerTeam);
if (!flag) {
LOGGER.warn("Unable to add mob to team \"{}\" (that team probably doesn't exist)", string);
@@ -777,11 +_,13 @@
@@ -801,11 +_,13 @@
});
this.setSharedFlag(7, compound.getBooleanOr("FallFlying", false));
compound.read("sleeping_pos", BlockPos.CODEC).ifPresentOrElse(blockPos -> {
this.setSharedFlag(7, input.getBooleanOr("FallFlying", false));
input.read("sleeping_pos", BlockPos.CODEC).ifPresentOrElse(blockPos -> {
+ if (this.position().distanceToSqr(blockPos.getX(), blockPos.getY(), blockPos.getZ()) < Mth.square(16)) { // Paper - The sleeping pos will always also set the actual pos, so a desync suggests something is wrong
this.setSleepingPos(blockPos);
this.entityData.set(DATA_POSE, Pose.SLEEPING);
@ -234,10 +234,10 @@
}
+ } // Paper - The sleeping pos will always also set the actual pos, so a desync suggests something is wrong
}, this::clearSleepingPos);
compound.getCompound("Brain").ifPresent(compoundTag -> this.brain = this.makeBrain(new Dynamic<>(NbtOps.INSTANCE, compoundTag)));
this.lastHurtByPlayer = EntityReference.read(compound, "last_hurt_by_player");
@@ -791,15 +_,44 @@
this.equipment.setAll(compound.read("equipment", EntityEquipment.CODEC, registryOps).orElseGet(EntityEquipment::new));
input.read("Brain", Codec.PASSTHROUGH).ifPresent(dynamic -> this.brain = this.makeBrain((Dynamic<?>)dynamic));
this.lastHurtByPlayer = EntityReference.read(input, "last_hurt_by_player");
@@ -816,15 +_,44 @@
this.locatorBarIcon = input.read("locator_bar_icon", Waypoint.Icon.CODEC).orElseGet(Waypoint.Icon::new);
}
+ // CraftBukkit start
@ -281,7 +281,7 @@
iterator.remove();
this.onEffectsRemoved(List.of(mobEffectInstance));
} else if (mobEffectInstance.getDuration() % 600 == 0) {
@@ -809,6 +_,17 @@
@@ -834,6 +_,17 @@
} catch (ConcurrentModificationException var6) {
}
@ -299,7 +299,7 @@
if (this.effectsDirty) {
this.updateInvisibilityStatus();
this.updateGlowingStatus();
@@ -916,15 +_,33 @@
@@ -941,15 +_,33 @@
}
public boolean removeAllEffects() {
@ -337,7 +337,7 @@
}
}
@@ -951,21 +_,57 @@
@@ -976,21 +_,57 @@
}
public final boolean addEffect(MobEffectInstance effectInstance) {
@ -397,7 +397,7 @@
this.onEffectUpdated(mobEffectInstance, true, entity);
flag = true;
}
@@ -1004,11 +_,37 @@
@@ -1029,11 +_,37 @@
@Nullable
public final MobEffectInstance removeEffectNoUpdate(Holder<MobEffect> effect) {
@ -436,7 +436,7 @@
if (mobEffectInstance != null) {
this.onEffectsRemoved(List.of(mobEffectInstance));
return true;
@@ -1092,17 +_,62 @@
@@ -1124,17 +_,62 @@
}
public void heal(float healAmount) {
@ -500,7 +500,7 @@
this.entityData.set(DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth()));
}
@@ -1114,7 +_,7 @@
@@ -1146,7 +_,7 @@
public boolean hurtServer(ServerLevel level, DamageSource damageSource, float amount) {
if (this.isInvulnerableTo(level, damageSource)) {
return false;
@ -509,15 +509,14 @@
return false;
} else if (damageSource.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) {
return false;
@@ -1128,35 +_,59 @@
amount = 0.0F;
@@ -1161,35 +_,58 @@
}
float originAmount = amount;
- float f1 = this.applyItemBlocking(level, damageSource, amount);
- amount -= f1;
+ final float originalAmount = amount; // Paper - revert to vanilla #hurt - OBFHELPER
+ float f1 = this.applyItemBlocking(level, damageSource, amount, true); // Paper
+ // Paper end
+ // amount -= f1; // CraftBukkit - Moved into handleEntityDamage(DamageSource, float) to allow modification
boolean flag = f1 > 0.0F;
- if (damageSource.is(DamageTypeTags.IS_FREEZING) && this.getType().is(EntityTypeTags.FREEZE_HURTS_EXTRA_TYPES)) {
+ // CraftBukkit - Moved into handleEntityDamage(DamageSource, float) to get amount
@ -554,7 +553,7 @@
+ if (!this.actuallyHurt(level, damageSource, (float) event.getFinalDamage(), event)) { // Paper - fix invulnerability reduction in EntityDamageEvent - no longer subtract lastHurt, that is part of the damage event calc now
+ return false;
+ }
+ if (this instanceof ServerPlayer && event.getDamage() == 0 && originalAmount == 0) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0 - skip damage if the vanilla damage is 0 and was not modified by plugins in the event.
+ if (this instanceof ServerPlayer && event.getDamage() == 0 && originAmount == 0) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0 - skip damage if the vanilla damage is 0 and was not modified by plugins in the event.
+ // CraftBukkit end
this.lastHurt = amount;
flag1 = false;
@ -567,7 +566,7 @@
+ if (!this.actuallyHurt(level, damageSource, (float) event.getFinalDamage(), event)) {
+ return false;
+ }
+ if (this instanceof ServerPlayer && event.getDamage() == 0 && originalAmount == 0) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0 - skip damage if the vanilla damage is 0 and was not modified by plugins in the event.
+ if (this instanceof ServerPlayer && event.getDamage() == 0 && originAmount == 0) return false; // Paper - revert to vanilla damage - players are not affected by damage that is 0 - skip damage if the vanilla damage is 0 and was not modified by plugins in the event.
this.lastHurt = amount;
- this.invulnerableTime = 20;
- this.actuallyHurt(level, damageSource, amount);
@ -577,7 +576,7 @@
this.hurtDuration = 10;
this.hurtTime = this.hurtDuration;
}
@@ -1171,7 +_,7 @@
@@ -1204,7 +_,7 @@
level.broadcastDamageEvent(this, damageSource);
}
@ -586,7 +585,7 @@
this.markHurt();
}
@@ -1186,8 +_,16 @@
@@ -1219,8 +_,16 @@
d = damageSource.getSourcePosition().x() - this.getX();
d1 = damageSource.getSourcePosition().z() - this.getZ();
}
@ -604,7 +603,7 @@
if (!flag) {
this.indicateDamage(d, d1);
}
@@ -1196,19 +_,19 @@
@@ -1229,19 +_,19 @@
if (this.isDeadOrDying()) {
if (!this.checkTotemDeathProtection(damageSource)) {
@ -629,7 +628,7 @@
if (flag2) {
this.lastDamageSource = damageSource;
this.lastDamageStamp = this.level().getGameTime();
@@ -1234,6 +_,12 @@
@@ -1267,6 +_,12 @@
}
public float applyItemBlocking(ServerLevel level, DamageSource damageSource, float damageAmount) {
@ -642,7 +641,7 @@
if (damageAmount <= 0.0F) {
return 0.0F;
} else {
@@ -1258,10 +_,12 @@
@@ -1291,10 +_,12 @@
}
float f = blocksAttacks.resolveBlockedDamage(damageSource, damageAmount, acos);
@ -656,7 +655,7 @@
return f;
}
@@ -1272,6 +_,59 @@
@@ -1305,6 +_,59 @@
}
}
@ -716,7 +715,7 @@
public void playSecondaryHurtSound(DamageSource damageSource) {
if (damageSource.is(DamageTypes.THORNS)) {
SoundSource soundSource = this instanceof Player ? SoundSource.PLAYERS : SoundSource.HOSTILE;
@@ -1304,12 +_,24 @@
@@ -1337,12 +_,24 @@
return EntityReference.get(this.lastHurtByPlayer, this.level(), Player.class);
}
@ -742,7 +741,7 @@
}
private boolean checkTotemDeathProtection(DamageSource damageSource) {
@@ -1319,18 +_,39 @@
@@ -1352,18 +_,39 @@
ItemStack itemStack = null;
DeathProtection deathProtection = null;
@ -789,7 +788,7 @@
serverPlayer.awardStat(Stats.ITEM_USED.get(itemStack.getItem()));
CriteriaTriggers.USED_TOTEM.trigger(serverPlayer, itemStack);
this.gameEvent(GameEvent.ITEM_INTERACT_FINISH);
@@ -1389,6 +_,7 @@
@@ -1422,6 +_,7 @@
if (!this.isRemoved() && !this.dead) {
Entity entity = damageSource.getEntity();
LivingEntity killCredit = this.getKillCredit();
@ -797,7 +796,7 @@
if (killCredit != null) {
killCredit.awardKillScore(this, damageSource);
}
@@ -1398,68 +_,141 @@
@@ -1431,68 +_,141 @@
}
if (!this.level().isClientSide && this.hasCustomName()) {
@ -945,14 +944,14 @@
+ protected void dropExperience(ServerLevel level, @Nullable Entity entity) {
+ // CraftBukkit start - Update getExpReward() above if the removed if() changes!
+ if (!(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time
+ ExperienceOrb.award(level, this.position(), this.expToDrop, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, entity, this); // Paper
+ ExperienceOrb.awardWithDirection(level, this.position(), net.minecraft.world.phys.Vec3.ZERO, this.expToDrop, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, entity, this); // Paper
+ this.expToDrop = 0;
+ }
+ // CraftBukkit end
}
protected void dropCustomDeathLoot(ServerLevel level, DamageSource damageSource, boolean recentlyHit) {
@@ -1539,9 +_,14 @@
@@ -1572,9 +_,14 @@
}
public void knockback(double strength, double x, double z) {
@ -969,7 +968,7 @@
Vec3 deltaMovement = this.getDeltaMovement();
while (x * x + z * z < 1.0E-5F) {
@@ -1550,11 +_,22 @@
@@ -1583,11 +_,22 @@
}
Vec3 vec3 = new Vec3(x, 0.0, z).normalize().scale(strength);
@ -993,7 +992,7 @@
}
}
@@ -1639,7 +_,7 @@
@@ -1672,7 +_,7 @@
@Override
public boolean isAlive() {
@ -1002,7 +1001,7 @@
}
public boolean isLookingAtMe(LivingEntity entity, double tolerance, boolean scaleByDistance, boolean visual, double... yValues) {
@@ -1673,9 +_,14 @@
@@ -1706,9 +_,14 @@
boolean flag = super.causeFallDamage(fallDistance, damageMultiplier, damageSource);
int i = this.calculateFallDamage(fallDistance, damageMultiplier);
if (i > 0) {
@ -1018,7 +1017,7 @@
return true;
} else {
return flag;
@@ -1740,7 +_,7 @@
@@ -1773,7 +_,7 @@
protected float getDamageAfterArmorAbsorb(DamageSource damageSource, float damageAmount) {
if (!damageSource.is(DamageTypeTags.BYPASSES_ARMOR)) {
@ -1027,7 +1026,7 @@
damageAmount = CombatRules.getDamageAfterAbsorb(
this, damageAmount, damageSource, this.getArmorValue(), (float)this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)
);
@@ -1753,7 +_,8 @@
@@ -1786,7 +_,8 @@
if (damageSource.is(DamageTypeTags.BYPASSES_EFFECTS)) {
return damageAmount;
} else {
@ -1037,7 +1036,7 @@
int i = (this.getEffect(MobEffects.RESISTANCE).getAmplifier() + 1) * 5;
int i1 = 25 - i;
float f = damageAmount * i1;
@@ -1790,24 +_,201 @@
@@ -1823,24 +_,201 @@
}
}
@ -1249,7 +1248,7 @@
}
public CombatTracker getCombatTracker() {
@@ -1836,7 +_,17 @@
@@ -1869,7 +_,17 @@
}
public final void setArrowCount(int count) {
@ -1268,7 +1267,7 @@
}
public final int getStingerCount() {
@@ -1991,7 +_,7 @@
@@ -2024,7 +_,7 @@
@Override
protected void onBelowWorld() {
@ -1277,7 +1276,7 @@
}
protected void updateSwingTime() {
@@ -2087,8 +_,15 @@
@@ -2120,8 +_,15 @@
}
public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
@ -1295,7 +1294,7 @@
public float getArmorCoverPercentage() {
int i = 0;
@@ -2180,14 +_,27 @@
@@ -2213,14 +_,27 @@
return this.hasEffect(MobEffects.JUMP_BOOST) ? 0.1F * (this.getEffect(MobEffects.JUMP_BOOST).getAmplifier() + 1.0F) : 0.0F;
}
@ -1323,7 +1322,7 @@
this.addDeltaMovement(new Vec3(-Mth.sin(f) * 0.2, 0.0, Mth.cos(f) * 0.2));
}
@@ -2327,8 +_,10 @@
@@ -2380,8 +_,10 @@
}
public void stopFallFlying() {
@ -1334,7 +1333,7 @@
}
private Vec3 updateFallFlyingMovement(Vec3 deltaMovement) {
@@ -2454,7 +_,7 @@
@@ -2507,7 +_,7 @@
}
protected float getFlyingSpeed() {
@ -1343,7 +1342,7 @@
}
public float getSpeed() {
@@ -2538,37 +_,15 @@
@@ -2591,37 +_,15 @@
profilerFiller.pop();
profilerFiller.push("rangeChecks");
@ -1390,7 +1389,7 @@
profilerFiller.pop();
if (this.isFallFlying()) {
@@ -2598,16 +_,39 @@
@@ -2651,16 +_,39 @@
@Nullable
private Map<EquipmentSlot, ItemStack> collectEquipmentChanges() {
Map<EquipmentSlot, ItemStack> map = null;
@ -1430,7 +1429,7 @@
AttributeMap attributes = this.getAttributes();
if (!itemStack.isEmpty()) {
this.stopLocationBasedEffects(itemStack, equipmentSlot, attributes);
@@ -2632,6 +_,8 @@
@@ -2685,6 +_,8 @@
}
}
}
@ -1439,7 +1438,7 @@
}
return map;
@@ -2663,7 +_,7 @@
@@ -2716,7 +_,7 @@
list.add(Pair.of(equipmentSlot, itemStack1));
this.lastEquipmentItems.put(equipmentSlot, itemStack1);
});
@ -1448,7 +1447,7 @@
}
protected void tickHeadTurn(float yBodyRot) {
@@ -2749,8 +_,10 @@
@@ -2802,8 +_,10 @@
if (!flag || this.onGround() && !(fluidHeight > fluidJumpThreshold)) {
if (!this.isInLava() || this.onGround() && !(fluidHeight > fluidJumpThreshold)) {
if ((this.onGround() || flag && fluidHeight <= fluidJumpThreshold) && this.noJumpDelay == 0) {
@ -1459,7 +1458,7 @@
}
} else {
this.jumpInLiquid(FluidTags.LAVA);
@@ -2791,7 +_,7 @@
@@ -2844,7 +_,7 @@
profilerFiller.pop();
if (this.level() instanceof ServerLevel serverLevel) {
profilerFiller.push("freezing");
@ -1468,7 +1467,7 @@
this.setTicksFrozen(Math.max(0, this.getTicksFrozen() - 2));
}
@@ -2812,6 +_,20 @@
@@ -2865,6 +_,20 @@
this.pushEntities();
profilerFiller.pop();
@ -1489,15 +1488,15 @@
if (this.level() instanceof ServerLevel serverLevel && this.isSensitiveToWater() && this.isInWaterOrRain()) {
this.hurtServer(serverLevel, this.damageSources().drown(), 1.0F);
}
@@ -2830,6 +_,7 @@
this.checkSlowFallDistance();
@@ -2887,6 +_,7 @@
this.checkFallDistanceAccumulation();
if (!this.level().isClientSide) {
if (!this.canGlide()) {
+ if (this.getSharedFlag(7) != false && !CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) // CraftBukkit
this.setSharedFlag(7, false);
return;
}
@@ -2869,10 +_,25 @@
@@ -2926,10 +_,25 @@
}
protected void pushEntities() {
@ -1524,7 +1523,7 @@
if (_int > 0 && pushableEntities.size() > _int - 1 && this.random.nextInt(4) == 0) {
int i = 0;
@@ -2888,7 +_,16 @@
@@ -2945,7 +_,16 @@
}
}
@ -1541,7 +1540,7 @@
this.doPush(entity1);
}
}
@@ -2930,9 +_,16 @@
@@ -2987,9 +_,16 @@
@Override
public void stopRiding() {
@ -1560,16 +1559,16 @@
this.dismountVehicle(vehicle);
}
}
@@ -2959,7 +_,7 @@
@@ -3016,7 +_,7 @@
}
public void onItemPickup(ItemEntity itemEntity) {
- Entity owner = itemEntity.getOwner();
+ Entity owner = itemEntity.thrower != null ? this.level().getGlobalPlayerByUUID(itemEntity.thrower) : null; // Paper - check global player list where appropriate
+ Entity owner = EntityReference.get(itemEntity.thrower, this.level()::getGlobalPlayerByUUID, Entity.class); // Paper - check global player list where appropriate
if (owner instanceof ServerPlayer) {
CriteriaTriggers.THROWN_ITEM_PICKED_UP_BY_ENTITY.trigger((ServerPlayer)owner, itemEntity.getItem(), this);
}
@@ -2969,7 +_,7 @@
@@ -3026,7 +_,7 @@
if (!entity.isRemoved()
&& !this.level().isClientSide
&& (entity instanceof ItemEntity || entity instanceof AbstractArrow || entity instanceof ExperienceOrb)) {
@ -1578,7 +1577,7 @@
}
}
@@ -2983,7 +_,8 @@
@@ -3040,7 +_,8 @@
} else {
Vec3 vec3 = new Vec3(this.getX(), this.getEyeY(), this.getZ());
Vec3 vec31 = new Vec3(entity.getX(), y, entity.getZ());
@ -1588,7 +1587,7 @@
}
}
@@ -3003,13 +_,27 @@
@@ -3060,13 +_,27 @@
@Override
public boolean isPickable() {
@ -1619,7 +1618,7 @@
@Override
public float getYHeadRot() {
@@ -3040,7 +_,7 @@
@@ -3097,7 +_,7 @@
}
public final void setAbsorptionAmount(float absorptionAmount) {
@ -1628,7 +1627,7 @@
}
protected void internalSetAbsorptionAmount(float absorptionAmount) {
@@ -3067,6 +_,15 @@
@@ -3124,6 +_,15 @@
return (this.entityData.get(DATA_LIVING_ENTITY_FLAGS) & 2) > 0 ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND;
}
@ -1644,7 +1643,7 @@
private void updatingUsingItem() {
if (this.isUsingItem()) {
if (ItemStack.isSameItem(this.getItemInHand(this.getUsedItemHand()), this.useItem)) {
@@ -3084,6 +_,11 @@
@@ -3141,6 +_,11 @@
return null;
} else {
double d = this.getEyeY() - 0.3F;
@ -1656,7 +1655,7 @@
ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), d, this.getZ(), stack);
itemEntity.setPickUpDelay(40);
if (includeThrower) {
@@ -3115,7 +_,12 @@
@@ -3172,7 +_,12 @@
protected void updateUsingItem(ItemStack usingItem) {
usingItem.onUseTick(this.level(), this, this.getUseItemRemainingTicks());
@ -1670,7 +1669,7 @@
this.completeUsingItem();
}
}
@@ -3141,10 +_,19 @@
@@ -3198,10 +_,19 @@
}
public void startUsingItem(InteractionHand hand) {
@ -1692,7 +1691,7 @@
if (!this.level().isClientSide) {
this.setLivingEntityFlag(1, true);
this.setLivingEntityFlag(2, hand == InteractionHand.OFF_HAND);
@@ -3168,7 +_,10 @@
@@ -3225,7 +_,10 @@
}
} else if (!this.isUsingItem() && !this.useItem.isEmpty()) {
this.useItem = ItemStack.EMPTY;
@ -1704,7 +1703,7 @@
}
}
}
@@ -3207,12 +_,49 @@
@@ -3264,12 +_,49 @@
this.releaseUsingItem();
} else {
if (!this.useItem.isEmpty() && this.isUsingItem()) {
@ -1755,7 +1754,7 @@
}
}
}
@@ -3237,6 +_,7 @@
@@ -3294,6 +_,7 @@
ItemStack itemInHand = this.getItemInHand(this.getUsedItemHand());
if (!this.useItem.isEmpty() && ItemStack.isSameItem(itemInHand, this.useItem)) {
this.useItem = itemInHand;
@ -1763,7 +1762,7 @@
this.useItem.releaseUsing(this.level(), this, this.getUseItemRemainingTicks());
if (this.useItem.useOnRelease()) {
this.updatingUsingItem();
@@ -3256,7 +_,10 @@
@@ -3313,7 +_,10 @@
}
this.useItem = ItemStack.EMPTY;
@ -1775,7 +1774,7 @@
}
public boolean isBlocking() {
@@ -3280,6 +_,60 @@
@@ -3337,6 +_,60 @@
}
}
@ -1836,7 +1835,7 @@
public boolean isSuppressingSlidingDownLadder() {
return this.isShiftKeyDown();
}
@@ -3298,6 +_,12 @@
@@ -3355,6 +_,12 @@
}
public boolean randomTeleport(double x, double y, double z, boolean broadcastTeleport) {
@ -1849,7 +1848,7 @@
double x1 = this.getX();
double y1 = this.getY();
double z1 = this.getZ();
@@ -3320,16 +_,39 @@
@@ -3377,16 +_,39 @@
}
if (flag1) {
@ -1892,7 +1891,7 @@
} else {
if (broadcastTeleport) {
level.broadcastEntityEvent(this, (byte)46);
@@ -3339,7 +_,7 @@
@@ -3396,7 +_,7 @@
pathfinderMob.getNavigation().stop();
}

View File

@ -1,7 +1,7 @@
--- a/net/minecraft/world/entity/Mob.java
+++ b/net/minecraft/world/entity/Mob.java
@@ -83,6 +_,14 @@
import net.minecraft.world.phys.AABB;
@@ -82,6 +_,14 @@
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.ticks.ContainerSingleItem;
+// CraftBukkit start
@ -15,7 +15,7 @@
public abstract class Mob extends LivingEntity implements EquipmentUser, Leashable, Targeting {
private static final EntityDataAccessor<Byte> DATA_MOB_FLAGS_ID = SynchedEntityData.defineId(Mob.class, EntityDataSerializers.BYTE);
private static final int MOB_FLAG_NO_AI = 1;
@@ -112,6 +_,7 @@
@@ -115,6 +_,7 @@
private final BodyRotationControl bodyRotationControl;
protected PathNavigation navigation;
public GoalSelector goalSelector;
@ -23,15 +23,15 @@
public GoalSelector targetSelector;
@Nullable
private LivingEntity target;
@@ -126,6 +_,7 @@
@@ -129,6 +_,7 @@
private Leashable.LeashData leashData;
private BlockPos restrictCenter = BlockPos.ZERO;
private float restrictRadius = -1.0F;
private BlockPos homePosition = BlockPos.ZERO;
private int homeRadius = -1;
+ public boolean aware = true; // CraftBukkit
protected Mob(EntityType<? extends Mob> entityType, Level level) {
super(entityType, level);
@@ -142,6 +_,12 @@
@@ -145,6 +_,12 @@
}
}
@ -44,7 +44,7 @@
protected void registerGoals() {
}
@@ -222,7 +_,39 @@
@@ -225,7 +_,39 @@
}
public void setTarget(@Nullable LivingEntity target) {
@ -84,40 +84,40 @@
}
@Override
@@ -358,13 +_,22 @@
@@ -365,13 +_,22 @@
if (this.isNoAi()) {
compound.putBoolean("NoAI", this.isNoAi());
output.putBoolean("NoAI", this.isNoAi());
}
+ compound.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit
+ output.putBoolean("Bukkit.Aware", this.aware); // CraftBukkit
}
@Override
public void readAdditionalSaveData(CompoundTag compound) {
super.readAdditionalSaveData(compound);
- this.setCanPickUpLoot(compound.getBooleanOr("CanPickUpLoot", false));
- this.persistenceRequired = compound.getBooleanOr("PersistenceRequired", false);
protected void readAdditionalSaveData(ValueInput input) {
super.readAdditionalSaveData(input);
- this.setCanPickUpLoot(input.getBooleanOr("CanPickUpLoot", false));
- this.persistenceRequired = input.getBooleanOr("PersistenceRequired", false);
+ // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it
+ boolean canPickUpLoot = compound.getBooleanOr("CanPickUpLoot", false);
+ if (isLevelAtLeast(compound, 1) || canPickUpLoot) {
+ boolean canPickUpLoot = input.getBooleanOr("CanPickUpLoot", false);
+ if (isLevelAtLeast(input, 1) || canPickUpLoot) {
+ this.setCanPickUpLoot(canPickUpLoot);
+ }
+ boolean persistenceRequired = compound.getBooleanOr("PersistenceRequired", false);
+ if (isLevelAtLeast(compound, 1) || persistenceRequired) {
+ boolean persistenceRequired = input.getBooleanOr("PersistenceRequired", false);
+ if (isLevelAtLeast(input, 1) || persistenceRequired) {
+ this.persistenceRequired = persistenceRequired;
+ }
+ // CraftBukkit end
RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE);
this.dropChances = compound.read("drop_chances", DropChances.CODEC, registryOps).orElse(DropChances.DEFAULT);
this.readLeashData(compound);
@@ -372,6 +_,7 @@
this.lootTable = compound.read("DeathLootTable", LootTable.KEY_CODEC);
this.lootTableSeed = compound.getLongOr("DeathLootTableSeed", 0L);
this.setNoAi(compound.getBooleanOr("NoAI", false));
+ this.aware = compound.getBooleanOr("Bukkit.Aware", true); // CraftBukkit
this.dropChances = input.read("drop_chances", DropChances.CODEC).orElse(DropChances.DEFAULT);
this.readLeashData(input);
this.homeRadius = input.getIntOr("home_radius", -1);
@@ -383,6 +_,7 @@
this.lootTable = input.read("DeathLootTable", LootTable.KEY_CODEC);
this.lootTableSeed = input.getLongOr("DeathLootTableSeed", 0L);
this.setNoAi(input.getBooleanOr("NoAI", false));
+ this.aware = input.getBooleanOr("Bukkit.Aware", true); // CraftBukkit
}
@Override
@@ -433,6 +_,11 @@
@@ -446,6 +_,11 @@
&& !itemEntity.getItem().isEmpty()
&& !itemEntity.hasPickUpDelay()
&& this.wantsToPickUp(serverLevel, itemEntity.getItem())) {
@ -129,7 +129,7 @@
this.pickUpItem(serverLevel, itemEntity);
}
}
@@ -447,18 +_,24 @@
@@ -460,18 +_,24 @@
protected void pickUpItem(ServerLevel level, ItemEntity entity) {
ItemStack item = entity.getItem();
@ -156,7 +156,7 @@
EquipmentSlot equipmentSlotForItem = this.getEquipmentSlotForItem(stack);
if (!this.isEquippableInSlot(stack, equipmentSlotForItem)) {
return ItemStack.EMPTY;
@@ -471,10 +_,18 @@
@@ -484,10 +_,18 @@
canReplaceCurrentItem = itemBySlot.isEmpty();
}
@ -176,7 +176,7 @@
}
ItemStack itemStack = equipmentSlotForItem.limit(stack);
@@ -591,22 +_,29 @@
@@ -608,22 +_,29 @@
@Override
public void checkDespawn() {
if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.shouldDespawnInPeaceful()) {
@ -219,7 +219,7 @@
this.noActionTime = 0;
}
}
@@ -618,6 +_,15 @@
@@ -635,6 +_,15 @@
@Override
protected final void serverAiStep() {
this.noActionTime++;
@ -235,7 +235,7 @@
ProfilerFiller profilerFiller = Profiler.get();
profilerFiller.push("sensing");
this.sensing.tick();
@@ -793,14 +_,69 @@
@@ -814,14 +_,69 @@
public boolean stillValid(Player player) {
return player.getVehicle() == Mob.this || player.canInteractWithEntity(Mob.this, 4.0);
}
@ -305,7 +305,7 @@
ItemStack itemBySlot = this.getItemBySlot(equipmentSlot);
float f = this.dropChances.byEquipment(equipmentSlot);
if (f != 0.0F) {
@@ -820,7 +_,13 @@
@@ -841,7 +_,13 @@
}
this.spawnAtLocation(level, itemBySlot);
@ -319,7 +319,7 @@
}
}
}
@@ -844,7 +_,9 @@
@@ -865,7 +_,9 @@
set.add(equipmentSlot);
} else if (this.dropChances.isPreserved(equipmentSlot)) {
this.setItemSlot(equipmentSlot, ItemStack.EMPTY);
@ -329,7 +329,7 @@
}
}
}
@@ -1122,6 +_,21 @@
@@ -1147,6 +_,21 @@
public <T extends Mob> T convertTo(
EntityType<T> entityType, ConversionParams conversionParams, EntitySpawnReason spawnReason, ConversionParams.AfterConversion<T> afterConversion
) {
@ -351,7 +351,7 @@
if (this.isRemoved()) {
return null;
} else {
@@ -1130,13 +_,23 @@
@@ -1155,13 +_,23 @@
return null;
} else {
conversionParams.type().convert(this, mob, conversionParams);
@ -378,7 +378,7 @@
}
return mob;
@@ -1146,7 +_,18 @@
@@ -1171,7 +_,18 @@
@Nullable
public <T extends Mob> T convertTo(EntityType<T> entityType, ConversionParams coversionParams, ConversionParams.AfterConversion<T> afterConversion) {
@ -398,7 +398,7 @@
}
@Nullable
@@ -1182,7 +_,17 @@
@@ -1213,7 +_,17 @@
public boolean startRiding(Entity entity, boolean force) {
boolean flag = super.startRiding(entity, force);
if (flag && this.isLeashed()) {
@ -417,7 +417,7 @@
}
return flag;
@@ -1270,7 +_,7 @@
@@ -1296,7 +_,7 @@
float knockback = this.getKnockback(source, damageSource);
if (knockback > 0.0F && source instanceof LivingEntity livingEntity) {
livingEntity.knockback(

View File

@ -1,8 +1,8 @@
--- a/net/minecraft/world/entity/NeutralMob.java
+++ b/net/minecraft/world/entity/NeutralMob.java
@@ -35,9 +_,11 @@
@@ -36,9 +_,11 @@
if (level instanceof ServerLevel serverLevel) {
UUID uuid = tag.read("AngryAt", UUIDUtil.CODEC).orElse(null);
UUID uuid = input.read("AngryAt", UUIDUtil.CODEC).orElse(null);
this.setPersistentAngerTarget(uuid);
- if ((uuid != null ? serverLevel.getEntity(uuid) : null) instanceof LivingEntity livingEntity) {
- this.setTarget(livingEntity);
@ -15,7 +15,7 @@
}
}
@@ -90,7 +_,7 @@
@@ -91,7 +_,7 @@
default void stopBeingAngry() {
this.setLastHurtByMob(null);
this.setPersistentAngerTarget(null);
@ -24,7 +24,7 @@
this.setRemainingPersistentAngerTime(0);
}
@@ -101,8 +_,24 @@
@@ -102,8 +_,24 @@
void setTarget(@Nullable LivingEntity livingEntity);

Some files were not shown because too many files have changed in this diff Show More