Merge remote-tracking branch 'upstream/main'
All checks were successful
SteamWarCI Build successful

This commit is contained in:
2025-05-31 19:42:03 +02:00
337 changed files with 4559 additions and 1903 deletions

View File

@@ -143,7 +143,7 @@ index 3a384175f8e7f204234bbaf3081bdc20c47a0d4b..5699bc15eba92e22433a20cb8326b59f
private ClientboundLevelChunkWithLightPacket(RegistryFriendlyByteBuf buffer) {
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index ef201f4add358fbf1818f3b2ec9e75fe2cce4c8b..fe9b4484d683fe48f435a053c9c90557fdf80e7b 100644
index 6b67cc939851745718f919488c997eb6719a16fc..085040aa98704f2874bcd95b751b0a81dcdb15ad 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
@@ -186,7 +186,7 @@ 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 a2a4dbcfb77d44657b3dfbe97cb629de215c29eb..73717609fccd9af12e2cc39824106f49426b581c 100644
index 9b2ee3e16e2c443e8ff03faec59dd55d729e9274..5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -407,7 +407,7 @@ public abstract class PlayerList {
@@ -199,7 +199,7 @@ index a2a4dbcfb77d44657b3dfbe97cb629de215c29eb..73717609fccd9af12e2cc39824106f49
}
// Paper end - Send empty chunk
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 1f26826b2161cfeb27e5b2060e178b493e9142d9..63f8b0c47e3321b74f4b6bcbc1e28cd751911198 100644
index 1bb40f18b671d63719d96a58ff283767c2cfe383..ba50f21707a69bbf720345996d7c83d2064e5246 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
@@ -209,10 +209,10 @@ index 1f26826b2161cfeb27e5b2060e178b493e9142d9..63f8b0c47e3321b74f4b6bcbc1e28cd7
+ public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray
private final CraftWorld world;
public boolean pvpMode;
public org.bukkit.generator.ChunkGenerator generator;
public @Nullable org.bukkit.generator.ChunkGenerator generator;
@@ -201,7 +202,8 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
org.bukkit.generator.BiomeProvider biomeProvider, // CraftBukkit
org.bukkit.World.Environment env, // CraftBukkit
@Nullable org.bukkit.generator.BiomeProvider biomeProvider, // Paper
org.bukkit.World.Environment environment, // Paper
java.util.function.Function<org.spigotmc.SpigotWorldConfig, // Spigot - create per world config
- io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator // Paper - create paper world config
+ io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, // Paper - create paper world config

View File

@@ -3874,10 +3874,10 @@ index 0000000000000000000000000000000000000000..1c82dcd38f789707e15e8cbec72ef9cd
+}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java
new file mode 100644
index 0000000000000000000000000000000000000000..7554c109c35397bc1a43dd80e87764fd78645bbf
index 0000000000000000000000000000000000000000..2d24d03bbdb5ee0d862cbfff2219f58afffafe12
--- /dev/null
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/level/entity/EntityLookup.java
@@ -0,0 +1,1002 @@
@@ -0,0 +1,1006 @@
+package ca.spottedleaf.moonrise.patches.chunk_system.level.entity;
+
+import ca.spottedleaf.concurrentutil.map.ConcurrentLong2ReferenceChainedHashTable;
@@ -4059,6 +4059,10 @@ index 0000000000000000000000000000000000000000..7554c109c35397bc1a43dd80e87764fd
+ }
+ }
+
+ public Iterable<Entity> getAllMapped() {
+ return this.entityByUUID.values();
+ }
+
+ public int getEntityCount() {
+ synchronized (this.accessibleEntities) {
+ return this.accessibleEntities.size();
@@ -26798,7 +26802,7 @@ index c50a1a01d167696134bd65b2d28db323d81d6ebd..5d63bf024cbcbd2f627c64fee77553c9
}
}
diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java
index 3f83a589442a80e9c16b5e9cd0f50792defd12bc..0005a1784ccaa00e5d6d67e7be98445150487982 100644
index 69fbcd734c269bbc9858b0ad0b3b268ddb81fcc6..a1ae77b70f69852d9e4332bf1cb3409c33b21de0 100644
--- a/net/minecraft/server/level/ServerEntity.java
+++ b/net/minecraft/server/level/ServerEntity.java
@@ -104,6 +104,11 @@ public class ServerEntity {
@@ -26814,7 +26818,7 @@ index 3f83a589442a80e9c16b5e9cd0f50792defd12bc..0005a1784ccaa00e5d6d67e7be984451
if (!passengers.equals(this.lastPassengers)) {
List<UUID> list = this.mountedOrDismounted(passengers).map(Entity::getUUID).toList();
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index fe9b4484d683fe48f435a053c9c90557fdf80e7b..8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee 100644
index 085040aa98704f2874bcd95b751b0a81dcdb15ad..cd72273468f596b640bd2d10d846fbe8813846a6 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -166,7 +166,7 @@ import net.minecraft.world.phys.shapes.VoxelShape;
@@ -27565,10 +27569,10 @@ index fe9b4484d683fe48f435a053c9c90557fdf80e7b..8afe96bfdc37e57129f1bb4af5b6d5cc
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index a8c73bdf8fb130eed8922cb537a35cda07e66da5..3e73c69c9db8cbded28a001b20d9989acb11c638 100644
index 57af8cd7629fa14176c6e7a29956617ec9506999..63fecebe6048b0d3372ea84ac74dc74744de3273 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -187,7 +187,7 @@ import net.minecraft.world.scores.Team;
@@ -186,7 +186,7 @@ import net.minecraft.world.scores.Team;
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
import org.slf4j.Logger;
@@ -27577,7 +27581,7 @@ index a8c73bdf8fb130eed8922cb537a35cda07e66da5..3e73c69c9db8cbded28a001b20d9989a
private static final Logger LOGGER = LogUtils.getLogger();
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_XZ = 32;
private static final int NEUTRAL_MOB_DEATH_NOTIFICATION_RADII_Y = 10;
@@ -423,6 +423,36 @@ public class ServerPlayer extends Player {
@@ -415,6 +415,36 @@ public class ServerPlayer extends Player {
public @Nullable String clientBrandName = null; // Paper - Brand support
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
@@ -28202,10 +28206,10 @@ index b30f56fbc1fd17259a1d05dc9155fffcab292ca1..11fed81a4696ba18440e755c3b8a5ca3
this.generatingStep = generatingStep;
this.cache = cache;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8..78201407a37eced73998b97d5d5c412eaba69af1 100644
index eda176c96bcf3d67650722ffce33863edfbdea9e..a7a07ebe6ceed99fa768b6834e350fe2f51a6950 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1320,7 +1320,7 @@ public abstract class PlayerList {
@@ -1332,7 +1332,7 @@ public abstract class PlayerList {
public void setViewDistance(int viewDistance) {
this.viewDistance = viewDistance;
@@ -28214,7 +28218,7 @@ index 5ec9e3b37e575e9805bf9f0ce5cae5c1284461d8..78201407a37eced73998b97d5d5c412e
for (ServerLevel serverLevel : this.server.getAllLevels()) {
if (serverLevel != null) {
@@ -1331,7 +1331,7 @@ public abstract class PlayerList {
@@ -1343,7 +1343,7 @@ public abstract class PlayerList {
public void setSimulationDistance(int simulationDistance) {
this.simulationDistance = simulationDistance;
@@ -28597,7 +28601,7 @@ index 8cc5c0716392ba06501542ff5cbe71ee43979e5d..09fd99c9cbd23b5f3c899bfb00c9b896
+ // Paper end - block counting
}
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e36b7294f 100644
index 663fb13233afb51f935c30ac2acae808809754c6..81a18b8e605bd4c28b48a32c80be231609182970 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -140,7 +140,7 @@ import net.minecraft.world.scores.ScoreHolder;
@@ -28950,7 +28954,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
}
private static float[] collectCandidateStepUpHeights(AABB box, List<VoxelShape> colliders, float deltaY, float maxUpStep) {
@@ -2599,21 +2747,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -2616,21 +2764,110 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public boolean isInWall() {
@@ -29072,7 +29076,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
}
public InteractionResult interact(Player player, InteractionHand hand) {
@@ -4061,15 +4298,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4078,15 +4315,17 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public Iterable<Entity> getIndirectPassengers() {
@@ -29098,7 +29102,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
}
public int countPlayerPassengers() {
@@ -4212,77 +4451,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4229,77 +4468,136 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
return Mth.lerp(partialTick, this.yRotO, this.yRot);
}
@@ -29289,7 +29293,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
public boolean touchingUnloadedChunk() {
AABB aabb = this.getBoundingBox().inflate(1.0);
@@ -4437,6 +4735,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4454,6 +4752,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
public final void setPosRaw(double x, double y, double z, boolean forceBoundingBoxUpdate) {
@@ -29305,7 +29309,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
if (!checkPosition(this, x, y, z)) {
return;
}
@@ -4570,6 +4877,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4587,6 +4894,12 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@Override
public final void setRemoved(Entity.RemovalReason removalReason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause cause) { // CraftBukkit - add Bukkit remove cause
@@ -29318,7 +29322,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
org.bukkit.craftbukkit.event.CraftEventFactory.callEntityRemoveEvent(this, cause); // CraftBukkit
final boolean alreadyRemoved = this.removalReason != null; // Paper - Folia schedulers
if (this.removalReason == null) {
@@ -4580,7 +4893,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4597,7 +4910,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.stopRiding();
}
@@ -29327,7 +29331,7 @@ index 24f3fa347c889b4e2b7b2ce69cda0f68e9bbc346..48477efbd01bb1f8987d9a3ae195710e
this.levelCallback.onRemove(removalReason);
this.onRemoval(removalReason);
// Paper start - Folia schedulers
@@ -4614,7 +4927,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -4631,7 +4944,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
public boolean shouldBeSaved() {
return (this.removalReason == null || this.removalReason.shouldSave())
&& !this.isPassenger()
@@ -29576,7 +29580,7 @@ index b766b4281aecb3b96e2c263664d81da3425e3653..c3bcb494afe464207e805f8c40b03c70
this(setDirty, true, ImmutableList.of());
}
diff --git a/net/minecraft/world/entity/decoration/ArmorStand.java b/net/minecraft/world/entity/decoration/ArmorStand.java
index 75bf15ccd8a12153951f886ed87be9f3bece3133..6f601a0a300bbf01f77d835576d15e25c8ba10b8 100644
index f5ce8151bb1bae9be638ced7f74899d452d517e1..5248f3c22abb608d7d7b338f169f13bfbf4cd2d6 100644
--- a/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -245,7 +245,7 @@ public class ArmorStand extends LivingEntity {
@@ -29725,7 +29729,7 @@ index 300f3ed58109219d97846082941b860585f66fed..892a7c1eb1b321ca6d5ca709142e7fea
// Paper start - Affects Spawning API
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
index 63f8b0c47e3321b74f4b6bcbc1e28cd751911198..eb4d03cfdb34243901cfba832d35559d5be9e876 100644
index ba50f21707a69bbf720345996d7c83d2064e5246..e9751a95ffd88f365185d53f8764291d9d2473e2 100644
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -81,6 +81,7 @@ import net.minecraft.world.level.storage.LevelData;
@@ -30399,7 +30403,7 @@ index 63f8b0c47e3321b74f4b6bcbc1e28cd751911198..eb4d03cfdb34243901cfba832d35559d
+ // Paper end - getblock optimisations - cache world height/sections
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
this.generator = gen;
this.generator = generator;
@@ -281,6 +914,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup<Entity>, AutoCl
});
// CraftBukkit end

View File

@@ -50,7 +50,7 @@ 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 32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e..d50d2928ad9f8b34a14621b1fe5c188547e04bd1 100644
index 32c8d4675de341d5edad7dbd9c0bf4bce5037733..bfbfbaa9660d21071c420b60b10be0a02a1bc87e 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
@@ -64,7 +64,7 @@ index 32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e..d50d2928ad9f8b34a14621b1fe5c1885
+ }
+
+ if (doFull) {
+ this.saveLevelData(true);
+ this.saveLevelData(false);
+ }
+ // chunk autosave is already called by the ChunkSystem during unload processing (ChunkMap#processUnloads)
+ // Copied from save()
@@ -83,10 +83,10 @@ index 32db2b9e375c12cbf7abab69cc01e8ac2c7c3b6e..d50d2928ad9f8b34a14621b1fe5c1885
// 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 3e73c69c9db8cbded28a001b20d9989acb11c638..d1de5aff81da465be79f2f747466734e80ec50dc 100644
index 5a60f2598560571e156612bf256c1c340d92a922..57e7d0a8b5f2a5bc65b0f290fb655625b1481f31 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -189,6 +189,7 @@ import org.slf4j.Logger;
@@ -188,6 +188,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,7 +95,7 @@ index 3e73c69c9db8cbded28a001b20d9989acb11c638..d1de5aff81da465be79f2f747466734e
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 78201407a37eced73998b97d5d5c412eaba69af1..f057e682ccd378f11710dc2e7129cba95788bb18 100644
index a7a07ebe6ceed99fa768b6834e350fe2f51a6950..9ca3c55a3b5b1a532b86b08eb92460df4cb54f2a 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -486,6 +486,7 @@ public abstract class PlayerList {
@@ -106,7 +106,7 @@ index 78201407a37eced73998b97d5d5c412eaba69af1..f057e682ccd378f11710dc2e7129cba9
this.playerIo.save(player);
ServerStatsCounter serverStatsCounter = player.getStats(); // CraftBukkit
if (serverStatsCounter != null) {
@@ -1067,9 +1068,23 @@ public abstract class PlayerList {
@@ -1079,9 +1080,23 @@ public abstract class PlayerList {
}
public void saveAll() {

View File

@@ -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 8e7ee4dc951eb53ccf65ab71214a0b89bd932ba0..73a450e045eba5dbfc7a4e861e4c614c8f60d6b4 100644
index 4b2801749328f250ce5735fbe7f6941a6bede01a..af04fcdba1e57b4eac678235b56ad3e1c70169b7 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -403,6 +403,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -395,6 +395,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

@@ -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 73a450e045eba5dbfc7a4e861e4c614c8f60d6b4..105d6b3a40067f9e8ae5bbd9f2872171f73b3d07 100644
index af04fcdba1e57b4eac678235b56ad3e1c70169b7..3781d9cc174b7aecacb9b9855d52c7b1ff05835c 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -407,6 +407,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -399,6 +399,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
@@ -72,7 +72,7 @@ index 73a450e045eba5dbfc7a4e861e4c614c8f60d6b4..105d6b3a40067f9e8ae5bbd9f2872171
public org.bukkit.craftbukkit.entity.CraftPlayer.TransferCookieConnection transferCookieConnection;
public String displayName;
diff --git a/net/minecraft/world/level/NaturalSpawner.java b/net/minecraft/world/level/NaturalSpawner.java
index 17b13baa3465530b11ff918c806c772eb5c39a2c..afd6da5c361e1dcf311a9afe8a7efe2faef2556a 100644
index c710e08ab48075ce7854e56826adb8f0364b025b..14a2514a408a66a83f7b5fb43b4c4dc8f23fd5f4 100644
--- a/net/minecraft/world/level/NaturalSpawner.java
+++ b/net/minecraft/world/level/NaturalSpawner.java
@@ -279,6 +279,11 @@ public final class NaturalSpawner {

View File

@@ -6,7 +6,7 @@ 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 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062b48d43fa 100644
index 0be741820fc7da2aac4f4aad85c4238ef49a0f57..337976c5c1ead87c36daa4e741b06e5a195b8302 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -555,7 +555,7 @@ public class ServerGamePacketListenerImpl
@@ -88,7 +88,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062
}
@Override
@@ -1430,7 +1462,7 @@ public class ServerGamePacketListenerImpl
@@ -1432,7 +1464,7 @@ public class ServerGamePacketListenerImpl
}
}
@@ -97,7 +97,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062
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
@@ -1469,6 +1501,7 @@ public class ServerGamePacketListenerImpl
@@ -1471,6 +1503,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,7 +105,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062
// Paper start - prevent position desync
if (this.awaitingPositionFromClient != null) {
return; // ... thanks Mojang for letting move calls teleport across dimensions.
@@ -1501,7 +1534,17 @@ public class ServerGamePacketListenerImpl
@@ -1503,7 +1536,17 @@ public class ServerGamePacketListenerImpl
}
// Paper start - Add fail move event
@@ -124,7 +124,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062
if (teleportBack) {
io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK,
toX, toY, toZ, toYaw, toPitch, false);
@@ -1638,7 +1681,7 @@ public class ServerGamePacketListenerImpl
@@ -1640,7 +1683,7 @@ public class ServerGamePacketListenerImpl
private boolean updateAwaitingTeleport() {
if (this.awaitingPositionFromClient != null) {
@@ -133,7 +133,7 @@ index 5e921c490814be31fc2843327c0e2cc76bda6620..f49a2c18ec20a7181951389066b7d062
this.awaitingTeleportTime = this.tickCount;
this.teleport(
this.awaitingPositionFromClient.x,
@@ -1657,6 +1700,33 @@ public class ServerGamePacketListenerImpl
@@ -1659,6 +1702,33 @@ public class ServerGamePacketListenerImpl
}
}

View File

@@ -13,7 +13,7 @@
+ public CommandNode<net.minecraft.commands.CommandSourceStack> 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.PluginCommandMeta pluginCommandMeta; // Paper - Brigadier Command API
+ public io.papermc.paper.command.brigadier.APICommandMeta apiCommandMeta; // Paper - Brigadier Command API
+ // CraftBukkit start
+ public void removeCommand(String name) {
+ this.children.remove(name);

View File

@@ -172,7 +172,7 @@
}
return null;
@@ -359,26 +_,120 @@
@@ -359,26 +_,121 @@
}
public void sendCommands(ServerPlayer player) {
@@ -252,6 +252,7 @@
+ }
+ // 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();
+ // Paper start

View File

@@ -0,0 +1,10 @@
--- a/net/minecraft/core/ClientAsset.java
+++ b/net/minecraft/core/ClientAsset.java
@@ -12,6 +_,6 @@
public static final StreamCodec<ByteBuf, ClientAsset> STREAM_CODEC = StreamCodec.composite(ResourceLocation.STREAM_CODEC, ClientAsset::id, ClientAsset::new);
public ClientAsset(ResourceLocation id) {
- this(id, id.withPath(string -> "textures/" + string + ".png"));
+ this(id, id.withPath(string -> "textures/" + string + ".png")); // Paper - diff on change - io.papermc.paper.registry.data.client.ClientAssetImpl#pathFromIdentifier
}
}

View File

@@ -1,33 +0,0 @@
--- a/net/minecraft/network/HashedStack.java
+++ b/net/minecraft/network/HashedStack.java
@@ -17,7 +_,7 @@
}
@Override
- public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
+ public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic
return stack.isEmpty();
}
};
@@ -27,7 +_,7 @@
hashedStack -> hashedStack instanceof HashedStack.ActualItem actualItem ? Optional.of(actualItem) : Optional.empty()
);
- boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator);
+ boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching); // Paper - add flag to simplify remote matching logic
static HashedStack create(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
return (HashedStack)(stack.isEmpty()
@@ -47,10 +_,10 @@
);
@Override
- public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator) {
+ public boolean matches(ItemStack stack, HashedPatchMap.HashGenerator hashGenerator, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic
return this.count == stack.getCount()
&& this.item.equals(stack.getItemHolder())
- && this.components.matches(stack.getComponentsPatch(), hashGenerator);
+ && (simplifyMatching || this.components.matches(stack.getComponentsPatch(), hashGenerator)); // Paper - add flag to simplify remote matching logic
}
}
}

View File

@@ -0,0 +1,31 @@
--- a/net/minecraft/network/syncher/EntityDataSerializers.java
+++ b/net/minecraft/network/syncher/EntityDataSerializers.java
@@ -51,10 +_,27 @@
public static final EntityDataSerializer<Optional<Component>> OPTIONAL_COMPONENT = EntityDataSerializer.forValueType(
ComponentSerialization.TRUSTED_OPTIONAL_STREAM_CODEC
);
+ // Paper start - do not obfuscate items sent as entity data
+ public static final StreamCodec<RegistryFriendlyByteBuf, ItemStack> OVERSIZED_ITEM_CODEC = new net.minecraft.network.codec.StreamCodec<>() {
+ @Override
+ public net.minecraft.world.item.ItemStack decode(final net.minecraft.network.RegistryFriendlyByteBuf buffer) {
+ return ItemStack.OPTIONAL_STREAM_CODEC.decode(buffer);
+ }
+
+ @Override
+ public void encode(final net.minecraft.network.RegistryFriendlyByteBuf buffer, final net.minecraft.world.item.ItemStack value) {
+ // If the codec is called during an obfuscation session, downgrade the context's obf level to OVERSIZED if it isn't already.
+ // Entity data cannot be fully obfuscated as entities might render out specific values (e.g. count or custom name).
+ try (final io.papermc.paper.util.SafeAutoClosable ignored = io.papermc.paper.util.sanitizer.ItemObfuscationSession.withContext(c -> c.level(io.papermc.paper.util.sanitizer.ItemObfuscationSession.ObfuscationLevel.OVERSIZED))) {
+ ItemStack.OPTIONAL_STREAM_CODEC.encode(buffer, value);
+ }
+ }
+ };
+ // Paper end - do not obfuscate items sent as entity data
public static final EntityDataSerializer<ItemStack> ITEM_STACK = new EntityDataSerializer<ItemStack>() {
@Override
public StreamCodec<? super RegistryFriendlyByteBuf, ItemStack> codec() {
- return ItemStack.OPTIONAL_STREAM_CODEC;
+ return OVERSIZED_ITEM_CODEC; // Paper - do not obfuscate items sent as entity data
}
@Override

View File

@@ -1,12 +1,13 @@
--- a/net/minecraft/server/ReloadableServerResources.java
+++ b/net/minecraft/server/ReloadableServerResources.java
@@ -38,7 +_,8 @@
@@ -38,7 +_,9 @@
this.fullRegistryHolder = new ReloadableServerRegistries.Holder(registryAccess.compositeAccess());
this.postponedTags = postponedTags;
this.recipes = new RecipeManager(registries);
- this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures));
+ this.commands = new Commands(commandSelection, CommandBuildContext.simple(registries, enabledFeatures), true); // Paper - Brigadier Command API - use modern alias registration
+ io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setDispatcher(this.commands, CommandBuildContext.simple(registries, enabledFeatures)); // Paper - Brigadier Command API
+ io.papermc.paper.command.PaperCommands.registerCommands(); // Paper
this.advancements = new ServerAdvancementManager(registries);
this.functionLibrary = new ServerFunctionLibrary(functionCompilationLevel, this.commands.getDispatcher());
}

View File

@@ -1,5 +1,13 @@
--- 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 @@
private int levitationStartTime;
private boolean disconnected;
@@ -10,7 +18,7 @@
@Nullable
private Vec3 startingToFallPosition;
@Nullable
@@ -281,6 +_,20 @@
@@ -281,6 +_,13 @@
}
}
@@ -20,26 +28,10 @@
+ ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(ServerPlayer.this.inventoryMenu.containerId, ServerPlayer.this.inventoryMenu.incrementStateId(), net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT, ServerPlayer.this.inventoryMenu.getSlot(net.minecraft.world.inventory.InventoryMenu.SHIELD_SLOT).getItem().copy()));
+ }
+ // Paper end - Sync offhand slot in menus
+
+ // Paper start - add flag to simplify remote matching logic
+ @Override
+ public ServerPlayer player() {
+ return ServerPlayer.this;
+ }
+ // Paper end - add flag to simplify remote matching logic
+
@Override
public void sendSlotChange(AbstractContainerMenu container, int slot, ItemStack itemStack) {
ServerPlayer.this.connection.send(new ClientboundContainerSetSlotPacket(container.containerId, container.incrementStateId(), slot, itemStack));
@@ -302,7 +_,7 @@
@Override
public RemoteSlot createSlot() {
- return new RemoteSlot.Synchronized(this.cache::getUnchecked);
+ return new RemoteSlot.Synchronized(this.cache::getUnchecked, ServerPlayer.this.getBukkitEntity().simplifyContainerDesyncCheck()); // Paper - add flag to simplify remote matching logic
}
};
private final ContainerListener containerListener = new ContainerListener() {
@@ -316,6 +_,32 @@
}
}
@@ -316,12 +308,19 @@
}
float saturationLevel = this.foodData.getSaturationLevel();
@@ -793,15 +_,84 @@
@@ -793,15 +_,36 @@
}
private void updateScoreForCriteria(ObjectiveCriteria criteria, int points) {
- this.getScoreboard().forAllObjectives(criteria, this, score -> score.set(points));
- }
-
- @Override
- public void die(DamageSource cause) {
- this.gameEvent(GameEvent.ENTITY_DIE);
- boolean _boolean = this.serverLevel().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
+ }
+
@@ -348,13 +347,24 @@
+ return false;
+ }
+ // Paper end - PlayerDeathEvent#getItemsToKeep
@Override
public void die(DamageSource cause) {
- this.gameEvent(GameEvent.ENTITY_DIE);
- boolean _boolean = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES);
- if (_boolean) {
- Component deathMessage = this.getCombatTracker().getDeathMessage();
+ // Paper start - Expand PlayerDeathEvent API
+ private void sendClientboundPlayerCombatKillPacket(boolean displayMessage, Component deathMessage) {
+ if (displayMessage && deathMessage != CommonComponents.EMPTY) {
+ // Paper - moved from below die(DamageSource) method
this.connection
.send(
new ClientboundPlayerCombatKillPacket(this.getId(), deathMessage),
@@ -818,6 +_,65 @@
}
)
);
+ } else {
+ this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), CommonComponents.EMPTY));
+ }
+ }
+ // Paper end - Expand PlayerDeathEvent API
+ @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
+ // CraftBukkit start - fire PlayerDeathEvent
@@ -382,7 +392,7 @@
+
+ String deathmessage = defaultMessage.getString();
+ this.keepLevel = keepInventory; // SPIGOT-2222: pre-set keepLevel
+ org.bukkit.event.entity.PlayerDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerDeathEvent(this, cause, loot, io.papermc.paper.adventure.PaperAdventure.asAdventure(defaultMessage), keepInventory); // Paper - Adventure
+ org.bukkit.event.entity.PlayerDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callPlayerDeathEvent(this, cause, loot, io.papermc.paper.adventure.PaperAdventure.asAdventure(defaultMessage), showDeathMessage, keepInventory); // Paper - Adventure; Expand PlayerDeathEvent API
+ // Paper start - cancellable death event
+ if (event.isCancelled()) {
+ // make compatible with plugins that might have already set the health in an event listener
@@ -400,13 +410,25 @@
+ }
+
+ net.kyori.adventure.text.Component apiDeathMessage = event.deathMessage() != null ? event.deathMessage() : net.kyori.adventure.text.Component.empty(); // Paper - Adventure
+ Component deathScreenMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(event.deathScreenMessageOverride() != null ? event.deathScreenMessageOverride() : apiDeathMessage); // Paper - Expand PlayerDeathEvent API
+
+ if (apiDeathMessage != null && apiDeathMessage != net.kyori.adventure.text.Component.empty() && showDeathMessage) { // Paper - Adventure // TODO: allow plugins to override?
+ if (apiDeathMessage != null && apiDeathMessage != net.kyori.adventure.text.Component.empty() && event.getShowDeathMessages()) { // Paper - Adventure; Expand PlayerDeathEvent API
+ Component deathMessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(apiDeathMessage); // Paper - Adventure
+
this.connection
.send(
new ClientboundPlayerCombatKillPacket(this.getId(), deathMessage),
+ // Paper - moved up to sendClientboundPlayerCombatKillPacket()
+ sendClientboundPlayerCombatKillPacket(event.getShowDeathMessages(), deathScreenMessage); // Paper - Expand PlayerDeathEvent
Team team = this.getTeam();
if (team == null || team.getDeathMessageVisibility() == Team.Visibility.ALWAYS) {
this.server.getPlayerList().broadcastSystemMessage(deathMessage, false);
@@ -827,7 +_,7 @@
this.server.getPlayerList().broadcastSystemToAllExceptTeam(this, deathMessage);
}
} else {
- this.connection.send(new ClientboundPlayerCombatKillPacket(this.getId(), CommonComponents.EMPTY));
+ sendClientboundPlayerCombatKillPacket(event.getShowDeathMessages(), deathScreenMessage); // Paper - Expand PlayerDeathEvent
}
this.removeEntitiesOnShoulder();
@@ -835,11 +_,35 @@
this.tellNeutralMobsThatIDied();
}
@@ -491,7 +513,7 @@
}
}
@@ -914,23 +_,82 @@
@@ -914,23 +_,77 @@
}
private boolean isPvpAllowed() {
@@ -541,18 +563,13 @@
+ );
+
+ // Paper start - respawn flags
+ com.google.common.collect.ImmutableSet.Builder<org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag> builder = com.google.common.collect.ImmutableSet.builder();
+ if (respawnReason == org.bukkit.event.player.PlayerRespawnEvent.RespawnReason.END_PORTAL) {
+ builder.add(org.bukkit.event.player.PlayerRespawnEvent.RespawnFlag.END_PORTAL);
+ }
+ org.bukkit.event.player.PlayerRespawnEvent respawnEvent = new org.bukkit.event.player.PlayerRespawnEvent(
+ respawnPlayer,
+ location,
+ isBedSpawn,
+ isAnchorSpawn,
+ teleportTransition.missingRespawnBlock(),
+ respawnReason,
+ builder
+ respawnReason
+ );
+ // Paper end - respawn flags
+ this.level().getCraftServer().getPluginManager().callEvent(respawnEvent);

