Files
Purpur/patches/server/0158-Add-unsafe-Entity-serialization-API.patch
William Blake Galbreath 17368d1aa9 Updated Upstream (Paper & Tuinity)
Upstream has released updates that appear to apply and compile correctly

Paper Changes:
12dec20 Bump paerweight to 1.1.7
e33ed89 Get short commit ref using a more proper method
7d6147d Remove now unneeded patch due to paperweight 1.1.7
e72fa41 Update task dependency for includeMappings so the new task isn't skipped
0ad5526 Trim whitspace off of git hash (oops)

Tuinity Changes:
e878ba9 Update paper
2bd2849 Bring back fix codec spam patch
2021-06-27 00:42:39 -05:00

112 lines
6.3 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Mariell Hoversholm <proximyst@proximyst.com>
Date: Sat, 9 Jan 2021 21:22:58 +0100
Subject: [PATCH] Add unsafe Entity serialization API
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 3a92c0112befe51e795f81b1fce52e1f083f6373..1035e023003521574a09fdea3fd08e5fca66d8fc 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1242,5 +1242,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean isRidableInWater() {
return getHandle().rideableUnderWater();
}
+
+ @Override
+ public boolean spawnAt(Location location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
+ entity.level = ((CraftWorld) location.getWorld()).getHandle();
+ entity.absMoveTo(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
+ return !entity.valid && entity.level.addEntity(entity, spawnReason);
+ }
// Purpur end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
index 9239c4c948ddfc6f7ad8c5f277e355581f8f37ec..75c5cb1a0b95f319eb32da618df7fa75ccefccbd 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -408,9 +408,14 @@ public final class CraftMagicNumbers implements UnsafeValues {
Preconditions.checkNotNull(item, "null cannot be serialized");
Preconditions.checkArgument(item.getType() != Material.AIR, "air cannot be serialized");
+ // Purpur start - rework NBT <-> bytes
+ return serializeNbtToBytes(CraftItemStack.asNMSCopy(item).save(new CompoundTag()), true);
+ }
+
+ public byte[] serializeNbtToBytes(CompoundTag compound, boolean addDataVersion) {
+ if (addDataVersion) compound.putInt("DataVersion", getDataVersion());
java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
- CompoundTag compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).handle : CraftItemStack.asNMSCopy(item)).save(new CompoundTag());
- compound.putInt("DataVersion", getDataVersion());
+ // Purpur end
try {
net.minecraft.nbt.NbtIo.writeCompressed(
compound,
@@ -428,21 +433,52 @@ public final class CraftMagicNumbers implements UnsafeValues {
Preconditions.checkNotNull(data, "null cannot be deserialized");
Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing");
+ // Purpur start - rework NBT <-> bytes
+ CompoundTag compound = deserializeNbtFromBytes(data, true);
+ Dynamic<Tag> converted = DataFixers.getDataFixer().update(References.ITEM_STACK, new Dynamic<>(NbtOps.INSTANCE, compound), compound.getInt("DataVersion"), getDataVersion());
+ return net.minecraft.world.item.ItemStack.of((CompoundTag) converted.getValue()).asBukkitMirror();
+ }
+
+ public CompoundTag deserializeNbtFromBytes(byte[] data, boolean verifyDataVersion) {
+ // Purpur end
try {
CompoundTag compound = net.minecraft.nbt.NbtIo.readCompressed(
new java.io.ByteArrayInputStream(data)
);
+ if (verifyDataVersion) { // Purpur
int dataVersion = compound.getInt("DataVersion");
Preconditions.checkArgument(dataVersion <= getDataVersion(), "Newer version! Server downgrades are not supported!");
- Dynamic<Tag> converted = DataFixers.getDataFixer().update(References.ITEM_STACK, new Dynamic<Tag>(NbtOps.INSTANCE, compound), dataVersion, getDataVersion());
- return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of((CompoundTag) converted.getValue()));
+ } // Purpur
+ return compound; // Purpur
} catch (IOException ex) {
com.destroystokyo.paper.util.SneakyThrow.sneaky(ex);
throw new RuntimeException();
}
}
+ // Purpur start
+ @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, "non-CraftEntity cannot be serialized");
+ CompoundTag compound = new CompoundTag();
+ compound.putString("id", ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getMinecraftKeyString());
+ return serializeNbtToBytes(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().saveWithoutId(compound), true);
+ }
+
+ @Override
+ public org.bukkit.entity.Entity deserializeEntity(byte[] data, org.bukkit.World world) {
+ CompoundTag compound = deserializeNbtFromBytes(data, true);
+ Dynamic<Tag> converted = DataFixers.getDataFixer().update(References.ENTITY, new Dynamic<>(NbtOps.INSTANCE, compound), compound.getInt("DataVersion"), getDataVersion());
+ compound = (CompoundTag) converted.getValue();
+ compound.remove("UUID"); // Make the server make a new UUID for this entity; makes entities always spawnable.
+ return net.minecraft.world.entity.EntityType.create(compound, ((org.bukkit.craftbukkit.CraftWorld) world).getHandle())
+ .orElseThrow(() -> new IllegalArgumentException("unknown ID was found for the data; did you downgrade?"))
+ .getBukkitEntity();
+ }
+ // Purpur end
+
@Override
public String getTranslationKey(Material mat) {
if (mat.isBlock()) {