From 42eb17973b634127c0b3d00bde72c60ff0f3ff7b Mon Sep 17 00:00:00 2001 From: Cryptite Date: Tue, 25 Apr 2023 08:00:36 -0500 Subject: [PATCH] Maybe fix patch here? --- .../api/0013-Equipment-Packet-Caching.patch | 149 ++++++++ .../0021-Equipment-Packet-Caching.patch | 320 ++++++++++++++++++ ... => 0022-Shared-DataFolder-for-maps.patch} | 0 3 files changed, 469 insertions(+) create mode 100644 patches/api/0013-Equipment-Packet-Caching.patch create mode 100644 patches/server/0021-Equipment-Packet-Caching.patch rename patches/server/{0021-Shared-DataFolder-for-maps.patch => 0022-Shared-DataFolder-for-maps.patch} (100%) diff --git a/patches/api/0013-Equipment-Packet-Caching.patch b/patches/api/0013-Equipment-Packet-Caching.patch new file mode 100644 index 000000000..12f2331a8 --- /dev/null +++ b/patches/api/0013-Equipment-Packet-Caching.patch @@ -0,0 +1,149 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Tue, 25 Apr 2023 07:36:40 -0500 +Subject: [PATCH] Equipment Packet Caching + + +diff --git a/src/main/java/org/bukkit/entity/LivingEntity.java b/src/main/java/org/bukkit/entity/LivingEntity.java +index ffca32ae2464ea5a669029079a50585ca259a4f8..283b71fc6f74790827d1af9d5ad05eea66df8e4c 100644 +--- a/src/main/java/org/bukkit/entity/LivingEntity.java ++++ b/src/main/java/org/bukkit/entity/LivingEntity.java +@@ -1150,4 +1150,11 @@ public interface LivingEntity extends Attributable, Damageable, ProjectileSource + */ + void setBodyYaw(float bodyYaw); + // Paper end ++ ++ // Slice start ++ /** ++ * @param p The player to send this entity's equipment packet to ++ */ ++ void sendEquipment(Player p); ++ // Slice end + } +diff --git a/src/main/java/org/bukkit/event/entity/EntityEquipmentItemLookup.java b/src/main/java/org/bukkit/event/entity/EntityEquipmentItemLookup.java +new file mode 100644 +index 0000000000000000000000000000000000000000..6c329ca3c22d1fd712041334c5c1e7bd7e7201ac +--- /dev/null ++++ b/src/main/java/org/bukkit/event/entity/EntityEquipmentItemLookup.java +@@ -0,0 +1,54 @@ ++package org.bukkit.event.entity; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.event.HandlerList; ++import org.bukkit.inventory.EquipmentSlot; ++import org.bukkit.inventory.ItemStack; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when requesting a cached equipment item lookup ++ */ ++public class EntityEquipmentItemLookup extends EntityEvent { ++ private static final HandlerList handlers = new HandlerList(); ++ private final String tag; ++ private final EquipmentSlot equipmentSlot; ++ private ItemStack itemStack; ++ ++ public EntityEquipmentItemLookup(@NotNull final Entity entity, @NotNull String tag, @NotNull EquipmentSlot slot, @NotNull final ItemStack itemStack) { ++ super(entity); ++ this.tag = tag; ++ this.equipmentSlot = slot; ++ this.itemStack = itemStack; ++ } ++ ++ @NotNull ++ public ItemStack getItemStack() { ++ return itemStack; ++ } ++ ++ public void setItemStack(ItemStack itemStack) { ++ this.itemStack = itemStack; ++ } ++ ++ @NotNull ++ public EquipmentSlot getEquipmentSlot() { ++ return equipmentSlot; ++ } ++ ++ @NotNull ++ public String getTag() { ++ return tag; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} +diff --git a/src/main/java/org/bukkit/event/player/PlayerReceiveEquipmentEvent.java b/src/main/java/org/bukkit/event/player/PlayerReceiveEquipmentEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..513d62342d8e29e8d3c92fe932d0d77f659cf2f1 +--- /dev/null ++++ b/src/main/java/org/bukkit/event/player/PlayerReceiveEquipmentEvent.java +@@ -0,0 +1,61 @@ ++package org.bukkit.event.player; ++ ++import org.bukkit.entity.Entity; ++import org.bukkit.entity.Player; ++import org.bukkit.event.Cancellable; ++import org.bukkit.event.HandlerList; ++import org.jetbrains.annotations.NotNull; ++ ++/** ++ * Called when a player is about to receive an equipment packet about another player ++ */ ++public class PlayerReceiveEquipmentEvent extends PlayerEvent implements Cancellable { ++ private static final HandlerList handlers = new HandlerList(); ++ private final Entity tracked; ++ private boolean cancel; ++ private String tag; ++ ++ public PlayerReceiveEquipmentEvent(@NotNull final Player player, @NotNull final Entity tracked) { ++ super(player); ++ this.tracked = tracked; ++ } ++ ++ /** ++ * Gets the tracked entity ++ * ++ * @return Entity the player is now tracking ++ */ ++ @NotNull ++ public Entity getTracked() { ++ return tracked; ++ } ++ ++ public String getTag() { ++ return tag; ++ } ++ ++ public void setTag(String tag) { ++ this.tag = tag; ++ } ++ ++ @Override ++ public boolean isCancelled() { ++ return cancel; ++ } ++ ++ @Override ++ public void setCancelled(boolean cancel) { ++ this.cancel = cancel; ++ } ++ ++ @NotNull ++ @Override ++ public HandlerList getHandlers() { ++ return handlers; ++ } ++ ++ @NotNull ++ public static HandlerList getHandlerList() { ++ return handlers; ++ } ++} diff --git a/patches/server/0021-Equipment-Packet-Caching.patch b/patches/server/0021-Equipment-Packet-Caching.patch new file mode 100644 index 000000000..2eee099cc --- /dev/null +++ b/patches/server/0021-Equipment-Packet-Caching.patch @@ -0,0 +1,320 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Cryptite +Date: Tue, 18 Apr 2023 08:16:32 -0500 +Subject: [PATCH] Equipment Packet Caching + + +diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +index 8d442c5a498ecf288a0cc0c54889c6e2fda849ce..8fc13d7b004da228fc58554ea5058ef8e58833a4 100644 +--- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java ++++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +@@ -286,5 +286,6 @@ public class GlobalConfiguration extends ConfigurationPart { + public boolean lagCompensateBlockBreaking = true; + public boolean useDimensionTypeForCustomSpawners = false; + public boolean strictAdvancementDimensionCheck = false; ++ public String sharedDataFolder; // Slice + } + } +diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java +index 5a8f850b447fc3a4bd0eb0c505bbdfc8be7115e8..34d74735b7a7d258c6bd14bb7e5406934a208a31 100644 +--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java ++++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEquipmentPacket.java +@@ -18,6 +18,15 @@ public class ClientboundSetEquipmentPacket implements Packet> equipmentList, net.minecraft.world.entity.LivingEntity entity, String tag) { ++ this.entity = id; ++ slots = new java.util.ArrayList<>(equipmentList.size()); ++ for (Pair pair : equipmentList) { ++ EquipmentSlot slot = pair.getFirst(); ++ slots.add(Pair.of(slot, entity.getOrCreateCachedEquipmentItem(tag, slot, pair.getSecond()))); ++ } ++ } ++ + public ClientboundSetEquipmentPacket(FriendlyByteBuf buf) { + this.entity = buf.readVarInt(); + EquipmentSlot[] equipmentSlots = EquipmentSlot.values(); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index fa14ab3d8117e9d357380d21d3c6a2cd1df7c04c..bf79373dd6a0cf1e8252555d43012371390a51c7 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -313,6 +313,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { + AtomicReference atomicreference = new AtomicReference(); +@@ -413,6 +414,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> list = Lists.newArrayList(); +- EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); +- int i = aenumitemslot.length; +- +- for (int j = 0; j < i; ++j) { +- EquipmentSlot enumitemslot = aenumitemslot[j]; +- ItemStack itemstack = ((LivingEntity) this.entity).getItemBySlot(enumitemslot); +- +- if (!itemstack.isEmpty()) { +- // Paper start - prevent oversized data +- final ItemStack sanitized = LivingEntity.sanitizeItemStack(itemstack.copy(), false); +- list.add(Pair.of(enumitemslot, ((LivingEntity) this.entity).stripMeta(sanitized, false))); // Paper - remove unnecessary item meta +- // Paper end +- } +- } +- +- if (!list.isEmpty()) { +- consumer.accept(new ClientboundSetEquipmentPacket(this.entity.getId(), list)); +- } +- ((LivingEntity) this.entity).detectEquipmentUpdates(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending ++ if (this.entity instanceof LivingEntity livingEntity) { ++ livingEntity.sendEquipment(entityplayer); // Slice + } + + // CraftBukkit start - Fix for nonsensical head yaw +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 5813349d484cf40c5b75de6e55dff95286285934..e24b0871819add31e00e1e3d782fda31a2ad312f 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -1926,7 +1926,7 @@ public class ServerLevel extends Level implements WorldGenLevel { + @Override + public MapItemSavedData getMapData(String id) { + // CraftBukkit start +- return (MapItemSavedData) this.getServer().overworld().getDataStorage().get((nbttagcompound) -> { ++ return (MapItemSavedData) this.getServer().getMapDataStorage().get((nbttagcompound) -> { // Slice + // We only get here when the data file exists, but is not a valid map + MapItemSavedData newMap = MapItemSavedData.load(nbttagcompound); + newMap.id = id; +@@ -1940,12 +1940,22 @@ public class ServerLevel extends Level implements WorldGenLevel { + @Override + public void setMapData(String id, MapItemSavedData state) { + state.id = id; // CraftBukkit +- this.getServer().overworld().getDataStorage().set(id, state); ++ this.getServer().getMapDataStorage().set(id, state); // Slice + } + + @Override + public int getFreeMapId() { +- return ((MapIndex) this.getServer().overworld().getDataStorage().computeIfAbsent(MapIndex::load, MapIndex::new, "idcounts")).getFreeAuxValueForMap(); ++ // Slice start ++ DimensionDataStorage storage = this.getServer().getMapDataStorage(); ++ MapIndex mapIndex = storage.readSavedData(MapIndex::load, "idcounts"); ++ if (mapIndex == null) { ++ mapIndex = new MapIndex(); ++ } ++ int newId = mapIndex.getFreeAuxValueForMap(); ++ storage.set("idcounts", mapIndex); ++ storage.save(); ++ return newId; ++ // Slice end + } + + // Paper start - helper function for configurable spawn radius +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 72739d5949314b242869fd5fef3b5f0c076434d0..5879e1cc44bee6fd4b3fef2577ed516ce8e3c917 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -261,6 +261,8 @@ public abstract class LivingEntity extends Entity implements Attackable { + public org.bukkit.craftbukkit.entity.CraftLivingEntity getBukkitLivingEntity() { return (org.bukkit.craftbukkit.entity.CraftLivingEntity) super.getBukkitEntity(); } // Paper + public boolean silentDeath = false; // Paper - mark entity as dying silently for cancellable death event + public net.kyori.adventure.util.TriState frictionState = net.kyori.adventure.util.TriState.NOT_SET; // Paper ++ private final com.google.common.collect.Table equipmentPacketCache = com.google.common.collect.HashBasedTable.create(); // Slice ++ public java.util.Map cachedEquipmentMap = new java.util.HashMap<>(); // Slice + + @Override + public float getBukkitYaw() { +@@ -3040,6 +3042,7 @@ public abstract class LivingEntity extends Entity implements Attackable { + if (map != null) { + this.handleHandSwap(map); + if (!map.isEmpty()) { ++ cachedEquipmentMap.clear(); // Slice - Must invalidate cached equipment map if we have changes + this.handleEquipmentChanges(map); + } + } +@@ -3132,7 +3135,25 @@ public abstract class LivingEntity extends Entity implements Attackable { + } + + }); +- ((ServerLevel) this.level).getChunkSource().broadcast(this, new ClientboundSetEquipmentPacket(this.getId(), list)); ++ ++ // Slice start ++ net.minecraft.server.level.ChunkMap.TrackedEntity entityTracker = ((ServerLevel) this.level).getChunkSource().chunkMap.entityMap.get(getId()); ++ if (entityTracker != null) { ++ ClientboundSetEquipmentPacket packet = new ClientboundSetEquipmentPacket(this.getId(), list); ++ for (net.minecraft.server.network.ServerPlayerConnection playerConnection : entityTracker.seenBy) { ++ ServerPlayer player = playerConnection.getPlayer(); ++ org.bukkit.event.player.PlayerReceiveEquipmentEvent event = new org.bukkit.event.player.PlayerReceiveEquipmentEvent(player.getBukkitEntity(), getBukkitEntity()); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ String tag = event.getTag(); ++ if (tag != null) { ++ playerConnection.send(new ClientboundSetEquipmentPacket(this.getId(), list, this, tag)); ++ } else { ++ playerConnection.send(packet); ++ } ++ } ++ } ++ // Slice end + } + + // Paper start - hide unnecessary item meta +@@ -4402,4 +4423,74 @@ public abstract class LivingEntity extends Entity implements Attackable { + public static record Fallsounds(SoundEvent small, SoundEvent big) { + + } ++ ++ // Slice start ++ public ItemStack getOrCreateCachedEquipmentItem(String tag, EquipmentSlot slot, ItemStack itemStack) { ++ return equipmentPacketCache.row(tag).computeIfAbsent(itemStack, i -> { ++ String name = slot.name(); ++ ++ //How neat is this. ++ if (name.equals("MAINHAND")) { ++ name = "HAND"; ++ } else if (name.equals("OFFHAND")) { ++ name = "OFF_HAND"; ++ } ++ ++ org.bukkit.event.entity.EntityEquipmentItemLookup event = new org.bukkit.event.entity.EntityEquipmentItemLookup(getBukkitEntity(), tag, org.bukkit.inventory.EquipmentSlot.valueOf(name), CraftItemStack.asBukkitCopy(i)); ++ this.level.getCraftServer().getPluginManager().callEvent(event); ++ org.bukkit.inventory.ItemStack eventItem = event.getItemStack(); ++ return CraftItemStack.asNMSCopy(eventItem); ++ }); ++ } ++ // Slice end ++ ++ // Slice start ++ public void sendEquipment(ServerPlayer p) { ++ org.bukkit.event.player.PlayerReceiveEquipmentEvent event = new org.bukkit.event.player.PlayerReceiveEquipmentEvent(p.getBukkitEntity(), getBukkitEntity()); ++ level.getCraftServer().getPluginManager().callEvent(event); ++ ++ boolean sendEquipment = !event.isCancelled(); ++ String tag = event.getTag(); ++ if (sendEquipment && this instanceof ServerPlayer player && tag != null) { ++ ClientboundSetEquipmentPacket equipmentPacket = player.cachedEquipmentMap.get(tag); ++ if (equipmentPacket != null) { ++ //Event says use a tag, and our tag exists; so we simply used our entire cached packet ++ p.connection.send(equipmentPacket); ++ sendEquipment = false; ++ } ++ } ++ ++ if (sendEquipment) { ++ EquipmentSlot[] equipmentSlots = EquipmentSlot.values(); ++ List> list = new ArrayList<>(equipmentSlots.length); ++ ++ for (EquipmentSlot enumitemslot : equipmentSlots) { ++ ItemStack itemstack = getItemBySlot(enumitemslot); ++ ++ if (!itemstack.isEmpty()) { ++ // Paper start - prevent oversized data ++ final ItemStack sanitized = LivingEntity.sanitizeItemStack(itemstack.copy(), false); ++ ItemStack strippedItem = stripMeta(sanitized, false); ++ ++ if (tag != null) { ++ strippedItem = getOrCreateCachedEquipmentItem(tag, enumitemslot, strippedItem); ++ } ++ ++ list.add(Pair.of(enumitemslot, strippedItem)); // Paper - remove unnecessary item meta ++ // Paper end ++ } ++ } ++ ++ if (!list.isEmpty()) { ++ ClientboundSetEquipmentPacket equipmentPacket = new ClientboundSetEquipmentPacket(getId(), list); ++ if (tag != null) { ++ cachedEquipmentMap.put(tag, equipmentPacket); ++ } ++ p.connection.send(equipmentPacket); ++ } ++ ++ detectEquipmentUpdates(); // CraftBukkit - SPIGOT-3789: sync again immediately after sending ++ } ++ } ++ // Slice end + } +diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +index defe31a5d3aa89a3d18b94f2ff005594e38754b3..637a86e74d633901fdd2f2f1ba6aa4ed49780ead 100644 +--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java ++++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java +@@ -58,7 +58,7 @@ public class DimensionDataStorage { + } + + @Nullable +- private T readSavedData(Function readFunction, String id) { ++ public T readSavedData(Function readFunction, String id) { // Slice private -> public + try { + File file = this.getDataFile(id); + if (file.exists()) { +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +index d43859f8aa7beed82dd3a146bb1086982cd0cda7..502aec23d70f7b995eaf9df61dc50896cf8e43c2 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +@@ -1071,4 +1071,13 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { + getHandle().knockback(strength, directionX, directionZ); + }; + // Paper end ++ ++ // Slice start ++ @Override ++ public void sendEquipment(Player p) { ++ if (entity instanceof net.minecraft.world.entity.LivingEntity livingEntity) { ++ livingEntity.sendEquipment(((CraftPlayer) p).getHandle()); ++ } ++ } ++ // Slice end + } diff --git a/patches/server/0021-Shared-DataFolder-for-maps.patch b/patches/server/0022-Shared-DataFolder-for-maps.patch similarity index 100% rename from patches/server/0021-Shared-DataFolder-for-maps.patch rename to patches/server/0022-Shared-DataFolder-for-maps.patch