diff --git a/build.gradle.kts b/build.gradle.kts index 6330e1a..b36f496 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,14 +1,14 @@ plugins { `java-library` - id("io.papermc.paperweight.userdev") version "1.5.5" - id("xyz.jpenilla.run-paper") version "2.1.0" // Adds runServer and runMojangMappedServer tasks for testing + id("io.papermc.paperweight.userdev") version "1.5.8" + id("xyz.jpenilla.run-paper") version "2.2.0" // Adds runServer and runMojangMappedServer tasks for testing // Shades and relocates dependencies into our plugin jar. See https://imperceptiblethoughts.com/shadow/introduction/ id("com.github.johnrengelman.shadow") version "8.1.1" } group = "com.moulberry.axiom" -version = "1.4.0" +version = "1.4.1" description = "Serverside component for Axiom on Paper" java { @@ -25,7 +25,7 @@ repositories { } dependencies { - paperweight.paperDevBundle("1.20.1-R0.1-SNAPSHOT") + paperweight.paperDevBundle("1.20.2-R0.1-20231010.011415-29") implementation("xyz.jpenilla:reflection-remapper:0.1.0-SNAPSHOT") // Zstd Compression Library diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37aef8d..c30b486 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/com/moulberry/axiom/AxiomConstants.java b/src/main/java/com/moulberry/axiom/AxiomConstants.java index d0da771..06186b3 100644 --- a/src/main/java/com/moulberry/axiom/AxiomConstants.java +++ b/src/main/java/com/moulberry/axiom/AxiomConstants.java @@ -12,7 +12,7 @@ public class AxiomConstants { } } - public static final int API_VERSION = 6; + public static final int API_VERSION = 7; public static final NamespacedKey ACTIVE_HOTBAR_INDEX = new NamespacedKey("axiom", "active_hotbar_index"); public static final NamespacedKey HOTBAR_DATA = new NamespacedKey("axiom", "hotbar_data"); diff --git a/src/main/java/com/moulberry/axiom/AxiomPaper.java b/src/main/java/com/moulberry/axiom/AxiomPaper.java index a5bf9e5..27b1049 100644 --- a/src/main/java/com/moulberry/axiom/AxiomPaper.java +++ b/src/main/java/com/moulberry/axiom/AxiomPaper.java @@ -2,10 +2,7 @@ package com.moulberry.axiom; import com.moulberry.axiom.buffer.CompressedBlockEntity; import com.moulberry.axiom.event.AxiomCreateWorldPropertiesEvent; -import com.moulberry.axiom.event.AxiomTimeChangeEvent; import com.moulberry.axiom.packet.*; -import com.moulberry.axiom.world_properties.WorldPropertyCategory; -import com.moulberry.axiom.world_properties.WorldPropertyWidgetType; import com.moulberry.axiom.world_properties.server.ServerWorldPropertiesRegistry; import com.moulberry.axiom.world_properties.server.ServerWorldProperty; import io.netty.buffer.Unpooled; @@ -20,15 +17,13 @@ import net.minecraft.network.ConnectionProtocol; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.PacketFlow; -import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket; +import net.minecraft.network.protocol.common.ServerboundCustomPayloadPacket; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.GameRules; import org.bukkit.*; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.messaging.Messenger; import org.checkerframework.checker.nullness.qual.NonNull; @@ -56,7 +51,7 @@ public class AxiomPaper extends JavaPlugin implements Listener { msg.registerOutgoingPluginChannel(this, "axiom:enable"); msg.registerOutgoingPluginChannel(this, "axiom:initialize_hotbars"); msg.registerOutgoingPluginChannel(this, "axiom:set_editor_views"); - msg.registerOutgoingPluginChannel(this, "axiom:block_entities"); + msg.registerOutgoingPluginChannel(this, "axiom:response_chunk_data"); msg.registerOutgoingPluginChannel(this, "axiom:register_world_properties"); msg.registerOutgoingPluginChannel(this, "axiom:set_world_property"); msg.registerOutgoingPluginChannel(this, "axiom:ack_world_properties"); @@ -71,7 +66,7 @@ public class AxiomPaper extends JavaPlugin implements Listener { msg.registerIncomingPluginChannel(this, "axiom:switch_active_hotbar", new SwitchActiveHotbarPacketListener()); msg.registerIncomingPluginChannel(this, "axiom:teleport", new TeleportPacketListener()); msg.registerIncomingPluginChannel(this, "axiom:set_editor_views", new SetEditorViewsPacketListener()); - msg.registerIncomingPluginChannel(this, "axiom:request_block_entity", new RequestBlockEntityPacketListener(this)); + msg.registerIncomingPluginChannel(this, "axiom:request_chunk_data", new RequestChunkDataPacketListener(this)); SetBlockBufferPacketListener setBlockBufferPacketListener = new SetBlockBufferPacketListener(this); @@ -104,7 +99,9 @@ public class AxiomPaper extends JavaPlugin implements Listener { if (!player.hasPermission("axiom.*")) { FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer()); buf.writeBoolean(false); - player.sendPluginMessage(this, "axiom:enable", buf.accessByteBufWithCorrectSize()); + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + player.sendPluginMessage(this, "axiom:enable", bytes); } else { newActiveAxiomPlayers.add(player.getUniqueId()); } diff --git a/src/main/java/com/moulberry/axiom/integration/RegionProtectionWorldGuard.java b/src/main/java/com/moulberry/axiom/integration/RegionProtectionWorldGuard.java index 8f22020..5158140 100644 --- a/src/main/java/com/moulberry/axiom/integration/RegionProtectionWorldGuard.java +++ b/src/main/java/com/moulberry/axiom/integration/RegionProtectionWorldGuard.java @@ -47,7 +47,7 @@ public class RegionProtectionWorldGuard { // Don't do any protection if player has bypass if (platform.getSessionManager().hasBypass(worldGuardPlayer, worldEditWorld)) { // todo: enable bypass -// return null; + return null; } RegionManager regionManager = regionContainer.get(worldEditWorld); @@ -108,7 +108,7 @@ public class RegionProtectionWorldGuard { // } } - System.out.println("returning default"); + // System.out.println("returning default"); StateFlag.State fallback = Flags.BUILD.getDefault(); return fallback == StateFlag.State.DENY ? SectionProtection.DENY : SectionProtection.ALLOW; } @@ -117,7 +117,7 @@ public class RegionProtectionWorldGuard { for (Map.Entry entry : consideredValues.entrySet()) { ProtectedRegion region = entry.getKey(); if (entry.getValue() == StateFlag.State.DENY) { - System.out.println("found region with deny!"); + // System.out.println("found region with deny!"); if (region instanceof GlobalProtectedRegion) { return SectionProtection.DENY; } else if (region instanceof ProtectedCuboidRegion && doesRegionCompletelyContainSection(region, cx, cy, cz)) { @@ -128,7 +128,7 @@ public class RegionProtectionWorldGuard { } if (hasPartialDeny) { - System.out.println("returning check!"); + // System.out.println("returning check!"); return new SectionProtection() { @Override public SectionState getSectionState() { @@ -143,7 +143,7 @@ public class RegionProtectionWorldGuard { // return complex thing } - System.out.println("returning allow!"); + // System.out.println("returning allow!"); return SectionProtection.ALLOW; } diff --git a/src/main/java/com/moulberry/axiom/packet/CustomByteArrayPayload.java b/src/main/java/com/moulberry/axiom/packet/CustomByteArrayPayload.java new file mode 100644 index 0000000..cb2bcd7 --- /dev/null +++ b/src/main/java/com/moulberry/axiom/packet/CustomByteArrayPayload.java @@ -0,0 +1,12 @@ +package com.moulberry.axiom.packet; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; + +public record CustomByteArrayPayload(ResourceLocation id, byte[] bytes) implements CustomPacketPayload { + @Override + public void write(FriendlyByteBuf buf) { + buf.writeBytes(bytes); + } +} diff --git a/src/main/java/com/moulberry/axiom/packet/HelloPacketListener.java b/src/main/java/com/moulberry/axiom/packet/HelloPacketListener.java index 9a908ec..d372c3c 100644 --- a/src/main/java/com/moulberry/axiom/packet/HelloPacketListener.java +++ b/src/main/java/com/moulberry/axiom/packet/HelloPacketListener.java @@ -9,11 +9,12 @@ import com.moulberry.axiom.persistence.UUIDDataType; import com.moulberry.axiom.world_properties.server.ServerWorldPropertiesRegistry; import io.netty.buffer.Unpooled; import net.kyori.adventure.text.Component; +import net.minecraft.SharedConstants; import net.minecraft.network.FriendlyByteBuf; import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; import org.bukkit.World; -import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataContainer; @@ -42,8 +43,14 @@ public class HelloPacketListener implements PluginMessageListener { FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message)); int apiVersion = friendlyByteBuf.readVarInt(); + int dataVersion = friendlyByteBuf.readVarInt(); friendlyByteBuf.readNbt(); // Discard + if (dataVersion != SharedConstants.getCurrentVersion().getDataVersion().getVersion()) { + player.kick(Component.text("Axiom: Incompatible data version detected, are you using ViaVersion?")); + return; + } + if (apiVersion != AxiomConstants.API_VERSION) { player.kick(Component.text("Unsupported Axiom API Version. Server supports " + AxiomConstants.API_VERSION + ", while client is " + apiVersion)); @@ -68,7 +75,10 @@ public class HelloPacketListener implements PluginMessageListener { buf.writeVarInt(5); // Maximum Reach buf.writeVarInt(16); // Max editor views buf.writeBoolean(true); // Editable Views - player.sendPluginMessage(this.plugin, "axiom:enable", buf.accessByteBufWithCorrectSize()); + + byte[] enableBytes = new byte[buf.writerIndex()]; + buf.getBytes(0, enableBytes); + player.sendPluginMessage(this.plugin, "axiom:enable", enableBytes); // Initialize Hotbars PersistentDataContainer container = player.getPersistentDataContainer(); @@ -86,7 +96,10 @@ public class HelloPacketListener implements PluginMessageListener { buf.writeItem(CraftItemStack.asNMSCopy(stack)); } } - player.sendPluginMessage(this.plugin, "axiom:initialize_hotbars", buf.accessByteBufWithCorrectSize()); + + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + player.sendPluginMessage(this.plugin, "axiom:initialize_hotbars", bytes); } // Initialize Views @@ -101,7 +114,9 @@ public class HelloPacketListener implements PluginMessageListener { View.load(view).write(buf); } - player.sendPluginMessage(this.plugin, "axiom:set_editor_views", buf.accessByteBufWithCorrectSize()); + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + player.sendPluginMessage(this.plugin, "axiom:set_editor_views", bytes); } // Register world properties diff --git a/src/main/java/com/moulberry/axiom/packet/RequestBlockEntityPacketListener.java b/src/main/java/com/moulberry/axiom/packet/RequestBlockEntityPacketListener.java deleted file mode 100644 index 84d3cf0..0000000 --- a/src/main/java/com/moulberry/axiom/packet/RequestBlockEntityPacketListener.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.moulberry.axiom.packet; - -import com.moulberry.axiom.AxiomPaper; -import com.moulberry.axiom.buffer.CompressedBlockEntity; -import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.longs.*; -import net.minecraft.core.BlockPos; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceKey; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; -import org.bukkit.entity.Player; -import org.bukkit.plugin.messaging.PluginMessageListener; -import org.jetbrains.annotations.NotNull; - -import java.io.ByteArrayOutputStream; - -public class RequestBlockEntityPacketListener implements PluginMessageListener { - - private final AxiomPaper plugin; - - public RequestBlockEntityPacketListener(AxiomPaper plugin) { - this.plugin = plugin; - } - - @Override - public void onPluginMessageReceived(@NotNull String channel, @NotNull Player bukkitPlayer, @NotNull byte[] message) { - FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message)); - long id = friendlyByteBuf.readLong(); - - if (!bukkitPlayer.hasPermission("axiom.*")) { - // We always send an 'empty' response in order to make the client happy - sendEmptyResponse(bukkitPlayer, id); - return; - } - - ServerPlayer player = ((CraftPlayer)bukkitPlayer).getHandle(); - MinecraftServer server = player.getServer(); - if (server == null) { - sendEmptyResponse(bukkitPlayer, id); - return; - } - - ResourceKey worldKey = friendlyByteBuf.readResourceKey(Registries.DIMENSION); - ServerLevel level = server.getLevel(worldKey); - if (level == null) { - sendEmptyResponse(bukkitPlayer, id); - return; - } - - Long2ObjectMap map = new Long2ObjectOpenHashMap<>(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); - - // Save and compress block entities - int count = friendlyByteBuf.readVarInt(); - for (int i = 0; i < count; i++) { - long pos = friendlyByteBuf.readLong(); - BlockEntity blockEntity = level.getBlockEntity(mutableBlockPos.set(pos)); - if (blockEntity != null) { - CompoundTag tag = blockEntity.saveWithoutMetadata(); - map.put(pos, CompressedBlockEntity.compress(tag, baos)); - } - } - - // Send response packet - FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(16)); - buf.writeLong(id); - buf.writeVarInt(map.size()); - for (Long2ObjectMap.Entry entry : map.long2ObjectEntrySet()) { - buf.writeLong(entry.getLongKey()); - entry.getValue().write(buf); - } - bukkitPlayer.sendPluginMessage(this.plugin, "axiom:block_entities", buf.accessByteBufWithCorrectSize()); - } - - private void sendEmptyResponse(Player player, long id) { - FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(16)); - buf.writeLong(id); - buf.writeByte(0); // no block entities - player.sendPluginMessage(this.plugin, "axiom:block_entities", buf.accessByteBufWithCorrectSize()); - } - -} diff --git a/src/main/java/com/moulberry/axiom/packet/RequestChunkDataPacketListener.java b/src/main/java/com/moulberry/axiom/packet/RequestChunkDataPacketListener.java new file mode 100644 index 0000000..4f83a2a --- /dev/null +++ b/src/main/java/com/moulberry/axiom/packet/RequestChunkDataPacketListener.java @@ -0,0 +1,263 @@ +package com.moulberry.axiom.packet; + +import com.moulberry.axiom.AxiomConstants; +import com.moulberry.axiom.AxiomPaper; +import com.moulberry.axiom.buffer.CompressedBlockEntity; +import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.longs.*; +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; +import net.minecraft.world.level.chunk.PalettedContainer; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.plugin.messaging.PluginMessageListener; +import org.jetbrains.annotations.NotNull; + +import java.io.ByteArrayOutputStream; + +public class RequestChunkDataPacketListener implements PluginMessageListener { + + private static final ResourceLocation RESPONSE_ID = new ResourceLocation("axiom:response_chunk_data"); + + private final AxiomPaper plugin; + + public RequestChunkDataPacketListener(AxiomPaper plugin) { + this.plugin = plugin; + } + + @Override + public void onPluginMessageReceived(@NotNull String channel, @NotNull Player bukkitPlayer, @NotNull byte[] message) { + ServerPlayer player = ((CraftPlayer)bukkitPlayer).getHandle(); + FriendlyByteBuf friendlyByteBuf = new FriendlyByteBuf(Unpooled.wrappedBuffer(message)); + long id = friendlyByteBuf.readLong(); + + if (!bukkitPlayer.hasPermission("axiom.*")) { + // We always send an 'empty' response in order to make the client happy + sendEmptyResponse(player, id); + return; + } + + MinecraftServer server = player.getServer(); + if (server == null) { + sendEmptyResponse(player, id); + return; + } + + ResourceKey worldKey = friendlyByteBuf.readResourceKey(Registries.DIMENSION); + ServerLevel level = server.getLevel(worldKey); + if (level == null) { + sendEmptyResponse(player, id); + return; + } + + boolean sendBlockEntitiesInChunks= friendlyByteBuf.readBoolean(); + + Long2ObjectMap blockEntityMap = new Long2ObjectOpenHashMap<>(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); + + // Save and compress block entities + int count = friendlyByteBuf.readVarInt(); + for (int i = 0; i < count; i++) { + long pos = friendlyByteBuf.readLong(); + BlockEntity blockEntity = level.getBlockEntity(mutableBlockPos.set(pos)); + if (blockEntity != null) { + CompoundTag tag = blockEntity.saveWithoutMetadata(); + blockEntityMap.put(pos, CompressedBlockEntity.compress(tag, baos)); + } + } + + int playerSectionX = player.getBlockX() >> 4; + int playerSectionZ = player.getBlockZ() >> 4; + + Long2ObjectMap> sections = new Long2ObjectOpenHashMap<>(); + count = friendlyByteBuf.readVarInt(); + for (int i = 0; i < count; i++) { + long pos = friendlyByteBuf.readLong(); + + int sx = BlockPos.getX(pos); + int sy = BlockPos.getY(pos); + int sz = BlockPos.getZ(pos); + + int distance = Math.abs(playerSectionX - sx) + Math.abs(playerSectionZ - sz); + if (distance > 128) continue; + + LevelChunk chunk = level.getChunk(sx, sz); + int sectionIndex = chunk.getSectionIndexFromSectionY(sy); + if (sectionIndex < 0 || sectionIndex >= chunk.getSectionsCount()) continue; + LevelChunkSection section = chunk.getSection(sectionIndex); + + if (section.hasOnlyAir()) { + sections.put(pos, null); + } else { + PalettedContainer container = section.getStates(); + sections.put(pos, container); + + if (sendBlockEntitiesInChunks && section.maybeHas(BlockState::hasBlockEntity)) { + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + BlockState blockState = container.get(x, y, z); + if (blockState.hasBlockEntity()) { + mutableBlockPos.set(sx*16 + x, sy*16 + y, sz*16 + z); + BlockEntity blockEntity = chunk.getBlockEntity(mutableBlockPos, LevelChunk.EntityCreationType.CHECK); + if (blockEntity != null) { + CompoundTag tag = blockEntity.saveWithoutMetadata(); + blockEntityMap.put(mutableBlockPos.asLong(), CompressedBlockEntity.compress(tag, baos)); + } + } + } + } + } + } + } + } + + + // Send response packet + + boolean firstPart = true; + int maxSize = 0x100000 - 64; // Leeway of 64 bytes + + FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer()); + buf.writeLong(id); + + for (Long2ObjectMap.Entry entry : blockEntityMap.long2ObjectEntrySet()) { + int beforeWriterIndex = buf.writerIndex(); + + buf.writeLong(entry.getLongKey()); + entry.getValue().write(buf); + + if (buf.writerIndex() >= maxSize) { + if (firstPart) { + // Finish and send current packet + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); + buf.writeBoolean(false); + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + player.connection.send(new ClientboundCustomPayloadPacket(new CustomByteArrayPayload(RESPONSE_ID, bytes))); + + // Continuation packet + buf = new FriendlyByteBuf(Unpooled.buffer()); + buf.writeLong(id); + } else { + // Copy extra bytes + int copiedSize = buf.writerIndex() - beforeWriterIndex; + byte[] copied = new byte[copiedSize]; + buf.getBytes(beforeWriterIndex, copied); + + // Discard extra bytes + buf.writerIndex(beforeWriterIndex); + + // Finish and send current packet + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); + buf.writeBoolean(false); + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + player.connection.send(new ClientboundCustomPayloadPacket(new CustomByteArrayPayload(RESPONSE_ID, bytes))); + + // Continuation packet + buf = new FriendlyByteBuf(Unpooled.buffer()); + buf.writeLong(id); + + // Write start of new packet + buf.writeBytes(copied); + firstPart = true; + } + } else { + firstPart = false; + } + } + + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); + + for (Long2ObjectMap.Entry> entry : sections.long2ObjectEntrySet()) { + int beforeWriterIndex = buf.writerIndex(); + + buf.writeLong(entry.getLongKey()); + var container = entry.getValue(); + if (container == null) { + buf.writeBoolean(false); + } else { + buf.writeBoolean(true); + entry.getValue().write(buf); + } + + if (buf.writerIndex() >= maxSize) { + if (firstPart) { + // Finish and send current packet + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); + buf.writeBoolean(false); + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + player.connection.send(new ClientboundCustomPayloadPacket(new CustomByteArrayPayload(RESPONSE_ID, bytes))); + + // Continuation packet + buf = new FriendlyByteBuf(Unpooled.buffer()); + buf.writeLong(id); + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); + } else { + // Copy extra bytes + int copiedSize = buf.writerIndex() - beforeWriterIndex; + byte[] copied = new byte[copiedSize]; + buf.getBytes(beforeWriterIndex, copied); + + // Discard extra bytes + buf.writerIndex(beforeWriterIndex); + + // Finish and send current packet + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); + buf.writeBoolean(false); + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + player.connection.send(new ClientboundCustomPayloadPacket(new CustomByteArrayPayload(RESPONSE_ID, bytes))); + + // Continuation packet + buf = new FriendlyByteBuf(Unpooled.buffer()); + buf.writeLong(id); + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); + + // Write start of new packet + buf.writeBytes(copied); + firstPart = true; + } + } else { + firstPart = false; + } + } + + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); + buf.writeBoolean(true); + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + player.connection.send(new ClientboundCustomPayloadPacket(new CustomByteArrayPayload(RESPONSE_ID, bytes))); + } + + private void sendEmptyResponse(ServerPlayer player, long id) { + FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(16)); + buf.writeLong(id); + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); // no block entities + buf.writeLong(AxiomConstants.MIN_POSITION_LONG); // no chunks + buf.writeBoolean(true); // finished + + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + player.connection.send(new ClientboundCustomPayloadPacket(new CustomByteArrayPayload(RESPONSE_ID, bytes))); + } + +} diff --git a/src/main/java/com/moulberry/axiom/packet/SetBlockBufferPacketListener.java b/src/main/java/com/moulberry/axiom/packet/SetBlockBufferPacketListener.java index 379054b..c7883ac 100644 --- a/src/main/java/com/moulberry/axiom/packet/SetBlockBufferPacketListener.java +++ b/src/main/java/com/moulberry/axiom/packet/SetBlockBufferPacketListener.java @@ -114,7 +114,7 @@ public class SetBlockBufferPacketListener { Bukkit.getPluginManager().callEvent(modifyWorldEvent); if (modifyWorldEvent.isCancelled()) return; - RegionProtection regionProtection = new RegionProtection(player.getBukkitEntity(), world.getWorld()); + // RegionProtection regionProtection = new RegionProtection(player.getBukkitEntity(), world.getWorld()); // Allowed, apply buffer BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos(); @@ -133,7 +133,7 @@ public class SetBlockBufferPacketListener { continue; } - SectionProtection sectionProtection = regionProtection.getSection(cx, cy, cz); +// SectionProtection sectionProtection = regionProtection.getSection(cx, cy, cz); // switch (sectionProtection.getSectionState()) { // case ALLOW -> sectionProtection = null; // case DENY -> { @@ -171,11 +171,11 @@ public class SetBlockBufferPacketListener { BlockState blockState = container.get(x, y, z); if (blockState == emptyState) continue; - switch (sectionProtection.getSectionState()) { - case ALLOW -> {} - case DENY -> blockState = Blocks.REDSTONE_BLOCK.defaultBlockState(); - case CHECK -> blockState = Blocks.DIAMOND_BLOCK.defaultBlockState(); - } +// switch (sectionProtection.getSectionState()) { +// case ALLOW -> {} +// case DENY -> blockState = Blocks.REDSTONE_BLOCK.defaultBlockState(); +// case CHECK -> blockState = Blocks.DIAMOND_BLOCK.defaultBlockState(); +// } int bx = cx*16 + x; int by = cy*16 + y; diff --git a/src/main/java/com/moulberry/axiom/packet/SetBlockPacketListener.java b/src/main/java/com/moulberry/axiom/packet/SetBlockPacketListener.java index 17e30ec..7db3fb8 100644 --- a/src/main/java/com/moulberry/axiom/packet/SetBlockPacketListener.java +++ b/src/main/java/com/moulberry/axiom/packet/SetBlockPacketListener.java @@ -24,8 +24,8 @@ import net.minecraft.world.level.lighting.LightEngine; import net.minecraft.world.phys.BlockHitResult; import org.bukkit.Bukkit; import org.bukkit.block.BlockFace; -import org.bukkit.craftbukkit.v1_20_R1.block.CraftBlock; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R2.block.CraftBlock; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; import org.bukkit.entity.Player; import org.bukkit.event.block.Action; import org.bukkit.event.player.PlayerInteractEvent; diff --git a/src/main/java/com/moulberry/axiom/packet/SetFlySpeedPacketListener.java b/src/main/java/com/moulberry/axiom/packet/SetFlySpeedPacketListener.java index 5b52e4e..bc516fb 100644 --- a/src/main/java/com/moulberry/axiom/packet/SetFlySpeedPacketListener.java +++ b/src/main/java/com/moulberry/axiom/packet/SetFlySpeedPacketListener.java @@ -1,13 +1,10 @@ package com.moulberry.axiom.packet; import com.moulberry.axiom.event.AxiomFlySpeedChangeEvent; -import com.moulberry.axiom.event.AxiomGameModeChangeEvent; import io.netty.buffer.Unpooled; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.level.GameType; import org.bukkit.Bukkit; -import org.bukkit.GameMode; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; import org.bukkit.entity.Player; import org.bukkit.plugin.messaging.PluginMessageListener; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/com/moulberry/axiom/packet/SetGamemodePacketListener.java b/src/main/java/com/moulberry/axiom/packet/SetGamemodePacketListener.java index c9c18e3..17f321a 100644 --- a/src/main/java/com/moulberry/axiom/packet/SetGamemodePacketListener.java +++ b/src/main/java/com/moulberry/axiom/packet/SetGamemodePacketListener.java @@ -6,7 +6,7 @@ import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.level.GameType; import org.bukkit.Bukkit; import org.bukkit.GameMode; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; import org.bukkit.entity.Player; import org.bukkit.plugin.messaging.PluginMessageListener; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/com/moulberry/axiom/packet/SetHotbarSlotPacketListener.java b/src/main/java/com/moulberry/axiom/packet/SetHotbarSlotPacketListener.java index a91cd63..7d18a7d 100644 --- a/src/main/java/com/moulberry/axiom/packet/SetHotbarSlotPacketListener.java +++ b/src/main/java/com/moulberry/axiom/packet/SetHotbarSlotPacketListener.java @@ -5,8 +5,8 @@ import com.moulberry.axiom.persistence.ItemStackDataType; import io.netty.buffer.Unpooled; import net.minecraft.network.FriendlyByteBuf; import org.bukkit.NamespacedKey; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; import org.bukkit.entity.Player; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; diff --git a/src/main/java/com/moulberry/axiom/packet/SetTimePacketListener.java b/src/main/java/com/moulberry/axiom/packet/SetTimePacketListener.java index 74ebb73..f650fd6 100644 --- a/src/main/java/com/moulberry/axiom/packet/SetTimePacketListener.java +++ b/src/main/java/com/moulberry/axiom/packet/SetTimePacketListener.java @@ -9,7 +9,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.entity.Player; import org.bukkit.plugin.messaging.PluginMessageListener; import org.jetbrains.annotations.NotNull; diff --git a/src/main/java/com/moulberry/axiom/packet/SetWorldPropertyListener.java b/src/main/java/com/moulberry/axiom/packet/SetWorldPropertyListener.java index d1ae1af..c18a72f 100644 --- a/src/main/java/com/moulberry/axiom/packet/SetWorldPropertyListener.java +++ b/src/main/java/com/moulberry/axiom/packet/SetWorldPropertyListener.java @@ -1,27 +1,15 @@ package com.moulberry.axiom.packet; import com.moulberry.axiom.AxiomPaper; -import com.moulberry.axiom.event.AxiomTimeChangeEvent; -import com.moulberry.axiom.world_properties.WorldPropertyCategory; import com.moulberry.axiom.world_properties.server.ServerWorldPropertiesRegistry; import com.moulberry.axiom.world_properties.server.ServerWorldProperty; import io.netty.buffer.Unpooled; -import net.minecraft.core.registries.Registries; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.level.GameRules; -import net.minecraft.world.level.Level; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; import org.bukkit.entity.Player; import org.bukkit.plugin.messaging.PluginMessageListener; import org.jetbrains.annotations.NotNull; -import java.util.List; -import java.util.Map; - public class SetWorldPropertyListener implements PluginMessageListener { @Override @@ -46,8 +34,10 @@ public class SetWorldPropertyListener implements PluginMessageListener { FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer()); buf.writeVarInt(updateId); - player.sendPluginMessage(AxiomPaper.PLUGIN, "axiom:ack_world_properties", - buf.accessByteBufWithCorrectSize()); + + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + player.sendPluginMessage(AxiomPaper.PLUGIN, "axiom:ack_world_properties", bytes); } } diff --git a/src/main/java/com/moulberry/axiom/packet/SwitchActiveHotbarPacketListener.java b/src/main/java/com/moulberry/axiom/packet/SwitchActiveHotbarPacketListener.java index 38badf8..2c98b73 100644 --- a/src/main/java/com/moulberry/axiom/packet/SwitchActiveHotbarPacketListener.java +++ b/src/main/java/com/moulberry/axiom/packet/SwitchActiveHotbarPacketListener.java @@ -7,7 +7,7 @@ import net.minecraft.network.FriendlyByteBuf; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.NamespacedKey; -import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataContainer; diff --git a/src/main/java/com/moulberry/axiom/persistence/ItemStackDataType.java b/src/main/java/com/moulberry/axiom/persistence/ItemStackDataType.java index bf37e0f..babb077 100644 --- a/src/main/java/com/moulberry/axiom/persistence/ItemStackDataType.java +++ b/src/main/java/com/moulberry/axiom/persistence/ItemStackDataType.java @@ -1,8 +1,8 @@ package com.moulberry.axiom.persistence; import net.minecraft.nbt.CompoundTag; -import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; -import org.bukkit.craftbukkit.v1_20_R1.persistence.CraftPersistentDataContainer; +import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R2.persistence.CraftPersistentDataContainer; import org.bukkit.inventory.ItemStack; import org.bukkit.persistence.PersistentDataAdapterContext; import org.bukkit.persistence.PersistentDataContainer; diff --git a/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyDataType.java b/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyDataType.java index 68e59f2..21f8d85 100644 --- a/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyDataType.java +++ b/src/main/java/com/moulberry/axiom/world_properties/WorldPropertyDataType.java @@ -42,7 +42,10 @@ public abstract class WorldPropertyDataType { public byte[] serialize(Integer value) { FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(8)); buf.writeVarInt(value); - return buf.accessByteBufWithCorrectSize(); + + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + return bytes; } @Override @@ -79,7 +82,10 @@ public abstract class WorldPropertyDataType { public byte[] serialize(Item value) { FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(8)); buf.writeId(BuiltInRegistries.ITEM, value); - return buf.accessByteBufWithCorrectSize(); + + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + return bytes; } @Override @@ -99,7 +105,10 @@ public abstract class WorldPropertyDataType { public byte[] serialize(Block value) { FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer(8)); buf.writeId(BuiltInRegistries.BLOCK, value); - return buf.accessByteBufWithCorrectSize(); + + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + return bytes; } @Override diff --git a/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertiesRegistry.java b/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertiesRegistry.java index 91414d2..774b549 100644 --- a/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertiesRegistry.java +++ b/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldPropertiesRegistry.java @@ -9,7 +9,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.GameRules; import org.bukkit.GameRule; import org.bukkit.World; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; @@ -53,8 +53,9 @@ public class ServerWorldPropertiesRegistry { buf.writeCollection(entry.getValue(), (buffer, p) -> p.write(buffer)); } - bukkitPlayer.sendPluginMessage(plugin, "axiom:register_world_properties", - buf.accessByteBufWithCorrectSize()); + byte[] bytes = new byte[buf.writerIndex()]; + buf.getBytes(0, bytes); + bukkitPlayer.sendPluginMessage(plugin, "axiom:register_world_properties", bytes); } public void registerDefault(World world) { diff --git a/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldProperty.java b/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldProperty.java index 5f861f7..e5c8d5b 100644 --- a/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldProperty.java +++ b/src/main/java/com/moulberry/axiom/world_properties/server/ServerWorldProperty.java @@ -61,7 +61,8 @@ public class ServerWorldProperty { buf.writeVarInt(this.widget.dataType().getTypeId()); buf.writeByteArray(this.widget.dataType().serialize(this.value)); - byte[] message = buf.accessByteBufWithCorrectSize(); + byte[] message = new byte[buf.writerIndex()]; + buf.getBytes(0, message); for (Player player : world.getPlayers()) { if (AxiomPaper.PLUGIN.activeAxiomPlayers.contains(player.getUniqueId())) { player.sendPluginMessage(AxiomPaper.PLUGIN, "axiom:set_world_property", message);