View File

@@ -523,7 +523,7 @@
this.player.sendSystemMessage(Component.translatable("advMode.notAllowed"));
} else {
BaseCommandBlock commandBlock = packet.getCommandBlock(this.player.level());
@@ -661,7 +_,7 @@
@@ -661,11 +_,11 @@
boolean flag = this.player.hasInfiniteMaterials() && packet.includeData();
ItemStack cloneItemStack = blockState.getCloneItemStack(serverLevel, blockPos, flag);
if (!cloneItemStack.isEmpty()) {
@@ -532,7 +532,23 @@
addBlockDataToItem(blockState, serverLevel, blockPos, cloneItemStack);
}
@@ -698,18 +_,29 @@
- this.tryPickItem(cloneItemStack);
+ this.tryPickItem(cloneItemStack, blockPos, null, packet.includeData()); // Paper - Extend PlayerPickItemEvent API
}
}
}
@@ -689,27 +_,40 @@
if (entityOrPart != null && this.player.canInteractWithEntity(entityOrPart, 3.0)) {
ItemStack pickResult = entityOrPart.getPickResult();
if (pickResult != null && !pickResult.isEmpty()) {
- this.tryPickItem(pickResult);
+ this.tryPickItem(pickResult, null, entityOrPart, packet.includeData()); // Paper - Extend PlayerPickItemEvent API
}
}
}
- private void tryPickItem(ItemStack stack) {
+ private void tryPickItem(ItemStack stack, @Nullable BlockPos blockPos, @Nullable Entity entity, boolean includeData) { // Paper - Extend PlayerPickItemEvent API
if (stack.isItemEnabled(this.player.level().enabledFeatures())) {
Inventory inventory = this.player.getInventory();
int i = inventory.findSlotMatchingItem(stack);
@@ -540,7 +556,9 @@
+ final int sourceSlot = i;
+ final int targetSlot = Inventory.isHotbarSlot(sourceSlot) ? sourceSlot : inventory.getSuitableHotbarSlot();
+ final org.bukkit.entity.Player bukkitPlayer = this.player.getBukkitEntity();
+ final io.papermc.paper.event.player.PlayerPickItemEvent event = new io.papermc.paper.event.player.PlayerPickItemEvent(bukkitPlayer, targetSlot, sourceSlot);
+ final io.papermc.paper.event.player.PlayerPickItemEvent event = entity != null
+ ? new io.papermc.paper.event.player.PlayerPickEntityEvent(bukkitPlayer, entity.getBukkitEntity(), includeData, targetSlot, sourceSlot)
+ : new io.papermc.paper.event.player.PlayerPickBlockEvent(bukkitPlayer, org.bukkit.craftbukkit.block.CraftBlock.at(this.player.level(), blockPos), includeData, targetSlot, sourceSlot);
+ if (!event.callEvent()) {
+ return;
+ }
@@ -2468,7 +2486,7 @@
} else if (flag && flag2) {
if (this.dropSpamThrottler.isUnderThreshold()) {
this.dropSpamThrottler.increment();
@@ -1895,11 +_,24 @@
@@ -1895,15 +_,38 @@
@Override
public void handleSignUpdate(ServerboundSignUpdatePacket packet) {
@@ -2494,6 +2512,20 @@
this.player.resetLastActionTime();
ServerLevel serverLevel = this.player.serverLevel();
BlockPos pos = packet.getPos();
if (serverLevel.hasChunkAt(pos)) {
+ // Paper start - Add API for client-side signs
+ if (!new io.papermc.paper.event.packet.UncheckedSignChangeEvent(
+ this.player.getBukkitEntity(),
+ io.papermc.paper.util.MCUtil.toPosition(pos),
+ packet.isFrontText() ? org.bukkit.block.sign.Side.FRONT : org.bukkit.block.sign.Side.BACK,
+ filteredText.stream().<net.kyori.adventure.text.Component>map(line -> net.kyori.adventure.text.Component.text(line.raw())).toList())
+ .callEvent()) {
+ return;
+ }
+ // Paper end - Add API for client-side signs
if (!(serverLevel.getBlockEntity(pos) instanceof SignBlockEntity signBlockEntity)) {
return;
}
@@ -1915,14 +_,32 @@
@Override
public void handlePlayerAbilities(ServerboundPlayerAbilitiesPacket packet) {

View File

@@ -9,10 +9,10 @@
+ static final java.util.regex.Pattern HOST_PATTERN = java.util.regex.Pattern.compile("[0-9a-f\\.:]{0,45}");
+ static final java.util.regex.Pattern PROP_PATTERN = java.util.regex.Pattern.compile("\\w{0,16}");
+ // Spigot end
+ // CraftBukkit start - add fields
+ private static final java.util.HashMap<java.net.InetAddress, Long> throttleTracker = new java.util.HashMap<>();
+ // Paper start - Connection throttle
+ private static final java.util.Map<java.net.InetAddress, Long> throttleTracker = new java.util.HashMap<>();
+ private static int throttleCounter = 0;
+ // CraftBukkit end
+ // Paper end - Connection throttle
+ private static final boolean BYPASS_HOSTCHECK = Boolean.getBoolean("Paper.bypassHostCheck"); // Paper
private final MinecraftServer server;
private final Connection connection;
@@ -29,7 +29,7 @@
switch (packet.intention()) {
case LOGIN:
this.beginLogin(packet, false);
@@ -50,22 +_,117 @@
@@ -50,22 +_,118 @@
default:
throw new UnsupportedOperationException("Invalid intention " + packet.intention());
}
@@ -42,17 +42,18 @@
private void beginLogin(ClientIntentionPacket packet, boolean transferred) {
this.connection.setupOutboundProtocol(LoginProtocols.CLIENTBOUND);
+ // CraftBukkit start - Connection throttle
+ // Paper start - Connection throttle
+ try {
+ if (!(this.connection.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress)) { // Paper - Unix domain socket support; the connection throttle is useless when you have a Unix domain socket
+ final long connectionThrottle = this.server.server.getConnectionThrottle();
+ final boolean isUnixDomainSocket = this.connection.channel.localAddress() instanceof io.netty.channel.unix.DomainSocketAddress; // Paper - Unix domain socket support; the connection throttle is useless when you have a Unix domain socket
+ if (connectionThrottle > 0 && !isUnixDomainSocket && this.connection.getRemoteAddress() instanceof java.net.InetSocketAddress socketAddress && !socketAddress.isUnresolved() && !socketAddress.getAddress().isLoopbackAddress()) {
+ long currentTime = System.currentTimeMillis();
+ long connectionThrottle = this.server.server.getConnectionThrottle();
+ java.net.InetAddress address = ((java.net.InetSocketAddress) this.connection.getRemoteAddress()).getAddress();
+ java.net.InetAddress address = socketAddress.getAddress();
+
+ synchronized (ServerHandshakePacketListenerImpl.throttleTracker) {
+ if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) {
+ if (ServerHandshakePacketListenerImpl.throttleTracker.containsKey(address) && currentTime - ServerHandshakePacketListenerImpl.throttleTracker.get(address) < connectionThrottle) {
+ ServerHandshakePacketListenerImpl.throttleTracker.put(address, currentTime);
+ Component chatmessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.connectionThrottle); // Paper - Configurable connection throttle kick message
+ Component chatmessage = io.papermc.paper.adventure.PaperAdventure.asVanilla(io.papermc.paper.configuration.GlobalConfiguration.get().messages.kick.connectionThrottle);
+ this.connection.send(new ClientboundLoginDisconnectPacket(chatmessage));
+ this.connection.disconnect(chatmessage);
+ return;
@@ -67,11 +68,11 @@
+ ServerHandshakePacketListenerImpl.throttleTracker.values().removeIf(time -> time > connectionThrottle);
+ }
+ }
+ } // Paper - Unix domain socket support
+ }
+ } catch (Throwable t) {
+ org.apache.logging.log4j.LogManager.getLogger().debug("Failed to check connection throttle", t);
+ }
+ // CraftBukkit end
+ // Paper end - Connection throttle
if (packet.protocolVersion() != SharedConstants.getCurrentVersion().getProtocolVersion()) {
- Component component;
- if (packet.protocolVersion() < 754) {

View File

@@ -524,7 +524,7 @@
IpBanListEntry ipBanListEntry = this.ipBans.get(socketAddress);
MutableComponent mutableComponent = Component.translatable("multiplayer.disconnect.banned_ip.reason", ipBanListEntry.getReason());
if (ipBanListEntry.getExpires() != null) {
@@ -381,69 +_,130 @@
@@ -381,69 +_,131 @@
);
}
@@ -649,6 +649,7 @@
+ // Paper start - Add PlayerPostRespawnEvent
+ boolean isBedSpawn = false;
+ boolean isRespawn = false;
+ boolean isAnchorSpawn = false;
+ // Paper end - Add PlayerPostRespawnEvent
+
+ // CraftBukkit start - fire PlayerRespawnEvent
@@ -714,13 +715,17 @@
serverPlayer.setHealth(serverPlayer.getHealth());
ServerPlayer.RespawnConfig respawnConfig = serverPlayer.getRespawnConfig();
if (!keepInventory && respawnConfig != null) {
@@ -477,8 +_,41 @@
@@ -477,8 +_,52 @@
)
);
}
+ // Paper start - Add PlayerPostRespawnEvent
+ if (blockState.is(net.minecraft.tags.BlockTags.BEDS) && !teleportTransition.missingRespawnBlock()) {
+ isBedSpawn = true;
+ if (!teleportTransition.missingRespawnBlock()) {
+ if (blockState.is(net.minecraft.tags.BlockTags.BEDS)) {
+ isBedSpawn = true;
+ } else if (blockState.is(Blocks.RESPAWN_ANCHOR)) {
+ isAnchorSpawn = true;
+ }
+ }
+ // Paper end - Add PlayerPostRespawnEvent
}
@@ -748,7 +753,14 @@
+
+ // Paper start - Add PlayerPostRespawnEvent
+ if (isRespawn) {
+ cserver.getPluginManager().callEvent(new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(player.getBukkitEntity(), location, isBedSpawn));
+ new com.destroystokyo.paper.event.player.PlayerPostRespawnEvent(
+ player.getBukkitEntity(),
+ location,
+ isBedSpawn,
+ isAnchorSpawn,
+ teleportTransition.missingRespawnBlock(),
+ eventReason
+ ).callEvent();
+ }
+ // Paper end - Add PlayerPostRespawnEvent
+

View File

@@ -1,16 +1,22 @@
--- a/net/minecraft/util/datafix/DataFixers.java
+++ b/net/minecraft/util/datafix/DataFixers.java
@@ -541,6 +_,18 @@
@@ -541,6 +_,24 @@
Schema schema44 = builder.addSchema(1456, SAME_NAMESPACED);
builder.addFixer(new EntityItemFrameDirectionFix(schema44, false));
Schema schema45 = builder.addSchema(1458, V1458::new);
+ // CraftBukkit start
+ builder.addFixer(new com.mojang.datafixers.DataFix(schema45, false) {
+ // API allows setting player custom names, so we need to convert them.
+ // This does *not* handle upgrades in any other version, but generally those shouldn't need conversion.
+ builder.addFixer(new DataFix(schema45, false) {
+ @Override
+ protected com.mojang.datafixers.TypeRewriteRule makeRule() {
+ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(References.PLAYER), (typed) -> {
+ return typed.update(DSL.remainderFinder(), (dynamic) -> {
+ return EntityCustomNameToComponentFix.fixCustomName(dynamic.getOps(), dynamic.get("CustomName").asString(""), "minecraft:player");
+ protected TypeRewriteRule makeRule() {
+ return this.fixTypeEverywhereTyped("Player CustomName", this.getInputSchema().getType(References.PLAYER), typed -> {
+ return typed.update(DSL.remainderFinder(), dynamic -> {
+ final String customName = dynamic.get("CustomName").asString("");
+ if (customName.isEmpty()) {
+ return dynamic.remove("CustomName");
+ }
+ return dynamic.set("CustomName", LegacyComponentDataFixUtils.createPlainTextComponent(dynamic.getOps(), customName));
+ });
+ });
+ }

View File

@@ -0,0 +1,10 @@
--- 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

@@ -0,0 +1,41 @@
--- a/net/minecraft/world/damagesource/CombatTracker.java
+++ b/net/minecraft/world/damagesource/CombatTracker.java
@@ -29,15 +_,24 @@
private int combatEndTime;
public boolean inCombat;
public boolean takingDamage;
+ public final io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper paperCombatTracker; // Paper - Combat tracker API
public CombatTracker(LivingEntity mob) {
this.mob = mob;
+ this.paperCombatTracker = new io.papermc.paper.world.damagesource.PaperCombatTrackerWrapper(this); // Paper - Combat tracker API
}
public void recordDamage(DamageSource source, float damage) {
this.recheckStatus();
FallLocation currentFallLocation = FallLocation.getCurrentFallLocation(this.mob);
CombatEntry combatEntry = new CombatEntry(source, damage, currentFallLocation, (float)this.mob.fallDistance);
+ // Paper start - Combat tracker API
+ recordDamageAndCheckCombatState(combatEntry);
+ }
+
+ public void recordDamageAndCheckCombatState(final CombatEntry combatEntry) {
+ final DamageSource source = combatEntry.source();
+ // Paper end - Combat tracker API
this.entries.add(combatEntry);
this.lastDamageTime = this.mob.tickCount;
this.takingDamage = true;
@@ -147,6 +_,13 @@
public void recheckStatus() {
int i = this.inCombat ? 300 : 100;
if (this.takingDamage && (!this.mob.isAlive() || this.mob.tickCount - this.lastDamageTime > i)) {
+ // Paper start - Combat tracker API
+ resetCombatState();
+ }
+ }
+
+ public void resetCombatState() {{
+ // Paper end - Combat tracker API
boolean flag = this.inCombat;
this.takingDamage = false;
this.inCombat = false;

View File

@@ -126,6 +126,15 @@
private final double[] pistonDeltas = new double[]{0.0, 0.0, 0.0};
private long pistonDeltasGameTime;
private EntityDimensions dimensions;
@@ -251,7 +_,7 @@
private boolean onGroundNoBlocks = false;
private float crystalSoundIntensity;
private int lastCrystalSoundPlayTick;
- public boolean hasVisualFire;
+ public net.kyori.adventure.util.TriState visualFire = net.kyori.adventure.util.TriState.NOT_SET; // Paper - improve visual fire API
@Nullable
private BlockState inBlockState = null;
private final List<List<Entity.Movement>> movementThisTick = new ObjectArrayList<>();
@@ -259,6 +_,41 @@
private final LongSet visitedBlocks = new LongOpenHashSet();
private final InsideBlockEffectApplier.StepBasedCollector insideEffectCollector = new InsideBlockEffectApplier.StepBasedCollector();
@@ -392,7 +401,12 @@
}
this.checkBelowWorld();
@@ -504,7 +_,12 @@
@@ -500,11 +_,16 @@
}
public void setSharedFlagOnFire(boolean isOnFire) {
- this.setSharedFlag(0, isOnFire || this.hasVisualFire);
+ this.setSharedFlag(0, this.visualFire.toBooleanOrElse(isOnFire)); // Paper - improve visual fire API
}
public void checkBelowWorld() {
@@ -694,7 +708,7 @@
return true;
}
}
@@ -1805,14 +_,34 @@
@@ -1805,14 +_,35 @@
}
public CompoundTag saveWithoutId(CompoundTag compound) {
@@ -715,6 +729,7 @@
}
+ } // CraftBukkit
+ this.setDeltaMovement(io.papermc.paper.util.MCUtil.sanitizeNanInf(this.deltaMovement, 0D)); // Paper - remove NaN values before usage in saving
compound.store("Motion", Vec3.CODEC, this.getDeltaMovement());
+ // CraftBukkit start - Checking for NaN pitch/yaw and resetting to zero
+ // TODO: make sure this is the best way to address this.
@@ -760,6 +775,21 @@
Component customName = this.getCustomName();
if (customName != null) {
RegistryOps<Tag> registryOps = this.registryAccess().createSerializationContext(NbtOps.INSTANCE);
@@ -1848,9 +_,12 @@
compound.putInt("TicksFrozen", this.getTicksFrozen());
}
- if (this.hasVisualFire) {
- compound.putBoolean("HasVisualFire", this.hasVisualFire);
+ // Paper start - improve visual fire API
+ if (this.visualFire.equals(net.kyori.adventure.util.TriState.TRUE)) {
+ compound.putBoolean("HasVisualFire", true);
}
+ compound.putString("Paper.FireOverride", visualFire.name());
+ // Paper end
if (!this.tags.isEmpty()) {
compound.store("Tags", TAG_LIST_CODEC, List.copyOf(this.tags));
@@ -1860,13 +_,13 @@
compound.store("data", CustomData.CODEC, this.customData);
}
@@ -810,6 +840,37 @@
return compound;
} catch (Throwable var8) {
CrashReport crashReport = CrashReport.forThrowable(var8, "Saving entity NBT");
@@ -1888,7 +_,7 @@
public void load(CompoundTag compound) {
try {
Vec3 vec3 = compound.read("Pos", Vec3.CODEC).orElse(Vec3.ZERO);
- Vec3 vec31 = compound.read("Motion", Vec3.CODEC).orElse(Vec3.ZERO);
+ Vec3 vec31 = compound.read("Motion", Vec3.CODEC).orElse(Vec3.ZERO); vec31 = io.papermc.paper.util.MCUtil.sanitizeNanInf(vec31, 0D); // Paper - avoid setting NaN values
Vec2 vec2 = compound.read("Rotation", Vec2.CODEC).orElse(Vec2.ZERO);
this.setDeltaMovement(Math.abs(vec31.x) > 10.0 ? 0.0 : vec31.x, Math.abs(vec31.y) > 10.0 ? 0.0 : vec31.y, Math.abs(vec31.z) > 10.0 ? 0.0 : vec31.z);
this.hasImpulse = true;
@@ -1921,7 +_,20 @@
this.setNoGravity(compound.getBooleanOr("NoGravity", false));
this.setGlowingTag(compound.getBooleanOr("Glowing", false));
this.setTicksFrozen(compound.getIntOr("TicksFrozen", 0));
- this.hasVisualFire = compound.getBooleanOr("HasVisualFire", false);
+ // Paper start - improve visual fire API
+ compound.getString("Paper.FireOverride").ifPresentOrElse(
+ override -> {
+ try {
+ this.visualFire = net.kyori.adventure.util.TriState.valueOf(override);
+ } catch (final Exception ignored) {
+ LOGGER.error("Unknown fire override {} for {}", override, this);
+ }
+ },
+ () -> this.visualFire = compound.getBoolean("HasVisualFire")
+ .map(net.kyori.adventure.util.TriState::byBoolean)
+ .orElse(net.kyori.adventure.util.TriState.NOT_SET)
+ );
+ // Paper end
this.customData = compound.read("data", CustomData.CODEC).orElse(CustomData.EMPTY);
this.tags.clear();
compound.read("Tags", TAG_LIST_CODEC).ifPresent(this.tags::addAll);
@@ -1932,6 +_,67 @@
} else {
throw new IllegalStateException("Entity has invalid rotation");

View File

@@ -97,7 +97,7 @@
Vec3 vec3 = new Vec3(
this.followingPlayer.getX() - this.getX(),
this.followingPlayer.getY() + this.followingPlayer.getEyeHeight() / 2.0 - this.getY(),
@@ -161,16 +_,27 @@
@@ -161,18 +_,29 @@
}
public static void award(ServerLevel level, Vec3 pos, int amount) {
@@ -124,9 +124,17 @@
private static boolean tryMergeToExisting(ServerLevel level, Vec3 pos, int amount) {
+ // Paper - TODO some other event for this kind of merge
AABB aabb = AABB.ofSize(pos, 1.0, 1.0, 1.0);
int randomInt = level.getRandom().nextInt(40);
- 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));
@@ -193,9 +_,14 @@
if (!entities.isEmpty()) {
ExperienceOrb experienceOrb = entities.get(0);
@@ -189,13 +_,18 @@
}
private static boolean canMerge(ExperienceOrb orb, int amount, int other) {
- return !orb.isRemoved() && (orb.getId() - amount) % 40 == 0 && orb.getValue() == other;
+ return !orb.isRemoved() && (orb.getId() - amount) % io.papermc.paper.configuration.GlobalConfiguration.get().misc.xpOrbGroupsPerArea.or(ORB_GROUPS_PER_AREA) == 0 && orb.getValue() == other; // Paper - Configure how many orbs will merge together
}
private void merge(ExperienceOrb orb) {

View File

@@ -198,7 +198,7 @@
}
return true;
@@ -400,31 +_,34 @@
@@ -400,31 +_,42 @@
float health = this.getHealth();
health -= damageAmount;
if (health <= 0.5F) {
@@ -231,13 +231,24 @@
+ // this.dropAllDeathLoot(level, damageSource); // CraftBukkit - moved down
for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
ItemStack itemStack = this.equipment.set(equipmentSlot, ItemStack.EMPTY);
- ItemStack itemStack = this.equipment.set(equipmentSlot, ItemStack.EMPTY);
+ ItemStack itemStack = this.equipment.get(equipmentSlot); // Paper - move equipment removal past event call
if (!itemStack.isEmpty()) {
- Block.popResource(this.level(), this.blockPosition().above(), itemStack);
- }
- }
+ this.drops.add(new DefaultDrop(itemStack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly}
}
}
+ return this.dropAllDeathLoot(level, damageSource); // CraftBukkit - moved from above // Paper
+ }
+ }
+ // Paper start - move equipment removal past event call
+ org.bukkit.event.entity.EntityDeathEvent event = this.dropAllDeathLoot(level, damageSource);
+ if (!event.isCancelled()) {
+ for (EquipmentSlot equipmentSlot : EquipmentSlot.VALUES) {
+ this.equipment.set(equipmentSlot, ItemStack.EMPTY);
+ }
+ }
+ return event;
+ // Paper end - move equipment removal past event call
}
private void playBrokenSound() {

View File

@@ -48,7 +48,7 @@
double squareRoot = Math.sqrt(d * d + d2 * d2);
if (this.level() instanceof ServerLevel serverLevel) {
+ // CraftBukkit start
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), arrow.getPickupItem(), arrow, net.minecraft.world.InteractionHand.MAIN_HAND, 0.8F, true); // Paper - improve entity shoot bow event, add arrow stack to event
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), arrow.getPickupItem(), arrow, net.minecraft.world.InteractionHand.MAIN_HAND, distanceFactor, true); // Paper - improve entity shoot bow event, add arrow stack to event
+ if (event.isCancelled()) {
+ event.getProjectile().remove();
+ return;

View File

@@ -56,7 +56,20 @@
this.setTarget(null);
this.teleport();
}
@@ -369,11 +_,13 @@
@@ -359,21 +_,25 @@
AbstractThrownPotion abstractThrownPotion1 = damageSource.getDirectEntity() instanceof AbstractThrownPotion abstractThrownPotion
? abstractThrownPotion
: null;
- if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && abstractThrownPotion1 == null) {
+ if (!damageSource.is(DamageTypeTags.IS_PROJECTILE) && abstractThrownPotion1 == null) { // Paper - EndermanEscapeEvent - diff on change - below logic relies on this path covering non-projectile damage.
boolean flag = super.hurtServer(level, damageSource, amount);
if (!(damageSource.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) {
+ if (this.tryEscape(damageSource.is(net.minecraft.tags.DamageTypeTags.IS_DROWNING) ? com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.DROWN : com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.CRITICAL_HIT)) { // Paper - EndermanEscapeEvent
this.teleport();
+ } // Paper - EndermanEscapeEvent
}
return flag;
} else {
boolean flag = abstractThrownPotion1 != null && this.hurtWithCleanWater(level, damageSource, abstractThrownPotion1, amount);

View File

@@ -5,7 +5,7 @@
double squareRoot = Math.sqrt(d * d + d2 * d2);
if (this.level() instanceof ServerLevel serverLevel) {
+ // Paper start - EntityShootBowEvent
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), mobArrow.getPickupItem(), mobArrow, target.getUsedItemHand(), 0.8F, true);
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), mobArrow.getPickupItem(), mobArrow, target.getUsedItemHand(), distanceFactor, true);
+ if (event.isCancelled()) {
+ event.getProjectile().remove();
+ return;

View File

@@ -66,7 +66,7 @@
+ // CraftBukkit end
+ }
+ // CraftBukkit start
+ if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, slimes, org.bukkit.event.entity.EntityTransformEvent.TransformReason.SPLIT).isCancelled()) {
+ if (!slimes.isEmpty() && org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTransformEvent(this, slimes, org.bukkit.event.entity.EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { // check for empty converted entities or cancel event
+ super.remove(reason, eventCause); // add Bukkit remove cause
+ return;
+ }

View File

@@ -42,6 +42,29 @@
return;
}
} else {
@@ -166,12 +_,14 @@
if (this.currentState == FishingHook.FishHookState.FLYING) {
if (this.hookedIn != null) {
this.setDeltaMovement(Vec3.ZERO);
+ new io.papermc.paper.event.entity.FishHookStateChangeEvent((org.bukkit.entity.FishHook) getBukkitEntity(), org.bukkit.entity.FishHook.HookState.HOOKED_ENTITY).callEvent(); // Paper - Add FishHookStateChangeEvent. #HOOKED_ENTITY
this.currentState = FishingHook.FishHookState.HOOKED_IN_ENTITY;
return;
}
if (flag) {
this.setDeltaMovement(this.getDeltaMovement().multiply(0.3, 0.2, 0.3));
+ new io.papermc.paper.event.entity.FishHookStateChangeEvent((org.bukkit.entity.FishHook) getBukkitEntity(), org.bukkit.entity.FishHook.HookState.BOBBING).callEvent(); // Paper - Add FishHookStateChangeEvent. #BOBBING
this.currentState = FishingHook.FishHookState.BOBBING;
return;
}
@@ -184,6 +_,7 @@
this.setPos(this.hookedIn.getX(), this.hookedIn.getY(0.8), this.hookedIn.getZ());
} else {
this.setHookedEntity(null);
+ new io.papermc.paper.event.entity.FishHookStateChangeEvent((org.bukkit.entity.FishHook) getBukkitEntity(), org.bukkit.entity.FishHook.HookState.UNHOOKED).callEvent(); // Paper - Add FishHookStateChangeEvent. #UNHOOKED
this.currentState = FishingHook.FishHookState.FLYING;
}
}
@@ -247,14 +_,14 @@
if (!player.isRemoved() && player.isAlive() && (isFishingRod || isFishingRod1) && !(this.distanceToSqr(player) > 1024.0)) {
return false;

View File

@@ -13,11 +13,12 @@
public static final SpawnPlacementType RAVAGER_SPAWN_PLACEMENT_TYPE = SpawnPlacements.getPlacementType(EntityType.RAVAGER);
public static final MapCodec<Raid> MAP_CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
@@ -74,6 +_,7 @@
@@ -74,6 +_,8 @@
Raid.RaidStatus.CODEC.fieldOf("status").forGetter(raid -> raid.status),
BlockPos.CODEC.fieldOf("center").forGetter(raid -> raid.center),
UUIDUtil.CODEC_SET.fieldOf("heroes_of_the_village").forGetter(raid -> raid.heroesOfTheVillage)
+ , org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer.createCodec(PDC_TYPE_REGISTRY).fieldOf(PDC_NBT_KEY).forGetter(raid -> raid.persistentDataContainer)
+ , org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer.createCodec(PDC_TYPE_REGISTRY).lenientOptionalFieldOf(PDC_NBT_KEY) // Paper - add persistent data container
+ .forGetter(raid -> raid.persistentDataContainer.isEmpty() ? java.util.Optional.empty() : java.util.Optional.of(raid.persistentDataContainer)) // Paper - add persistent data container
)
.apply(instance, Raid::new)
);
@@ -33,7 +34,7 @@
Raid.RaidStatus status,
BlockPos center,
Set<UUID> heroesOfTheVillage
+ , final org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer persistentDataContainer // Paper - add persistent data container
+ , final Optional<org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer> persistentDataContainer // Paper - add persistent data container
) {
this.started = started;
this.active = active;
@@ -41,7 +42,7 @@
this.numGroups = numGroups;
this.status = status;
this.heroesOfTheVillage.addAll(heroesOfTheVillage);
+ this.persistentDataContainer = persistentDataContainer; // Paper - add persistent data container
+ this.persistentDataContainer = persistentDataContainer.orElseGet(() -> new org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer(PDC_TYPE_REGISTRY)); // Paper - add persistent data container
}
public boolean isOver() {

View File

@@ -1,15 +1,9 @@
--- a/net/minecraft/world/inventory/ContainerSynchronizer.java
+++ b/net/minecraft/world/inventory/ContainerSynchronizer.java
@@ -13,4 +_,12 @@
@@ -13,4 +_,6 @@
void sendDataChange(AbstractContainerMenu container, int id, int value);
RemoteSlot createSlot();
+
+ default void sendOffHandSlotChange() {} // Paper - Sync offhand slot in menus
+
+ // Paper start - add flag to simplify remote matching logic
+ default net.minecraft.server.level.@org.jspecify.annotations.Nullable ServerPlayer player() {
+ return null;
+ }
+ // Paper end - add flag to simplify remote matching logic
}

View File

@@ -1,27 +0,0 @@
--- a/net/minecraft/world/inventory/RemoteSlot.java
+++ b/net/minecraft/world/inventory/RemoteSlot.java
@@ -29,12 +_,14 @@
public static class Synchronized implements RemoteSlot {
private final HashedPatchMap.HashGenerator hasher;
+ private final boolean simplifyMatching; // Paper - add flag to simplify remote matching logic
@Nullable
private ItemStack remoteStack = null;
@Nullable
private HashedStack remoteHash = null;
- public Synchronized(HashedPatchMap.HashGenerator hasher) {
+ public Synchronized(HashedPatchMap.HashGenerator hasher, final boolean simplifyMatching) { // Paper - add flag to simplify remote matching logic
+ this.simplifyMatching = simplifyMatching; // Paper - add flag to simplify remote matching logic
this.hasher = hasher;
}
@@ -54,7 +_,7 @@
public boolean matches(ItemStack stack) {
if (this.remoteStack != null) {
return ItemStack.matches(this.remoteStack, stack);
- } else if (this.remoteHash != null && this.remoteHash.matches(stack, this.hasher)) {
+ } else if (this.remoteHash != null && this.remoteHash.matches(stack, this.hasher, this.simplifyMatching)) { // Paper - add flag to simplify remote matching logic
this.remoteStack = stack.copy();
return true;
} else {

View File

@@ -0,0 +1,11 @@
--- a/net/minecraft/world/item/BowItem.java
+++ b/net/minecraft/world/item/BowItem.java
@@ -38,7 +_,7 @@
} else {
List<ItemStack> list = draw(stack, projectile, player);
if (level instanceof ServerLevel serverLevel && !list.isEmpty()) {
- this.shoot(serverLevel, player, player.getUsedItemHand(), stack, list, powerForTime * 3.0F, 1.0F, powerForTime == 1.0F, null);
+ this.shoot(serverLevel, player, player.getUsedItemHand(), stack, list, powerForTime * 3.0F, 1.0F, powerForTime == 1.0F, null, powerForTime); // Paper - Pass draw strength
}
level.playSound(

View File

@@ -30,6 +30,15 @@
} else {
Projectile projectile = super.createProjectile(level, shooter, weapon, ammo, isCrit);
if (projectile instanceof AbstractArrow abstractArrow) {
@@ -163,7 +_,7 @@
if (level instanceof ServerLevel serverLevel) {
ChargedProjectiles chargedProjectiles = weapon.set(DataComponents.CHARGED_PROJECTILES, ChargedProjectiles.EMPTY);
if (chargedProjectiles != null && !chargedProjectiles.isEmpty()) {
- this.shoot(serverLevel, shooter, hand, weapon, chargedProjectiles.getItems(), velocity, inaccuracy, shooter instanceof Player, target);
+ this.shoot(serverLevel, shooter, hand, weapon, chargedProjectiles.getItems(), velocity, inaccuracy, shooter instanceof Player, target, 1); // Paper - Pass draw strength
if (shooter instanceof ServerPlayer serverPlayer) {
CriteriaTriggers.SHOT_CROSSBOW.trigger(serverPlayer, weapon);
serverPlayer.awardStat(Stats.ITEM_USED.get(weapon.getItem()));
@@ -211,7 +_,14 @@
);
}

View File

@@ -0,0 +1,19 @@
--- a/net/minecraft/world/item/EmptyMapItem.java
+++ b/net/minecraft/world/item/EmptyMapItem.java
@@ -17,10 +_,16 @@
public InteractionResult use(Level level, Player player, InteractionHand hand) {
ItemStack itemInHand = player.getItemInHand(hand);
if (level instanceof ServerLevel serverLevel) {
+ org.bukkit.inventory.ItemStack emptyMap = itemInHand.asBukkitCopy(); // Paper - PlayerMapFilledEvent
itemInHand.consume(1, player);
player.awardStat(Stats.ITEM_USED.get(this));
serverLevel.playSound(null, player, SoundEvents.UI_CARTOGRAPHY_TABLE_TAKE_RESULT, player.getSoundSource(), 1.0F, 1.0F);
ItemStack itemStack = MapItem.create(serverLevel, player.getBlockX(), player.getBlockZ(), (byte)0, true, false);
+ // Paper start - PlayerMapFilledEvent
+ io.papermc.paper.event.player.PlayerMapFilledEvent event = new io.papermc.paper.event.player.PlayerMapFilledEvent((org.bukkit.entity.Player) player.getBukkitEntity(), emptyMap, org.bukkit.craftbukkit.inventory.CraftItemStack.asCraftMirror(itemStack));
+ event.callEvent();
+ itemStack = org.bukkit.craftbukkit.inventory.CraftItemStack.unwrap(event.getCreatedMap());
+ // Paper end - PlayerMapFilledEvent
if (itemInHand.isEmpty()) {
return InteractionResult.SUCCESS.heldItemTransformedTo(itemStack);
} else {

View File

@@ -1,5 +1,13 @@
--- a/net/minecraft/world/item/ProjectileWeaponItem.java
+++ b/net/minecraft/world/item/ProjectileWeaponItem.java
@@ -50,6 +_,7 @@
float inaccuracy,
boolean isCrit,
@Nullable LivingEntity target
+ ,float drawStrength // Paper - Pass draw strength
) {
float f = EnchantmentHelper.processProjectileSpread(level, weapon, shooter, 0.0F);
float f1 = projectileItems.size() == 1 ? 0.0F : 2.0F * f / (projectileItems.size() - 1);
@@ -62,12 +_,29 @@
float f4 = f2 + f3 * ((i + 1) / 2) * f1;
f3 = -f3;
@@ -14,7 +22,7 @@
+ Projectile projectile = this.createProjectile(level, shooter, weapon, itemStack, isCrit);
+ this.shootProjectile(shooter, projectile, i1, velocity, inaccuracy, f4, target);
+
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(shooter, weapon, itemStack, projectile, hand, velocity, true);
+ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(shooter, weapon, itemStack, projectile, hand, drawStrength, true);
+ if (event.isCancelled()) {
+ event.getProjectile().remove();
+ return;

View File

@@ -6,7 +6,7 @@
Vec3 vec3 = entity.position();
- if (entity.randomTeleport(d, d1, d2, true)) {
+ // CraftBukkit start - handle canceled status of teleport event
+ java.util.Optional<Boolean> status = entity.randomTeleport(d, d1, d2, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.CHORUS_FRUIT);
+ java.util.Optional<Boolean> status = entity.randomTeleport(d, d1, d2, true, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.CONSUMABLE_EFFECT);
+
+ // teleport event was canceled, no more tries
+ if (status.isEmpty()) break;

View File

@@ -0,0 +1,18 @@
--- a/net/minecraft/world/item/enchantment/EnchantmentHelper.java
+++ b/net/minecraft/world/item/enchantment/EnchantmentHelper.java
@@ -52,8 +_,14 @@
}
public static ItemEnchantments updateEnchantments(ItemStack stack, Consumer<ItemEnchantments.Mutable> updater) {
+ // Paper start - allowing updating enchantments on items without component
+ return updateEnchantments(stack, updater, false);
+ }
+
+ public static ItemEnchantments updateEnchantments(ItemStack stack, Consumer<ItemEnchantments.Mutable> updater, final boolean createComponentIfMissing) {
+ // Paper end - allowing updating enchantments on items without component
DataComponentType<ItemEnchantments> componentType = getComponentType(stack);
- ItemEnchantments itemEnchantments = stack.get(componentType);
+ ItemEnchantments itemEnchantments = createComponentIfMissing ? stack.getOrDefault(componentType, ItemEnchantments.EMPTY) : stack.get(componentType); // Paper - allowing updating enchantments on items without component
if (itemEnchantments == null) {
return ItemEnchantments.EMPTY;
} else {

View File

@@ -24,7 +24,7 @@
+ // CraftBukkit start
+ private final CraftWorld world;
+ public boolean pvpMode;
+ public org.bukkit.generator.ChunkGenerator generator;
+ public @Nullable org.bukkit.generator.ChunkGenerator generator;
+
+ public boolean captureBlockStates = false;
+ public boolean captureTreeGeneration = false;
@@ -81,16 +81,16 @@
long biomeZoomSeed,
- int maxChainedNeighborUpdates
+ int maxChainedNeighborUpdates,
+ org.bukkit.generator.ChunkGenerator gen, // CraftBukkit
+ org.bukkit.generator.BiomeProvider biomeProvider, // CraftBukkit
+ org.bukkit.World.Environment env, // CraftBukkit
+ @Nullable org.bukkit.generator.ChunkGenerator generator, // Paper
+ @Nullable org.bukkit.generator.BiomeProvider biomeProvider, // Paper
+ org.bukkit.World.Environment environment, // Paper
+ java.util.function.Function<org.spigotmc.SpigotWorldConfig, // Spigot - create per world config
+ io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator // Paper - create paper world config
) {
+ this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot
+ this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
+ this.generator = gen;
+ this.world = new CraftWorld((ServerLevel) this, gen, biomeProvider, env);
+ this.generator = generator;
+ this.world = new CraftWorld((ServerLevel) this, generator, biomeProvider, environment);
+
+ for (SpawnCategory spawnCategory : SpawnCategory.values()) {
+ if (org.bukkit.craftbukkit.util.CraftSpawnCategory.isValidForLimits(spawnCategory)) {

View File

@@ -1,5 +1,67 @@
--- a/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
+++ b/net/minecraft/world/level/block/entity/BrushableBlockEntity.java
@@ -65,9 +_,26 @@
return false;
} else {
this.coolDownEndsAtTick = startTick + 10L;
+ // Paper start - EntityChangeBlockEvent
+ // The vanilla logic here is *so* backwards, we'd be moving basically *all* following calls down.
+ // Instead, compute vanilla ourselves up here and just replace the below usages with our computed values for a free diff-on-change.
+ final int currentCompletionStage = this.getCompletionState();
+ final boolean enoughBrushesToBreak = ++this.brushCount >= REQUIRED_BRUSHES_TO_BREAK;
+ final int nextCompletionStage = this.getCompletionState();
+ final boolean differentCompletionStages = currentCompletionStage != nextCompletionStage;
+ final BlockState nextBrokenBlockState = this.getBlockState().setValue(BlockStateProperties.DUSTED, nextCompletionStage);
+ if (enoughBrushesToBreak || differentCompletionStages) {
+ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(
+ brusher, this.worldPosition, enoughBrushesToBreak ? computeTurnsTo().defaultBlockState() : nextBrokenBlockState
+ )) {
+ brushCount--;
+ return false;
+ }
+ }
+ // Paper end - EntityChangeBlockEvent
this.unpackLootTable(level, brusher, stack);
- int completionState = this.getCompletionState();
- if (++this.brushCount >= 10) {
+ int completionState = currentCompletionStage; // Paper - EntityChangeBlockEvent - use precomputed - diff on change
+ if (enoughBrushesToBreak) { // Paper - EntityChangeBlockEvent - use precomputed - diff on change
this.brushingCompleted(level, brusher, stack);
return true;
} else {
@@ -75,7 +_,7 @@
int completionState1 = this.getCompletionState();
if (completionState != completionState1) {
BlockState blockState = this.getBlockState();
- BlockState blockState1 = blockState.setValue(BlockStateProperties.DUSTED, completionState1);
+ BlockState blockState1 = nextBrokenBlockState; // Paper - EntityChangeBlockEvent - use precomputed - diff on change
level.setBlock(this.getBlockPos(), blockState1, 3);
}
@@ -116,6 +_,11 @@
this.dropContent(level, brusher, stack);
BlockState blockState = this.getBlockState();
level.levelEvent(3008, this.getBlockPos(), Block.getId(blockState));
+ // Paper start - EntityChangeEvent - extract result block logic
+ this.brushingCompleteUpdateBlock(this.computeTurnsTo());
+ }
+ private Block computeTurnsTo() {
+ // Paper end - EntityChangeEvent - extract result block logic
Block turnsInto;
if (this.getBlockState().getBlock() instanceof BrushableBlock brushableBlock) {
turnsInto = brushableBlock.getTurnsInto();
@@ -123,6 +_,11 @@
turnsInto = Blocks.AIR;
}
+ // Paper start - EntityChangeEvent - extract result block logic
+ return turnsInto;
+ }
+ public void brushingCompleteUpdateBlock(final Block turnsInto) {
+ // Paper end - EntityChangeEvent - extract result block logic
level.setBlock(this.worldPosition, turnsInto.defaultBlockState(), 3);
}
@@ -139,7 +_,12 @@
double d5 = blockPos.getZ() + 0.5 * d1 + d2;
ItemEntity itemEntity = new ItemEntity(level, d3, d4, d5, this.item.split(level.random.nextInt(21) + 10));

View File

@@ -96,6 +96,20 @@
}
public static void addTargetDecoration(ItemStack stack, BlockPos pos, String type, Holder<MapDecorationType> mapDecorationType) {
@@ -354,7 +_,12 @@
}
public void setColorsDirty(int x, int z) {
- this.setDirty();
+ // Paper start - Fix unnecessary map data saves
+ this.setColorsDirty(x, z, true);
+ }
+ public void setColorsDirty(int x, int z, boolean markFileDirty) {
+ if (markFileDirty) this.setDirty();
+ // Paper end - Fix unnecessary map data saves
for (MapItemSavedData.HoldingPlayer holdingPlayer : this.carriedBy) {
holdingPlayer.markColorsDirty(x, z);
@@ -395,7 +_,7 @@
return true;
}