Paper/patches/server/1052-Add-raw-byte-block-state-serialization.patch

79 lines
5.7 KiB
Diff
Raw Normal View History

2023-10-12 17:10:02 +02:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: TrollyLoki <trollyloki@gmail.com>
Date: Thu, 12 Oct 2023 11:05:19 -0400
Subject: [PATCH] Add raw byte block state serialization
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
2023-10-29 16:10:00 +01:00
index 9271ff2a9ea05569e3c81886399aa7ab47efb05d..78234964c1e2107ff73d4f31b060ca6a5c38ea27 100644
2023-10-12 17:10:02 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftBlockStates.java
2023-10-29 16:10:00 +01:00
@@ -235,13 +235,18 @@ public final class CraftBlockStates {
2023-10-12 17:10:02 +02:00
return CraftBlockStates.getBlockState(block, true);
}
public static BlockState getBlockState(Block block, boolean useSnapshot) {
+ return CraftBlockStates.getBlockState(block, useSnapshot, null, null);
+ }
+ // if customBlockData is null, customTileEntity is ignored and the state is populated from the world
+ // otherwise, the state is populated using the values of customBlockData and customTileEntity, ignoring the current state of the world
2023-10-12 17:10:02 +02:00
+ public static BlockState getBlockState(Block block, boolean useSnapshot, net.minecraft.world.level.block.state.BlockState customBlockData, BlockEntity customTileEntity) {
// Paper end
Preconditions.checkNotNull(block, "block is null");
CraftBlock craftBlock = (CraftBlock) block;
CraftWorld world = (CraftWorld) block.getWorld();
BlockPos blockPosition = craftBlock.getPosition();
- net.minecraft.world.level.block.state.BlockState blockData = craftBlock.getNMS();
- BlockEntity tileEntity = craftBlock.getHandle().getBlockEntity(blockPosition);
+ net.minecraft.world.level.block.state.BlockState blockData = customBlockData != null ? customBlockData : craftBlock.getNMS(); // Paper - use customBlockData if provided
+ BlockEntity tileEntity = customBlockData != null ? customTileEntity : craftBlock.getHandle().getBlockEntity(blockPosition); // Paper - use customTileEntity if customBlockData provided
// Paper start - block state snapshots
boolean prev = CraftBlockEntityState.DISABLE_SNAPSHOT;
CraftBlockEntityState.DISABLE_SNAPSHOT = !useSnapshot;
diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
2023-10-29 16:10:00 +01:00
index ec2396f0e5d62b10450eaa7239a8c5479638b3c3..866d1f5cee46594475717b247902b8832bcb315b 100644
2023-10-12 17:10:02 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java
2023-10-29 16:10:00 +01:00
@@ -526,6 +526,42 @@ public final class CraftMagicNumbers implements UnsafeValues {
2023-10-12 17:10:02 +02:00
.orElseThrow(() -> new IllegalArgumentException("An ID was not found for the data. Did you downgrade?")).getBukkitEntity();
}
+ @Override
+ public byte[] serializeBlock(org.bukkit.block.BlockState blockState) {
+ Preconditions.checkNotNull(blockState, "null cannot be serialized");
+ Preconditions.checkArgument(blockState instanceof org.bukkit.craftbukkit.block.CraftBlockState, "only CraftBlockStates can be serialized");
+ org.bukkit.craftbukkit.block.CraftBlockState craftBlockState = (org.bukkit.craftbukkit.block.CraftBlockState) blockState;
+
+ CompoundTag compound = new CompoundTag();
+ compound.put("BlockState", net.minecraft.nbt.NbtUtils.writeBlockState(craftBlockState.getHandle()));
2023-10-27 07:51:59 +02:00
+ if (craftBlockState instanceof org.bukkit.craftbukkit.block.CraftBlockEntityState<?>) {
+ compound.put("BlockEntity", ((org.bukkit.craftbukkit.block.CraftBlockEntityState<?>) craftBlockState).getSnapshotNBT());
2023-10-12 17:10:02 +02:00
+ }
+ return serializeNbtToBytes(compound);
+ }
+
+ @Override
+ public org.bukkit.block.BlockState deserializeBlock(byte[] data, org.bukkit.block.Block block) {
+ Preconditions.checkNotNull(data, "null cannot be deserialized");
+ Preconditions.checkArgument(data.length > 0, "cannot deserialize nothing");
+ Preconditions.checkArgument(block instanceof org.bukkit.craftbukkit.block.CraftBlock, "can only deserialize to CraftBlocks");
+ org.bukkit.craftbukkit.block.CraftBlock craftBlock = (org.bukkit.craftbukkit.block.CraftBlock) block;
+
+ CompoundTag compound = deserializeNbtFromBytes(data);
+ int dataVersion = compound.getInt("DataVersion");
+
+ CompoundTag blockStateCompound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.BLOCK_STATE, compound.getCompound("BlockState"), dataVersion, getDataVersion());
+ BlockState blockData = net.minecraft.nbt.NbtUtils.readBlockState(craftBlock.getCraftWorld().getHandle().holderLookup(net.minecraft.core.registries.Registries.BLOCK), blockStateCompound);
+
+ net.minecraft.world.level.block.entity.BlockEntity tileEntity = null;
+ if (compound.contains("BlockEntity", NBT.TAG_COMPOUND)) {
+ CompoundTag blockEntityCompound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.TILE_ENTITY, compound.getCompound("BlockEntity"), dataVersion, getDataVersion());
+ tileEntity = net.minecraft.world.level.block.entity.BlockEntity.loadStatic(craftBlock.getPosition(), blockData, blockEntityCompound);
+ }
+
+ return org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(craftBlock, false, blockData, tileEntity);
+ }
+
private byte[] serializeNbtToBytes(CompoundTag compound) {
compound.putInt("DataVersion", getDataVersion());
java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();