PaperMC/patches/server/0587-Add-Raw-Byte-Entity-Serialization.patch
Spottedleaf da9d110d5b Remove chunk save reattempt patch
This patch does not appear to be doing anything useful, and may
hide errors.

Currently, the save logic does not run through this path either
so it did not do anything.

Additionally, properly implement support for handling
RegionFileSizeException in Moonrise.
2024-11-28 18:27:59 -08:00

90 lines
5.2 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sun, 24 Oct 2021 16:20:31 -0400
Subject: [PATCH] Add Raw Byte Entity Serialization
== AT ==
public net.minecraft.world.entity.Entity setLevel(Lnet/minecraft/world/level/Level;)V
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 736569ea22a8b257fca6e4b9326f73ca8fbc803e..38147960aed55bb60b427d73739d8ec0b5b8b863 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2261,6 +2261,15 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
}
+ // Paper start - Entity serialization api
+ public boolean serializeEntity(CompoundTag compound) {
+ List<Entity> pass = new java.util.ArrayList<>(this.getPassengers());
+ this.passengers = ImmutableList.of();
+ boolean result = save(compound);
+ this.passengers = ImmutableList.copyOf(pass);
+ return result;
+ }
+ // Paper end - Entity serialization api
public boolean save(CompoundTag nbt) {
return this.isPassenger() ? false : this.saveAsPassenger(nbt);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 888a75423ac90ca85308eeb6d67bac5348bf31e0..b13c947d2cfe085017b30cb0f8340dd64f338914 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1083,6 +1083,18 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
}
// Paper end - tracked players API
+ // Paper start - raw entity serialization API
+ @Override
+ public boolean spawnAt(Location location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
+ Preconditions.checkNotNull(location, "location cannot be null");
+ Preconditions.checkNotNull(reason, "reason cannot be null");
+ this.entity.setLevel(((CraftWorld) location.getWorld()).getHandle());
+ this.entity.setPos(location.getX(), location.getY(), location.getZ());
+ this.entity.setRot(location.getYaw(), location.getPitch());
+ return !this.entity.valid && this.entity.level().addFreshEntity(this.entity, reason);
+ }
+ // Paper end - raw entity serialization API
+
// Paper start - missing entity api
@Override
public boolean isInvisible() { // Paper - moved up from LivingEntity
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 1dd9a5cc45d5073adb150abdcbe2025e6ed2c315..2a3dc48aa50b41ede0e1a0e280314624961967f2 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -510,7 +510,33 @@ public final class CraftMagicNumbers implements UnsafeValues {
return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.parse(MinecraftServer.getServer().registryAccess(), compound).orElseThrow());
}
- private byte[] serializeNbtToBytes(CompoundTag compound) {
+ @Override
+ public byte[] serializeEntity(org.bukkit.entity.Entity entity) {
+ Preconditions.checkNotNull(entity, "null cannot be serialized");
+ Preconditions.checkArgument(entity instanceof org.bukkit.craftbukkit.entity.CraftEntity, "only CraftEntities can be serialized");
+
+ net.minecraft.nbt.CompoundTag compound = new net.minecraft.nbt.CompoundTag();
+ ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().serializeEntity(compound);
+ return serializeNbtToBytes(compound);
+ }
+
+ @Override
+ public org.bukkit.entity.Entity deserializeEntity(byte[] data, org.bukkit.World world, boolean preserveUUID) {
+ Preconditions.checkNotNull(data, "null cannot be deserialized");
+ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing");
+
+ net.minecraft.nbt.CompoundTag compound = deserializeNbtFromBytes(data);
+ int dataVersion = compound.getInt("DataVersion");
+ compound = (net.minecraft.nbt.CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ENTITY, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue();
+ if (!preserveUUID) {
+ // Generate a new UUID so we don't have to worry about deserializing the same entity twice
+ compound.remove("UUID");
+ }
+ return net.minecraft.world.entity.EntityType.create(compound, ((org.bukkit.craftbukkit.CraftWorld) world).getHandle(), net.minecraft.world.entity.EntitySpawnReason.LOAD)
+ .orElseThrow(() -> new IllegalArgumentException("An ID was not found for the data. Did you downgrade?")).getBukkitEntity();
+ }
+
+ private byte[] serializeNbtToBytes(net.minecraft.nbt.CompoundTag compound) {
compound.putInt("DataVersion", getDataVersion());
java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
try {