From 83d2509ccc93b51651a23c5d2a7c712994581dda Mon Sep 17 00:00:00 2001 From: FalsePattern Date: Sat, 16 Nov 2024 23:07:36 +0100 Subject: [PATCH] block packet API --- .../falsepattern/chunk/api/DataManager.java | 39 +++++- .../chunk/internal/BlockPosUtil.java | 28 +++++ .../chunk/internal/DataRegistryImpl.java | 39 ++++++ .../impl/CustomPacketBlockChange.java | 13 ++ .../impl/CustomPacketMultiBlockChange.java | 9 ++ .../vanilla/NetHandlerPlayClientMixin.java | 57 +++++++++ .../common/vanilla/PlayerInstanceMixin.java | 28 +++++ .../S22PacketMultiBlockChangeMixin.java | 113 ++++++++++++++++++ .../vanilla/S23PacketBlockChangeMixin.java | 107 +++++++++++++++++ .../chunk/internal/mixin/plugin/Mixin.java | 4 + .../chunk/internal/vanilla/BiomeManager.java | 4 +- .../internal/vanilla/BlockIDManager.java | 50 ++++++-- .../chunk/internal/vanilla/NibbleManager.java | 4 +- .../internal/vanilla/SkylightManager.java | 4 +- src/main/resources/META-INF/chunkapi_at.cfg | 1 + 15 files changed, 482 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/falsepattern/chunk/internal/BlockPosUtil.java create mode 100644 src/main/java/com/falsepattern/chunk/internal/impl/CustomPacketBlockChange.java create mode 100644 src/main/java/com/falsepattern/chunk/internal/impl/CustomPacketMultiBlockChange.java create mode 100644 src/main/java/com/falsepattern/chunk/internal/mixin/mixins/client/vanilla/NetHandlerPlayClientMixin.java create mode 100644 src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/PlayerInstanceMixin.java create mode 100644 src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/S22PacketMultiBlockChangeMixin.java create mode 100644 src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/S23PacketBlockChangeMixin.java diff --git a/src/main/java/com/falsepattern/chunk/api/DataManager.java b/src/main/java/com/falsepattern/chunk/api/DataManager.java index 6de3928..24d9625 100644 --- a/src/main/java/com/falsepattern/chunk/api/DataManager.java +++ b/src/main/java/com/falsepattern/chunk/api/DataManager.java @@ -32,9 +32,12 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S23PacketBlockChange; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; +import java.io.IOException; import java.nio.ByteBuffer; /** @@ -95,11 +98,10 @@ public interface DataManager { */ @Contract(mutates = "param4") @StableAPI.Expose - void writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer data); + void writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer buffer); /** * Deserializes your data from a packet. - * Mutates this object. * * @param chunk The chunk to deserialize. * @param buffer The packet buffer to read from. @@ -109,6 +111,39 @@ public interface DataManager { void readFromBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer buffer); } + /** + * Implement this interface if you additionally want to synchronize your data on single and multi-block updates, + * not just chunk updates. + * + * @since TODO + * @author FalsePattern + * @version TODO + */ + @StableAPI(since = "TODO") + interface BlockPacketDataManager extends DataManager { + @Contract(mutates = "param1") + @StableAPI.Expose + void writeBlockToPacket(Chunk chunk, int x, int y, int z, S23PacketBlockChange packet); + + @Contract(mutates = "param1,param5") + @StableAPI.Expose + void readBlockFromPacket(Chunk chunk, int x, int y, int z, S23PacketBlockChange packet); + + /** + * Serializes your block data into a buffer. + */ + @Contract(mutates = "param2") + @StableAPI.Expose + void writeBlockPacketToBuffer(S23PacketBlockChange packet, PacketBuffer buffer) throws IOException; + + /** + * Deserializes your block data from a buffer. + */ + @Contract(mutates = "param1,param2") + @StableAPI.Expose + void readBlockPacketFromBuffer(S23PacketBlockChange packet, PacketBuffer buffer) throws IOException; + } + /** * The common superinterface for RootDataManager and SubChunkDataManager. * Contains version information and messages for users attempting to upgrade/remove versions. diff --git a/src/main/java/com/falsepattern/chunk/internal/BlockPosUtil.java b/src/main/java/com/falsepattern/chunk/internal/BlockPosUtil.java new file mode 100644 index 0000000..ff53856 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/BlockPosUtil.java @@ -0,0 +1,28 @@ +package com.falsepattern.chunk.internal; + +public class BlockPosUtil { + private static final int NUM_X_BITS = 26; + private static final int NUM_Z_BITS = 26; + private static final int NUM_Y_BITS = 64 - NUM_X_BITS - NUM_Z_BITS; + private static final long Y_MASK = (1L << NUM_Y_BITS) - 1L; + private static final int Y_SHIFT = NUM_Z_BITS; + private static final int X_SHIFT = Y_SHIFT + NUM_Y_BITS; + private static final long Z_MASK = (1L << NUM_Z_BITS) - 1L; + private static final long X_MASK = (1L << NUM_X_BITS) - 1L; + + public static long packToLong(int x, int y, int z) { + return ((long) x & X_MASK) << X_SHIFT | ((long) y & Y_MASK) << Y_SHIFT | ((long) z & Z_MASK); + } + + public static int getX(long packed) { + return (int) (packed << 64 - X_SHIFT - NUM_X_BITS >> 64 - NUM_X_BITS); + } + + public static int getY(long packed) { + return (int) (packed << 64 - Y_SHIFT - NUM_Y_BITS >> 64 - NUM_Y_BITS); + } + + public static int getZ(long packed) { + return (int) (packed << 64 - NUM_Z_BITS >> 64 - NUM_Z_BITS); + } +} diff --git a/src/main/java/com/falsepattern/chunk/internal/DataRegistryImpl.java b/src/main/java/com/falsepattern/chunk/internal/DataRegistryImpl.java index 1481d72..17da2c3 100644 --- a/src/main/java/com/falsepattern/chunk/internal/DataRegistryImpl.java +++ b/src/main/java/com/falsepattern/chunk/internal/DataRegistryImpl.java @@ -33,6 +33,8 @@ import lombok.var; import org.jetbrains.annotations.Nullable; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S23PacketBlockChange; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraftforge.common.util.Constants; @@ -55,6 +57,7 @@ import java.util.stream.Collectors; public class DataRegistryImpl { private static final Set managers = new HashSet<>(); private static final Map packetManagers = new HashMap<>(); + private static final Map blockPacketManagers = new HashMap<>(); private static final Map NBTManagers = new HashMap<>(); private static final Map chunkNBTManagers = new HashMap<>(); private static final Map subChunkNBTManagers = new HashMap<>(); @@ -90,6 +93,10 @@ public class DataRegistryImpl { maxPacketSize += 4 + id.getBytes(StandardCharsets.UTF_8).length + 4 + maxSize; packetManagers.put(id, new PacketManagerInfo(maxSize, packetManager)); } + if (manager instanceof DataManager.BlockPacketDataManager) { + val blockPacketManager = (DataManager.BlockPacketDataManager) manager; + blockPacketManagers.put(id, blockPacketManager); + } if (manager instanceof DataManager.StorageDataManager) { NBTManagers.put(id, (DataManager.StorageDataManager) manager); if (manager instanceof DataManager.ChunkDataManager) { @@ -116,6 +123,7 @@ public class DataRegistryImpl { val removed = packetManagers.remove(manager); maxPacketSize -= 4 + id.getBytes(StandardCharsets.UTF_8).length + 4 + removed.maxPacketSize; } + blockPacketManagers.remove(manager); chunkNBTManagers.remove(manager); subChunkNBTManagers.remove(manager); NBTManagers.remove(manager); @@ -183,6 +191,37 @@ public class DataRegistryImpl { return buf.position(); } + public static void writeBlockToPacket(Chunk chunk, int x, int y, int z, S23PacketBlockChange packet) { + for (val manager: blockPacketManagers.values()) { + manager.writeBlockToPacket(chunk, x, y, z, packet); + } + } + + public static void readBlockFromPacket(Chunk chunk, int x, int y, int z, S23PacketBlockChange packet) { + for (val manager: blockPacketManagers.values()) { + manager.readBlockFromPacket(chunk, x, y, z, packet); + } + } + + public static void writeBlockPacketToBuffer(S23PacketBlockChange packet, PacketBuffer buffer) throws IOException { + buffer.writeInt(blockPacketManagers.size()); + for (val pair: blockPacketManagers.entrySet()) { + val id = pair.getKey(); + val manager = pair.getValue(); + buffer.writeStringToBuffer(id); + manager.writeBlockPacketToBuffer(packet, buffer); + } + } + + public static void readBlockPacketFromBuffer(S23PacketBlockChange packet, PacketBuffer buffer) throws IOException { + int count = buffer.readInt(); + for (int i = 0; i < count; i++) { + val id = buffer.readStringFromBuffer(1024); + val manager = blockPacketManagers.get(id); + manager.readBlockPacketFromBuffer(packet, buffer); + } + } + private static ByteBuffer createSlice(ByteBuffer buffer, int start, int length) { int oldLimit = buffer.limit(); int oldPosition = buffer.position(); diff --git a/src/main/java/com/falsepattern/chunk/internal/impl/CustomPacketBlockChange.java b/src/main/java/com/falsepattern/chunk/internal/impl/CustomPacketBlockChange.java new file mode 100644 index 0000000..01e1800 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/impl/CustomPacketBlockChange.java @@ -0,0 +1,13 @@ +package com.falsepattern.chunk.internal.impl; + +import net.minecraft.world.chunk.Chunk; + +public interface CustomPacketBlockChange { + void chunkapi$init(int x, int y, int z, Chunk chunk); + void chunkapi$x(int value); + void chunkapi$y(int value); + void chunkapi$z(int value); + int chunkapi$x(); + int chunkapi$y(); + int chunkapi$z(); +} diff --git a/src/main/java/com/falsepattern/chunk/internal/impl/CustomPacketMultiBlockChange.java b/src/main/java/com/falsepattern/chunk/internal/impl/CustomPacketMultiBlockChange.java new file mode 100644 index 0000000..5d9a3c8 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/impl/CustomPacketMultiBlockChange.java @@ -0,0 +1,9 @@ +package com.falsepattern.chunk.internal.impl; + +import net.minecraft.network.play.server.S23PacketBlockChange; +import net.minecraft.world.chunk.Chunk; + +public interface CustomPacketMultiBlockChange { + void chunkapi$init(int count, short[] crammedPositions, Chunk chunk); + S23PacketBlockChange[] chunkapi$subPackets(); +} diff --git a/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/client/vanilla/NetHandlerPlayClientMixin.java b/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/client/vanilla/NetHandlerPlayClientMixin.java new file mode 100644 index 0000000..15ce716 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/client/vanilla/NetHandlerPlayClientMixin.java @@ -0,0 +1,57 @@ +package com.falsepattern.chunk.internal.mixin.mixins.client.vanilla; + +import com.falsepattern.chunk.internal.DataRegistryImpl; +import com.falsepattern.chunk.internal.impl.CustomPacketBlockChange; +import com.falsepattern.chunk.internal.impl.CustomPacketMultiBlockChange; +import lombok.val; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.network.play.INetHandlerPlayClient; +import net.minecraft.network.play.server.S22PacketMultiBlockChange; +import net.minecraft.network.play.server.S23PacketBlockChange; + +@Mixin(NetHandlerPlayClient.class) +public abstract class NetHandlerPlayClientMixin implements INetHandlerPlayClient { + @Shadow + private WorldClient clientWorldController; + + @Inject(method = "handleBlockChange", + at = @At(value = "RETURN"), + require = 1) + private void doHandleBlockChange(S23PacketBlockChange packetIn, CallbackInfo ci) { + val cPacket = (CustomPacketBlockChange) packetIn; + val x = cPacket.chunkapi$x(); + val y = cPacket.chunkapi$y(); + val z = cPacket.chunkapi$z(); + val chunk = clientWorldController.getChunkFromBlockCoords(x, z); + DataRegistryImpl.readBlockFromPacket(chunk, x & 0xf, y, z & 0xf, packetIn); + } + + /** + * @author FalsePattern + * @reason Integrate + */ + @Overwrite + public void handleMultiBlockChange(S22PacketMultiBlockChange packetIn) { + val cX = packetIn.func_148920_c().chunkXPos; + val cZ = packetIn.func_148920_c().chunkZPos; + val chunk = clientWorldController.getChunkFromChunkCoords(cX, cZ); + val bX = cX * 16; + val bZ = cZ * 16; + for (val subPacket : ((CustomPacketMultiBlockChange) packetIn).chunkapi$subPackets()) { + val cSub = (CustomPacketBlockChange) subPacket; + val x = cSub.chunkapi$x(); + val y = cSub.chunkapi$y(); + val z = cSub.chunkapi$z(); + this.clientWorldController.func_147492_c(x + bX, y, z + bZ, subPacket.func_148880_c(), subPacket.func_148881_g()); + DataRegistryImpl.readBlockFromPacket(chunk, x, y, z, subPacket); + } + } +} diff --git a/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/PlayerInstanceMixin.java b/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/PlayerInstanceMixin.java new file mode 100644 index 0000000..9f1dc2a --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/PlayerInstanceMixin.java @@ -0,0 +1,28 @@ +package com.falsepattern.chunk.internal.mixin.mixins.common.vanilla; + +import com.falsepattern.chunk.internal.impl.CustomPacketMultiBlockChange; +import lombok.val; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S22PacketMultiBlockChange; +import net.minecraft.server.management.PlayerManager; +import net.minecraft.world.chunk.Chunk; + +@Mixin(PlayerManager.PlayerInstance.class) +public abstract class PlayerInstanceMixin { + /** + * S22PacketMultiBlockChange is an absolute, utter pain in the ass to properly integrate with. + */ + @Redirect(method = "sendChunkUpdate", + at = @At(value = "NEW", + target = "(I[SLnet/minecraft/world/chunk/Chunk;)Lnet/minecraft/network/play/server/S22PacketMultiBlockChange;"), + require = 1) + private S22PacketMultiBlockChange hijackPacket(int count, short[] positions, Chunk chunk) { + val packet = new S22PacketMultiBlockChange(); + ((CustomPacketMultiBlockChange)packet).chunkapi$init(count, positions, chunk); + return packet; + } +} diff --git a/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/S22PacketMultiBlockChangeMixin.java b/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/S22PacketMultiBlockChangeMixin.java new file mode 100644 index 0000000..79eb065 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/S22PacketMultiBlockChangeMixin.java @@ -0,0 +1,113 @@ +package com.falsepattern.chunk.internal.mixin.mixins.common.vanilla; + +import com.falsepattern.chunk.internal.DataRegistryImpl; +import com.falsepattern.chunk.internal.impl.CustomPacketBlockChange; +import com.falsepattern.chunk.internal.impl.CustomPacketMultiBlockChange; +import io.netty.buffer.AbstractByteBuf; +import io.netty.buffer.Unpooled; +import lombok.val; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.INetHandlerPlayClient; +import net.minecraft.network.play.server.S22PacketMultiBlockChange; +import net.minecraft.network.play.server.S23PacketBlockChange; +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraft.world.chunk.Chunk; +import cpw.mods.fml.common.network.ByteBufUtils; + +import java.io.IOException; + +@Mixin(S22PacketMultiBlockChange.class) +public abstract class S22PacketMultiBlockChangeMixin implements CustomPacketMultiBlockChange { + @Shadow(aliases = "field_148925_b") + private ChunkCoordIntPair coord; + + private S23PacketBlockChange[] subPackets; + + @Inject(method = "(I[SLnet/minecraft/world/chunk/Chunk;)V", + at = @At(value = "FIELD", + target = "Lnet/minecraft/network/play/server/S22PacketMultiBlockChange;field_148925_b:Lnet/minecraft/world/ChunkCoordIntPair;"), + require = 1) + private void suppressConstructor(int p_i45181_1_, short[] crammedPositions, Chunk chunk, CallbackInfo ci) { + throw new IllegalStateException( + "S22PacketMultiBlockChange constructor is not supported by ChunkAPI. Please report this to FalsePattern!"); + } + + @Override + public void chunkapi$init(int count, short[] crammedPositions, Chunk chunk) { + coord = new ChunkCoordIntPair(chunk.xPosition, chunk.zPosition); + subPackets = new S23PacketBlockChange[count]; + for (int i = 0; i < count; ++i) { + val subPacket = new S23PacketBlockChange(); + int x = crammedPositions[i] >> 12 & 0xf; + int z = crammedPositions[i] >> 8 & 0xf; + int y = crammedPositions[i] & 0xff; + ((CustomPacketBlockChange) subPacket).chunkapi$init(x, y, z, chunk); + subPackets[i] = subPacket; + } + } + + + /** + * Reads the raw packet data from the data stream. + * + * @author FalsePattern + * @reason Integrate + */ + @Overwrite + public void readPacketData(PacketBuffer data) throws IOException { + coord = new ChunkCoordIntPair(data.readInt(), data.readInt()); + int count = data.readVarIntFromBuffer(); + subPackets = new S23PacketBlockChange[count]; + for (int i = 0; i < count; ++i) { + val subPacket = new S23PacketBlockChange(); + subPackets[i] = subPacket; + val cSub = (CustomPacketBlockChange) subPacket; + val pos = data.readUnsignedShort(); + val x = pos >> 12 & 0xf; + val z = pos >> 8 & 0xf; + val y = pos & 0xff; + cSub.chunkapi$x(x); + cSub.chunkapi$y(y); + cSub.chunkapi$z(z); + DataRegistryImpl.readBlockPacketFromBuffer(subPacket, data); + } + } + + /** + * Writes the raw packet data to the data stream. + * + * @author FalsePattern + * @reason Integrate + */ + @Overwrite + public void writePacketData(PacketBuffer data) throws IOException { + data.writeInt(coord.chunkXPos); + data.writeInt(coord.chunkZPos); + + if (subPackets != null) { + data.writeVarIntToBuffer(subPackets.length); + for (val subPacket : subPackets) { + val cSub = (CustomPacketBlockChange) subPacket; + int pos = ((cSub.chunkapi$x() & 0xf) << 12) | + ((cSub.chunkapi$z() & 0xf) << 8) | + (cSub.chunkapi$y() & 0xff); + data.writeShort(pos); + DataRegistryImpl.writeBlockPacketToBuffer(subPacket, data); + } + } else { + data.writeInt(0); + } + } + + @Override + public S23PacketBlockChange[] chunkapi$subPackets() { + return subPackets; + } +} diff --git a/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/S23PacketBlockChangeMixin.java b/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/S23PacketBlockChangeMixin.java new file mode 100644 index 0000000..5792e41 --- /dev/null +++ b/src/main/java/com/falsepattern/chunk/internal/mixin/mixins/common/vanilla/S23PacketBlockChangeMixin.java @@ -0,0 +1,107 @@ +package com.falsepattern.chunk.internal.mixin.mixins.common.vanilla; + +import com.falsepattern.chunk.internal.BlockPosUtil; +import com.falsepattern.chunk.internal.DataRegistryImpl; +import com.falsepattern.chunk.internal.impl.CustomPacketBlockChange; +import lombok.SneakyThrows; +import lombok.val; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.block.Block; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S23PacketBlockChange; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +import java.io.IOException; + +@Mixin(S23PacketBlockChange.class) +public abstract class S23PacketBlockChangeMixin implements CustomPacketBlockChange { + @Shadow(aliases = "field_148887_a") + private int xCoord; + @Shadow(aliases = "field_148885_b") + private int yCoord; + @Shadow(aliases = "field_148886_c") + private int zCoord; + + @Shadow public Block field_148883_d; + + @Shadow public int field_148884_e; + + @Override + public void chunkapi$init(int x, int y, int z, Chunk chunk) { + xCoord = x; + yCoord = y; + zCoord = z; + field_148883_d = chunk.getBlock(x, y, z); + field_148884_e = chunk.getBlockMetadata(x, y, z); + DataRegistryImpl.writeBlockToPacket(chunk, x, y, z, (S23PacketBlockChange) (Object) this); + } + + @Inject(method = "(IIILnet/minecraft/world/World;)V", + at = @At("RETURN"), + require = 1) + private void writeBlockToPacket(int x, int y, int z, World world, CallbackInfo ci) { + val chunk = world.getChunkFromBlockCoords(x, z); + DataRegistryImpl.writeBlockToPacket(chunk, x & 0xf, y, z & 0xf, (S23PacketBlockChange) (Object) this); + } + + /** + * @author FalsePattern + * @reason Integrate + */ + @Overwrite + public void readPacketData(PacketBuffer data) throws IOException { + long packed = data.readLong(); + xCoord = BlockPosUtil.getX(packed); + yCoord = BlockPosUtil.getY(packed); + zCoord = BlockPosUtil.getZ(packed); + DataRegistryImpl.readBlockPacketFromBuffer((S23PacketBlockChange) (Object) this, data); + } + + /** + * @author FalsePattern + * @reason Integrate + */ + @Overwrite + public void writePacketData(PacketBuffer data) throws IOException { + long packed = BlockPosUtil.packToLong(xCoord, yCoord, zCoord); + data.writeLong(packed); + DataRegistryImpl.writeBlockPacketToBuffer((S23PacketBlockChange) (Object) this, data); + } + + @Override + public void chunkapi$x(int value) { + xCoord = value; + } + + @Override + public void chunkapi$y(int value) { + yCoord = value; + } + + @Override + public void chunkapi$z(int value) { + zCoord = value; + } + + @Override + public int chunkapi$x() { + return xCoord; + } + + @Override + public int chunkapi$y() { + return yCoord; + } + + @Override + public int chunkapi$z() { + return zCoord; + } +} diff --git a/src/main/java/com/falsepattern/chunk/internal/mixin/plugin/Mixin.java b/src/main/java/com/falsepattern/chunk/internal/mixin/plugin/Mixin.java index 54457cd..8ac1819 100644 --- a/src/main/java/com/falsepattern/chunk/internal/mixin/plugin/Mixin.java +++ b/src/main/java/com/falsepattern/chunk/internal/mixin/plugin/Mixin.java @@ -40,10 +40,14 @@ import static com.falsepattern.lib.mixin.IMixin.PredicateHelpers.always; public enum Mixin implements IMixin { // @formatter:off AnvilChunkLoaderMixin(Side.COMMON, always(), "vanilla.AnvilChunkLoaderMixin"), + PlayerInstanceMixin(Side.COMMON, always(), "vanilla.PlayerInstanceMixin"), S21PacketChunkDataMixin(Side.COMMON, always(), "vanilla.S21PacketChunkDataMixin"), + S22PacketMultiBlockChangeMixin(Side.COMMON, always(), "vanilla.S22PacketMultiBlockChangeMixin"), + S23PacketBlockChangeMixin(Side.COMMON, always(), "vanilla.S23PacketBlockChangeMixin"), S26PacketMapChunkBulkMixin(Side.COMMON, always(), "vanilla.S26PacketMapChunkBulkMixin"), ChunkMixin(Side.CLIENT, always(), "vanilla.ChunkMixin"), + NetHandlerPlayClientMixin(Side.CLIENT, always(), "vanilla.NetHandlerPlayClientMixin"), ; // @formatter:on diff --git a/src/main/java/com/falsepattern/chunk/internal/vanilla/BiomeManager.java b/src/main/java/com/falsepattern/chunk/internal/vanilla/BiomeManager.java index e2483a5..2d98535 100644 --- a/src/main/java/com/falsepattern/chunk/internal/vanilla/BiomeManager.java +++ b/src/main/java/com/falsepattern/chunk/internal/vanilla/BiomeManager.java @@ -50,9 +50,9 @@ public class BiomeManager extends VanillaManager } @Override - public void writeToBuffer(@NotNull Chunk chunk, int subChunkMask, boolean forceUpdate, @NotNull ByteBuffer data) { + public void writeToBuffer(@NotNull Chunk chunk, int subChunkMask, boolean forceUpdate, @NotNull ByteBuffer buffer) { if (forceUpdate) { - data.put(chunk.getBiomeArray()); + buffer.put(chunk.getBiomeArray()); } } diff --git a/src/main/java/com/falsepattern/chunk/internal/vanilla/BlockIDManager.java b/src/main/java/com/falsepattern/chunk/internal/vanilla/BlockIDManager.java index cd0629b..da7c6ac 100644 --- a/src/main/java/com/falsepattern/chunk/internal/vanilla/BlockIDManager.java +++ b/src/main/java/com/falsepattern/chunk/internal/vanilla/BlockIDManager.java @@ -30,18 +30,25 @@ import com.falsepattern.chunk.api.ArrayUtil; import com.falsepattern.chunk.api.DataManager; import lombok.val; +import net.minecraft.block.Block; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S23PacketBlockChange; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.NibbleArray; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; +import java.io.IOException; import java.nio.ByteBuffer; import static com.falsepattern.chunk.internal.Common.BLOCKS_PER_SUBCHUNK; import static com.falsepattern.chunk.internal.Common.SUBCHUNKS_PER_CHUNK; public class BlockIDManager extends VanillaManager - implements DataManager.PacketDataManager, DataManager.SubChunkDataManager { + implements + DataManager.PacketDataManager, + DataManager.BlockPacketDataManager, + DataManager.SubChunkDataManager { private static final int LSB_BYTES_PER_SUBCHUNK = BLOCKS_PER_SUBCHUNK; private static final int MSB_BYTES_PER_SUBCHUNK = BLOCKS_PER_SUBCHUNK / 2; private static final int HEADER_SIZE = 2; @@ -57,27 +64,27 @@ public class BlockIDManager extends VanillaManager } @Override - public void writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer data) { + public void writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer buffer) { val subChunks = chunk.getBlockStorageArray(); - int currentPos = data.position(); - data.putShort((short) 0); + int currentPos = buffer.position(); + buffer.putShort((short) 0); int msbMask = 0; for (int i = 0; i < subChunks.length; i++) { if ((subChunkMask & (1 << i)) != 0) { val subChunk = subChunks[i]; val lsb = subChunk.getBlockLSBArray(); val msb = subChunk.getBlockMSBArray(); - data.put(lsb); + buffer.put(lsb); if (msb != null) { msbMask |= 1 << i; - data.put(msb.data); + buffer.put(msb.data); } } } - int endPos = data.position(); - data.position(currentPos); - data.putShort((short) msbMask); - data.position(endPos); + int endPos = buffer.position(); + buffer.position(currentPos); + buffer.putShort((short) msbMask); + buffer.position(endPos); } @Override @@ -129,4 +136,27 @@ public class BlockIDManager extends VanillaManager to.setBlockLSBArray(ArrayUtil.copyArray(from.getBlockLSBArray(), to.getBlockLSBArray())); to.setBlockMSBArray(ArrayUtil.copyArray(from.getBlockMSBArray(), to.getBlockMSBArray())); } + + @Override + public void writeBlockToPacket(Chunk chunk, int x, int y, int z, S23PacketBlockChange packet) { + } + + @Override + public void readBlockFromPacket(Chunk chunk, int x, int y, int z, S23PacketBlockChange packet) { + + } + + @Override + public void writeBlockPacketToBuffer(S23PacketBlockChange packet, PacketBuffer buffer) throws IOException { + buffer.writeShort((short)((Block.getIdFromBlock(packet.field_148883_d) & 0xFFF) << 4 | packet.field_148884_e & 0xF)); + } + + @Override + public void readBlockPacketFromBuffer(S23PacketBlockChange packet, PacketBuffer buffer) throws IOException { + int packed = buffer.readUnsignedShort(); + int id = (packed >> 4) & 0xFFF; + int meta = packed & 0xF; + packet.field_148883_d = Block.getBlockById(id); + packet.field_148884_e = meta; + } } diff --git a/src/main/java/com/falsepattern/chunk/internal/vanilla/NibbleManager.java b/src/main/java/com/falsepattern/chunk/internal/vanilla/NibbleManager.java index 3c2820f..9f51a11 100644 --- a/src/main/java/com/falsepattern/chunk/internal/vanilla/NibbleManager.java +++ b/src/main/java/com/falsepattern/chunk/internal/vanilla/NibbleManager.java @@ -47,13 +47,13 @@ public abstract class NibbleManager extends VanillaManager implements DataManage } @Override - public void writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer data) { + public void writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer buffer) { val subChunks = chunk.getBlockStorageArray(); for (int i = 0; i < subChunks.length; i++) { if ((subChunkMask & (1 << i)) != 0) { val subChunk = subChunks[i]; if (subChunk != null) { - data.put(getNibbleArray(subChunk).data, 0, BYTES_PER_SUBCHUNK); + buffer.put(getNibbleArray(subChunk).data, 0, BYTES_PER_SUBCHUNK); } } } diff --git a/src/main/java/com/falsepattern/chunk/internal/vanilla/SkylightManager.java b/src/main/java/com/falsepattern/chunk/internal/vanilla/SkylightManager.java index 38fd396..a7140df 100644 --- a/src/main/java/com/falsepattern/chunk/internal/vanilla/SkylightManager.java +++ b/src/main/java/com/falsepattern/chunk/internal/vanilla/SkylightManager.java @@ -48,9 +48,9 @@ public class SkylightManager extends NibbleManager implements DataManager.SubChu } @Override - public void writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer data) { + public void writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer buffer) { if (!chunk.worldObj.provider.hasNoSky) { - super.writeToBuffer(chunk, subChunkMask, forceUpdate, data); + super.writeToBuffer(chunk, subChunkMask, forceUpdate, buffer); } } diff --git a/src/main/resources/META-INF/chunkapi_at.cfg b/src/main/resources/META-INF/chunkapi_at.cfg index e6a2269..d9331cd 100644 --- a/src/main/resources/META-INF/chunkapi_at.cfg +++ b/src/main/resources/META-INF/chunkapi_at.cfg @@ -1,3 +1,4 @@ public-f net.minecraft.world.chunk.NibbleArray field_76585_a # data public-f net.minecraft.world.chunk.NibbleArray field_76583_b # depthBits public-f net.minecraft.world.chunk.NibbleArray field_76584_c # depthBitsPlusFour +public net.minecraft.server.management.PlayerManager$PlayerInstance