Files
Purpur/patches/server/0170-Add-unsafe-Entity-serialization-API.patch
BillyGalbreath d93887a156 Updated Upstream (Paper)
Upstream has released updates that appear to apply and compile correctly

Paper Changes:
5b20df6bf added PlayerNameEntityEvent
ff9c82444 Add worldborder events
616b1f3cd consider enchants for destroy speed
aaef1d5cc fix file conversion
674d8f7f7 Make discovered maps config work in treasure maps from loot tables too
be1687914 stop firing pressure plate EntityInteractEvent for ignored entities (fixes #4962)
7d56f38ed Do not use the bukkit singleton for the GUI (Fixes #5301)
4c9bdf53a Updated Upstream (Bukkit/CraftBukkit/Spigot) (#5299)
8647bd130 Improve ServerGUI
fcc6d3359 Throw proper exception on empty JsonList file
17d2e1291 Fix interact event in adventure mode
964e0bf42 MC-29274: Fix Wither hostility towards players
9e24a5213 Fixed furnace cook-speed multiplier losing precision when calculating cook time
c7e42faa3 Do not create unnecessary copies of the passenger list
40881ad67 added tnt minecarts to the tnt height nerf
26be708f4 Remove streams from SensorNearest
5b5989b21 fix nullability of playerlist header/footer, closes #5290
45bc531dd Fix Material#getTranslationKey for Block Materials (#5294)
2021-03-04 21:45:44 -06:00

130 lines
7.6 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/net/minecraft/server/EntityTypes.java b/src/main/java/net/minecraft/server/EntityTypes.java
index 73cf30786d2b4d6f87be5f9aad87c3edb594d18e..f5fb3b3c08a05bede7ed1141c018bd0d16a19244 100644
--- a/src/main/java/net/minecraft/server/EntityTypes.java
+++ b/src/main/java/net/minecraft/server/EntityTypes.java
@@ -394,6 +394,7 @@ public class EntityTypes<T extends Entity> {
return this.bf.create(this, world);
}
+ public static Optional<Entity> loadEntityFixedData(NBTTagCompound nbtTagCompound, World world) { return a(nbtTagCompound, world); } // Purpur - OBFHELPER
public static Optional<Entity> a(NBTTagCompound nbttagcompound, World world) {
return SystemUtils.a(a(nbttagcompound).map((entitytypes) -> {
return entitytypes.a(world);
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index f96c41fc8788ee7b674c18cc0fa692df9cee1939..63a419b4eed399a50ba9dde515c1c13da4e720c8 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -1199,5 +1199,12 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
public boolean isRidableInWater() {
return getHandle().isRidableInWater();
}
+
+ @Override
+ public boolean spawnAt(Location location, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
+ entity.world = ((CraftWorld) location.getWorld()).getHandle();
+ entity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
+ return !entity.valid && entity.world.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 a9c188c42c63d6e073bae3c77f1dacd2c3fc4602..a73ed438df34d494242f680e08110f4b9eba01c6 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
@@ -383,9 +383,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 NBTTagCompound()), true);
+ }
+
+ public byte[] serializeNbtToBytes(NBTTagCompound compound, boolean addDataVersion) {
+ if (addDataVersion) compound.setInt("DataVersion", getDataVersion());
java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
- NBTTagCompound compound = (item instanceof CraftItemStack ? ((CraftItemStack) item).getHandle() : CraftItemStack.asNMSCopy(item)).save(new NBTTagCompound());
- compound.setInt("DataVersion", getDataVersion());
+ // Purpur end
try {
net.minecraft.server.NBTCompressedStreamTools.writeNBT(
compound,
@@ -398,26 +403,58 @@ public final class CraftMagicNumbers implements UnsafeValues {
return outputStream.toByteArray();
}
+ public static DynamicOpsNBT getDynamicOpsNbtInstance() { return DynamicOpsNBT.a; } // Purpur - OBFHELPER - keeping out of the class because it's FULL of decompile errors
@Override
public ItemStack deserializeItem(byte[] data) {
Preconditions.checkNotNull(data, "null cannot be deserialized");
Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing");
+ // Purpur start - rework NBT <-> bytes
+ NBTTagCompound compound = deserializeNbtFromBytes(data, true);
+ Dynamic<NBTBase> converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ITEM_STACK, new Dynamic<>(getDynamicOpsNbtInstance(), compound), compound.getInt("DataVersion"), getDataVersion()); // TODO: obfhelper
+ return net.minecraft.server.ItemStack.fromCompound((NBTTagCompound) converted.getValue()).asBukkitMirror();
+ }
+
+ public NBTTagCompound deserializeNbtFromBytes(byte[] data, boolean verifyDataVersion) {
+ // Purpur end
try {
NBTTagCompound compound = net.minecraft.server.NBTCompressedStreamTools.readNBT(
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<NBTBase> converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ITEM_STACK, new Dynamic<NBTBase>(DynamicOpsNBT.a, compound), dataVersion, getDataVersion());
- return CraftItemStack.asCraftMirror(net.minecraft.server.ItemStack.fromCompound((NBTTagCompound) 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");
+ NBTTagCompound compound = new NBTTagCompound();
+ compound.setString("id", ((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().getMinecraftKeyString());
+ return serializeNbtToBytes(((org.bukkit.craftbukkit.entity.CraftEntity) entity).getHandle().save(compound), true);
+ }
+
+ @Override
+ public org.bukkit.entity.Entity deserializeEntity(byte[] data, org.bukkit.World world) {
+ NBTTagCompound compound = deserializeNbtFromBytes(data, true);
+ Dynamic<NBTBase> converted = DataConverterRegistry.getDataFixer().update(DataConverterTypes.ENTITY, new Dynamic<>(getDynamicOpsNbtInstance(), compound), compound.getInt("DataVersion"), getDataVersion());
+ compound = (NBTTagCompound) converted.getValue();
+ compound.remove("UUID"); // Make the server make a new UUID for this entity; makes entities always spawnable.
+ return net.minecraft.server.EntityTypes.loadEntityFixedData(compound, ((org.bukkit.craftbukkit.CraftWorld) world).getHandle())
+ .orElseThrow(() -> new IllegalArgumentException("unknown ID was found for the data; did you downgrade?"))
+ .getBukkitEntity();
+ }
+ // Pupur end
+
@Override
public String getTranslationKey(Material mat) {
if (mat.isBlock()) {