diff --git a/patches/api/0010-Bytebuf-API.patch b/patches/api/0010-Bytebuf-API.patch new file mode 100644 index 00000000..d09af222 --- /dev/null +++ b/patches/api/0010-Bytebuf-API.patch @@ -0,0 +1,396 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> +Date: Wed, 22 May 2024 10:12:04 +0800 +Subject: [PATCH] Bytebuf API + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 3c2b252243c1fa0d3adcc9c860c24af73165de33..1caffc8771680505be1c51a2f5050528435cdc33 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -2919,6 +2919,12 @@ public final class Bukkit { + } + // Leaves end - Photographer API + ++ // Leaves start - Bytebuf API ++ public static org.leavesmc.leaves.bytebuf.BytebufManager getBytebufManager() { ++ return server.getBytebufManager(); ++ } ++ // Leaves end - Bytebuf API ++ + @NotNull + public static Server.Spigot spigot() { + return server.spigot(); +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index 4a03044938630e4a0e701bc481f15da5a3323115..7a006d2582cd91b83ab05aeb6d6a6f96b77d2dbc 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -2564,4 +2564,8 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + // Leaves start - Photographer API + @NotNull PhotographerManager getPhotographerManager(); + // Leaves end - Photographer API ++ ++ // Leaves start - Bytebuf API ++ org.leavesmc.leaves.bytebuf.BytebufManager getBytebufManager(); ++ // Leaves end - Bytebuf API + } +diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java +index 6c327a07bf8a6aa11a2d7dad12b2830acc539484..e3e4bed888133422bd879479793a01eadbdef85e 100644 +--- a/src/main/java/org/bukkit/entity/Player.java ++++ b/src/main/java/org/bukkit/entity/Player.java +@@ -3802,6 +3802,12 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM + boolean isChunkSent(long chunkKey); + // Paper end + ++ // Leaves start - Bytebuf API ++ void sendPacket(org.leavesmc.leaves.bytebuf.packet.Packet packet); ++ ++ void sendPacket(org.leavesmc.leaves.bytebuf.Bytebuf buf, org.leavesmc.leaves.bytebuf.packet.PacketType type); ++ // Leaves end - Bytebuf API ++ + @NotNull + @Override + Spigot spigot(); +diff --git a/src/main/java/org/leavesmc/leaves/bytebuf/Bytebuf.java b/src/main/java/org/leavesmc/leaves/bytebuf/Bytebuf.java +new file mode 100644 +index 0000000000000000000000000000000000000000..657eee1d4a18f765480135ef50f5ef65fdc3ed28 +--- /dev/null ++++ b/src/main/java/org/leavesmc/leaves/bytebuf/Bytebuf.java +@@ -0,0 +1,102 @@ ++package org.leavesmc.leaves.bytebuf; ++ ++import com.google.gson.JsonElement; ++import org.bukkit.Bukkit; ++import org.bukkit.inventory.ItemStack; ++ ++import java.util.UUID; ++ ++public interface Bytebuf { ++ ++ static Bytebuf buf(int size) { ++ return Bukkit.getBytebufManager().newBytebuf(size); ++ } ++ ++ static Bytebuf buf() { ++ return buf(128); ++ } ++ ++ static Bytebuf of(byte[] bytes) { ++ return Bukkit.getBytebufManager().toBytebuf(bytes); ++ } ++ ++ byte[] toArray(); ++ ++ Bytebuf skipBytes(int i); ++ ++ int readerIndex(); ++ ++ Bytebuf readerIndex(int i); ++ ++ int writerIndex(); ++ ++ Bytebuf writerIndex(int i); ++ ++ Bytebuf resetReaderIndex(); ++ ++ Bytebuf resetWriterIndex(); ++ ++ Bytebuf writeByte(int i); ++ ++ byte readByte(); ++ ++ Bytebuf writeBoolean(boolean b); ++ ++ boolean readBoolean(); ++ ++ Bytebuf writeFloat(float f); ++ ++ float readFloat(); ++ ++ Bytebuf writeDouble(double d); ++ ++ double readDouble(); ++ ++ Bytebuf writeShort(int i); ++ ++ short readShort(); ++ ++ Bytebuf writeInt(int i); ++ ++ int readInt(); ++ ++ Bytebuf writeLong(long i); ++ ++ long readLong(); ++ ++ Bytebuf writeVarInt(int i); ++ ++ int readVarInt(); ++ ++ Bytebuf writeVarLong(long i); ++ ++ long readVarLong(); ++ ++ Bytebuf writeUUID(UUID uuid); ++ ++ UUID readUUID(); ++ ++ Bytebuf writeEnum(Enum instance); ++ ++ > T readEnum(Class enumClass); ++ ++ Bytebuf writeUTFString(String utf); ++ ++ String readUTFString(); ++ ++ Bytebuf writeComponentPlain(String str); ++ ++ String readComponentPlain(); ++ ++ Bytebuf writeComponentJson(JsonElement json); ++ ++ JsonElement readComponentJson(); ++ ++ Bytebuf writeItemStack(ItemStack itemStack); ++ ++ ItemStack readItemStack(); ++ ++ Bytebuf copy(); ++ ++ boolean release(); ++} +diff --git a/src/main/java/org/leavesmc/leaves/bytebuf/BytebufManager.java b/src/main/java/org/leavesmc/leaves/bytebuf/BytebufManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8668e47dee7a23d7843efc4a9752919f7a1dce88 +--- /dev/null ++++ b/src/main/java/org/leavesmc/leaves/bytebuf/BytebufManager.java +@@ -0,0 +1,15 @@ ++package org.leavesmc.leaves.bytebuf; ++ ++import org.bukkit.plugin.Plugin; ++import org.leavesmc.leaves.bytebuf.packet.PacketListener; ++ ++public interface BytebufManager { ++ ++ void registerListener(Plugin plugin, PacketListener listener); ++ ++ void unregisterListener(Plugin plugin, PacketListener listener); ++ ++ Bytebuf newBytebuf(int size); ++ ++ Bytebuf toBytebuf(byte[] bytes); ++} +diff --git a/src/main/java/org/leavesmc/leaves/bytebuf/packet/Packet.java b/src/main/java/org/leavesmc/leaves/bytebuf/packet/Packet.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8bb00c16fe3e6089397cc0fcaaec4715960dd724 +--- /dev/null ++++ b/src/main/java/org/leavesmc/leaves/bytebuf/packet/Packet.java +@@ -0,0 +1,6 @@ ++package org.leavesmc.leaves.bytebuf.packet; ++ ++import org.leavesmc.leaves.bytebuf.Bytebuf; ++ ++public record Packet(PacketType type, Bytebuf bytebuf) { ++} +diff --git a/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketListener.java b/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketListener.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e246c0a8725fa3b2be065433652a19a565c7205c +--- /dev/null ++++ b/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketListener.java +@@ -0,0 +1,10 @@ ++package org.leavesmc.leaves.bytebuf.packet; ++ ++import org.bukkit.entity.Player; ++ ++public interface PacketListener { ++ ++ Packet onPacketIn(Player player, Packet packet); ++ ++ Packet onPacketOut(Player player, Packet packet); ++} +diff --git a/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketType.java b/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketType.java +new file mode 100644 +index 0000000000000000000000000000000000000000..4fd80d703653b8fb2f2bec329b1c5d04ae419d2d +--- /dev/null ++++ b/src/main/java/org/leavesmc/leaves/bytebuf/packet/PacketType.java +@@ -0,0 +1,180 @@ ++package org.leavesmc.leaves.bytebuf.packet; ++ ++public enum PacketType { ++ // ClientboundBundle, ++ // ClientboundBundleDelimiter, ++ ClientboundAddEntity, ++ ClientboundAddExperienceOrb, ++ ClientboundAnimate, ++ ClientboundAwardStats, ++ ClientboundBlockChangedAck, ++ ClientboundBlockDestruction, ++ ClientboundBlockEntityData, ++ ClientboundBlockEvent, ++ ClientboundBlockUpdate, ++ ClientboundBossEvent, ++ ClientboundChangeDifficulty, ++ ClientboundChunkBatchFinished, ++ ClientboundChunkBatchStart, ++ ClientboundChunksBiomes, ++ ClientboundClearTitles, ++ ClientboundCommandSuggestions, ++ ClientboundCommands, ++ ClientboundContainerClose, ++ ClientboundContainerSetContent, ++ ClientboundContainerSetData, ++ ClientboundContainerSetSlot, ++ ClientboundCooldown, ++ ClientboundCustomChatCompletions, ++ ClientboundDamageEvent, ++ ClientboundDebugSample, ++ ClientboundDeleteChat, ++ ClientboundDisguisedChat, ++ ClientboundEntityEvent, ++ ClientboundExplode, ++ ClientboundForgetLevelChunk, ++ ClientboundGameEvent, ++ ClientboundHorseScreenOpen, ++ ClientboundHurtAnimation, ++ ClientboundInitializeBorder, ++ ClientboundLevelChunkWithLight, ++ ClientboundLevelEvent, ++ ClientboundLevelParticles, ++ ClientboundLightUpdate, ++ ClientboundLogin, ++ ClientboundMapItemData, ++ ClientboundMerchantOffers, ++ ClientboundMoveEntityPos, ++ ClientboundMoveEntityPosRot, ++ ClientboundMoveEntityRot, ++ ClientboundMoveVehicle, ++ ClientboundOpenBook, ++ ClientboundOpenScreen, ++ ClientboundOpenSignEditor, ++ ClientboundPlaceGhostRecipe, ++ ClientboundPlayerAbilities, ++ ClientboundPlayerChat, ++ ClientboundPlayerCombatEnd, ++ ClientboundPlayerCombatEnter, ++ ClientboundPlayerCombatKill, ++ ClientboundPlayerInfoRemove, ++ ClientboundPlayerInfoUpdate, ++ ClientboundPlayerLookAt, ++ ClientboundPlayerPosition, ++ ClientboundRecipe, ++ ClientboundRemoveEntities, ++ ClientboundRemoveMobEffect, ++ ClientboundRespawn, ++ ClientboundRotateHead, ++ ClientboundSectionBlocksUpdate, ++ ClientboundSelectAdvancementsTab, ++ ClientboundServerData, ++ ClientboundSetActionBarText, ++ ClientboundSetBorderCenter, ++ ClientboundSetBorderLerpSize, ++ ClientboundSetBorderSize, ++ ClientboundSetBorderWarningDelay, ++ ClientboundSetBorderWarningDistance, ++ ClientboundSetCamera, ++ ClientboundSetCarriedItem, ++ ClientboundSetChunkCacheCenter, ++ ClientboundSetChunkCacheRadius, ++ ClientboundSetDefaultSpawnPosition, ++ ClientboundSetDisplayObjective, ++ ClientboundSetEntityData, ++ ClientboundSetEntityLink, ++ ClientboundSetEntityMotion, ++ ClientboundSetEquipment, ++ ClientboundSetExperience, ++ ClientboundSetHealth, ++ ClientboundSetObjective, ++ ClientboundSetPassengers, ++ ClientboundSetPlayerTeam, ++ ClientboundSetScore, ++ ClientboundSetSimulationDistance, ++ ClientboundSetSubtitleText, ++ ClientboundSetTime, ++ ClientboundSetTitleText, ++ ClientboundSetTitlesAnimation, ++ ClientboundSoundEntity, ++ ClientboundSound, ++ ClientboundStartConfiguration, ++ ClientboundStopSound, ++ ClientboundSystemChat, ++ ClientboundTabList, ++ ClientboundTagQuery, ++ ClientboundTakeItemEntity, ++ ClientboundTeleportEntity, ++ ClientboundUpdateAdvancements, ++ ClientboundUpdateAttributes, ++ ClientboundUpdateMobEffect, ++ ClientboundUpdateRecipes, ++ ClientboundProjectilePower, ++ ServerboundAcceptTeleportation, ++ ServerboundBlockEntityTagQuery, ++ ServerboundChangeDifficulty, ++ ServerboundChatAck, ++ ServerboundChatCommand, ++ ServerboundChatCommandSigned, ++ ServerboundChat, ++ ServerboundChatSessionUpdate, ++ ServerboundChunkBatchReceived, ++ ServerboundClientCommand, ++ ServerboundCommandSuggestion, ++ ServerboundConfigurationAcknowledged, ++ ServerboundContainerButtonClick, ++ ServerboundContainerClick, ++ ServerboundContainerClose, ++ ServerboundContainerSlotStateChanged, ++ ServerboundDebugSampleSubscription, ++ ServerboundEditBook, ++ ServerboundEntityTagQuery, ++ ServerboundInteract, ++ ServerboundJigsawGenerate, ++ ServerboundLockDifficulty, ++ ServerboundMovePlayerPos, ++ ServerboundMovePlayerPosRot, ++ ServerboundMovePlayerRot, ++ ServerboundMovePlayerStatusOnly, ++ ServerboundMoveVehicle, ++ ServerboundPaddleBoat, ++ ServerboundPickItem, ++ ServerboundPlaceRecipe, ++ ServerboundPlayerAbilities, ++ ServerboundPlayerAction, ++ ServerboundPlayerCommand, ++ ServerboundPlayerInput, ++ ServerboundRecipeBookChangeSettings, ++ ServerboundRecipeBookSeenRecipe, ++ ServerboundRenameItem, ++ ServerboundSeenAdvancements, ++ ServerboundSelectTrade, ++ ServerboundSetBeacon, ++ ServerboundSetCarriedItem, ++ ServerboundSetCommandBlock, ++ ServerboundSetCommandMinecart, ++ ServerboundSetCreativeModeSlot, ++ ServerboundSetJigsawBlock, ++ ServerboundSetStructureBlock, ++ ServerboundSignUpdate, ++ ServerboundSwing, ++ ServerboundTeleportToEntity, ++ ServerboundUseItemOn, ++ ServerboundUseItem, ++ ClientboundResetScore, ++ ClientboundTickingState, ++ ClientboundTickingStep, ++ ClientboundCustomPayload, ++ ClientboundDisconnect, ++ ClientboundKeepAlive, ++ ClientboundResourcePackPop, ++ ClientboundResourcePackPush, ++ ClientboundStoreCookie, ++ ClientboundTransfer, ++ ClientboundUpdateTags, ++ ServerboundClientInformation, ++ ServerboundCustomPayload, ++ ServerboundKeepAlive, ++ ServerboundPong, ++ ServerboundResourcePack ++} diff --git a/patches/api/0010-Placeholder-for-Bytebuf-API.patch b/patches/api/0010-Placeholder-for-Bytebuf-API.patch deleted file mode 100644 index 4a069c17..00000000 --- a/patches/api/0010-Placeholder-for-Bytebuf-API.patch +++ /dev/null @@ -1,15 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: MC_XiaoHei -Date: Sat, 11 May 2024 00:00:18 +0800 -Subject: [PATCH] Placeholder for Bytebuf-API - - -diff --git a/.gitignore b/.gitignore -index 97e78e27ee0eea2c8b24886eeb19164d552323fe..9764fa643039f215627c20a33ca70c9e36b2d599 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -38,3 +38,4 @@ - # vs code - /.vscode - /.factorypath -+ diff --git a/patches/server/0135-Bytebuf-API.patch b/patches/server/0135-Bytebuf-API.patch new file mode 100644 index 00000000..d7ac29fa --- /dev/null +++ b/patches/server/0135-Bytebuf-API.patch @@ -0,0 +1,593 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Lumine1909 <133463833+Lumine1909@users.noreply.github.com> +Date: Wed, 22 May 2024 10:12:22 +0800 +Subject: [PATCH] Bytebuf API + + +diff --git a/src/main/java/net/minecraft/network/chat/Component.java b/src/main/java/net/minecraft/network/chat/Component.java +index 6dcade427f19771b08e04cfa036dedcfac30b5cd..3306d9f5aefe5863cff79374c75cc309c1699c3f 100644 +--- a/src/main/java/net/minecraft/network/chat/Component.java ++++ b/src/main/java/net/minecraft/network/chat/Component.java +@@ -291,7 +291,7 @@ public interface Component extends Message, FormattedText, Iterable { + return (MutableComponent) ComponentSerialization.CODEC.parse(registries.createSerializationContext(JsonOps.INSTANCE), json).getOrThrow(JsonParseException::new); + } + +- static JsonElement serialize(Component text, HolderLookup.Provider registries) { ++ public static JsonElement serialize(Component text, HolderLookup.Provider registries) { // Leaves - package -> public + return (JsonElement) ComponentSerialization.CODEC.encodeStart(registries.createSerializationContext(JsonOps.INSTANCE), text).getOrThrow(JsonParseException::new); + } + +diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java +index 975062e67278614220eab0c301019a235c7953b7..810d92c033b556e8ae3a5e133a4e471e561eef2c 100644 +--- a/src/main/java/net/minecraft/server/players/PlayerList.java ++++ b/src/main/java/net/minecraft/server/players/PlayerList.java +@@ -470,6 +470,12 @@ public abstract class PlayerList { + return; + } + ++ // Leaves start - Bytebuf API ++ if (!(player instanceof ServerBot)) { ++ this.cserver.getBytebufHandler().injectPlayer(player); ++ } ++ // Leaves end - Bytebuf API ++ + org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); // Leaves - protocol + + // Leaves start - bot support +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 405a04f2711e26e22d7dd091745b5b5a01d724d9..68a0a3a792c998a9cc67ec4269e8821817394cfa 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -307,6 +307,7 @@ public final class CraftServer implements Server { + private final io.papermc.paper.potion.PaperPotionBrewer potionBrewer; // Paper - Custom Potion Mixes + private final org.leavesmc.leaves.entity.CraftBotManager botManager = new org.leavesmc.leaves.entity.CraftBotManager(); // Leaves + private final org.leavesmc.leaves.entity.CraftPhotographerManager photographerManager = new org.leavesmc.leaves.entity.CraftPhotographerManager(); // Leaves ++ private final org.leavesmc.leaves.bytebuf.internal.InternalBytebufHandler internalBytebufHandler = new org.leavesmc.leaves.bytebuf.internal.InternalBytebufHandler(); // Leaves + + // Paper start - Folia region threading API + private final io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler regionizedScheduler = new io.papermc.paper.threadedregions.scheduler.FallbackRegionScheduler(); +@@ -3291,4 +3292,15 @@ public final class CraftServer implements Server { + return photographerManager; + } + // Leaves end - replay mod api ++ ++ // Leaves start - Bytebuf API ++ @Override ++ public org.leavesmc.leaves.bytebuf.BytebufManager getBytebufManager() { ++ return internalBytebufHandler.getManager(); ++ } ++ ++ public org.leavesmc.leaves.bytebuf.internal.InternalBytebufHandler getBytebufHandler() { ++ return internalBytebufHandler; ++ } ++ // Leaves end - Bytebuf API + } +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 25a5ce110c0515f5a0ee5f287a7f3dd029a8f29f..fb65a871d7cff135f0c8bc262b0666a3556fbfb0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -3519,4 +3519,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + public void setSendViewDistance(final int viewDistance) { + this.getHandle().setSendViewDistance(viewDistance); + } ++ ++ // Leaves start - Bytebuf API ++ @Override ++ public void sendPacket(org.leavesmc.leaves.bytebuf.packet.Packet packet) { ++ this.server.getBytebufHandler().applyPacketToPlayer(this, packet); ++ } ++ ++ @Override ++ public void sendPacket(org.leavesmc.leaves.bytebuf.Bytebuf bytebuf, org.leavesmc.leaves.bytebuf.packet.PacketType type) { ++ this.server.getBytebufHandler().applyPacketToPlayer(this, new org.leavesmc.leaves.bytebuf.packet.Packet(type, bytebuf)); ++ } ++ // Leaves end - Bytebuf API + } +diff --git a/src/main/java/org/leavesmc/leaves/bytebuf/SimpleBytebufManager.java b/src/main/java/org/leavesmc/leaves/bytebuf/SimpleBytebufManager.java +new file mode 100644 +index 0000000000000000000000000000000000000000..443f7f6e0b8d40eaafb8009b3b7e405c6ec78d02 +--- /dev/null ++++ b/src/main/java/org/leavesmc/leaves/bytebuf/SimpleBytebufManager.java +@@ -0,0 +1,35 @@ ++package org.leavesmc.leaves.bytebuf; ++ ++import io.netty.buffer.Unpooled; ++import org.bukkit.plugin.Plugin; ++import org.leavesmc.leaves.bytebuf.internal.InternalBytebufHandler; ++import org.leavesmc.leaves.bytebuf.packet.PacketListener; ++ ++public class SimpleBytebufManager implements BytebufManager { ++ ++ private final InternalBytebufHandler internal; ++ ++ public SimpleBytebufManager(InternalBytebufHandler internal) { ++ this.internal = internal; ++ } ++ ++ @Override ++ public void registerListener(Plugin plugin, PacketListener listener) { ++ internal.listenerMap.put(listener, plugin); ++ } ++ ++ @Override ++ public void unregisterListener(Plugin plugin, PacketListener listener) { ++ internal.listenerMap.remove(listener); ++ } ++ ++ @Override ++ public Bytebuf newBytebuf(int size) { ++ return new WrappedBytebuf(Unpooled.buffer(size)); ++ } ++ ++ @Override ++ public Bytebuf toBytebuf(byte[] bytes) { ++ return new WrappedBytebuf(Unpooled.wrappedBuffer(bytes)); ++ } ++} +diff --git a/src/main/java/org/leavesmc/leaves/bytebuf/WrappedBytebuf.java b/src/main/java/org/leavesmc/leaves/bytebuf/WrappedBytebuf.java +new file mode 100644 +index 0000000000000000000000000000000000000000..d9277d14b8df71600196ab434b0d4c7f549eb84b +--- /dev/null ++++ b/src/main/java/org/leavesmc/leaves/bytebuf/WrappedBytebuf.java +@@ -0,0 +1,255 @@ ++package org.leavesmc.leaves.bytebuf; ++ ++import com.google.gson.JsonElement; ++import io.netty.buffer.ByteBuf; ++import net.minecraft.core.RegistryAccess; ++import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.network.RegistryFriendlyByteBuf; ++import net.minecraft.network.chat.Component; ++import net.minecraft.network.chat.ComponentSerialization; ++import net.minecraft.server.MinecraftServer; ++import org.bukkit.inventory.ItemStack; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++ ++import java.util.UUID; ++ ++public class WrappedBytebuf implements Bytebuf { ++ ++ private final FriendlyByteBuf buf; ++ private final RegistryFriendlyByteBuf registryBuf; ++ ++ public WrappedBytebuf(ByteBuf buf) { ++ this.buf = new FriendlyByteBuf(buf); ++ this.registryBuf = new RegistryFriendlyByteBuf(this.buf, MinecraftServer.getServer().registryAccess()); ++ } ++ ++ public RegistryFriendlyByteBuf getRegistryBuf() { ++ return registryBuf; ++ } ++ ++ @Override ++ public byte[] toArray() { ++ return buf.array(); ++ } ++ ++ @Override ++ public Bytebuf skipBytes(int i) { ++ buf.skipBytes(i); ++ return this; ++ } ++ ++ @Override ++ public int readerIndex() { ++ return buf.readerIndex(); ++ } ++ ++ @Override ++ public Bytebuf readerIndex(int i) { ++ buf.readerIndex(i); ++ return this; ++ } ++ ++ @Override ++ public int writerIndex() { ++ return buf.writerIndex(); ++ } ++ ++ @Override ++ public Bytebuf writerIndex(int i) { ++ buf.writerIndex(i); ++ return this; ++ } ++ ++ @Override ++ public Bytebuf resetReaderIndex() { ++ buf.resetReaderIndex(); ++ return this; ++ } ++ ++ @Override ++ public Bytebuf resetWriterIndex() { ++ buf.resetWriterIndex(); ++ return this; ++ } ++ ++ @Override ++ public Bytebuf writeByte(int i) { ++ buf.writeByte(i); ++ return this; ++ } ++ ++ @Override ++ public byte readByte() { ++ return buf.readByte(); ++ } ++ ++ @Override ++ public Bytebuf writeBoolean(boolean b) { ++ buf.writeBoolean(b); ++ return this; ++ } ++ ++ @Override ++ public boolean readBoolean() { ++ return buf.readBoolean(); ++ } ++ ++ @Override ++ public Bytebuf writeFloat(float f) { ++ buf.writeFloat(f); ++ return this; ++ } ++ ++ @Override ++ public float readFloat() { ++ return buf.readFloat(); ++ } ++ ++ @Override ++ public Bytebuf writeDouble(double d) { ++ buf.writeDouble(d); ++ return this; ++ } ++ ++ @Override ++ public double readDouble() { ++ return buf.readDouble(); ++ } ++ ++ @Override ++ public Bytebuf writeShort(int i) { ++ buf.writeShort(i); ++ return this; ++ } ++ ++ @Override ++ public short readShort() { ++ return buf.readShort(); ++ } ++ ++ @Override ++ public Bytebuf writeInt(int i) { ++ buf.writeShort(i); ++ return this; ++ } ++ ++ @Override ++ public int readInt() { ++ return buf.readInt(); ++ } ++ ++ @Override ++ public Bytebuf writeLong(long i) { ++ buf.writeLong(i); ++ return this; ++ } ++ ++ @Override ++ public long readLong() { ++ return buf.readLong(); ++ } ++ ++ @Override ++ public Bytebuf writeVarInt(int i) { ++ this.buf.writeVarInt(i); ++ return this; ++ } ++ ++ @Override ++ public int readVarInt() { ++ return this.buf.readVarInt(); ++ } ++ ++ @Override ++ public Bytebuf writeVarLong(long i) { ++ this.buf.writeVarLong(i); ++ return this; ++ } ++ ++ @Override ++ public long readVarLong() { ++ return this.buf.readVarLong(); ++ } ++ ++ @Override ++ public Bytebuf writeUUID(UUID uuid) { ++ this.buf.writeUUID(uuid); ++ return this; ++ } ++ ++ @Override ++ public UUID readUUID() { ++ return this.buf.readUUID(); ++ } ++ ++ @Override ++ public Bytebuf writeEnum(Enum instance) { ++ this.buf.writeEnum(instance); ++ return this; ++ } ++ ++ @Override ++ public > T readEnum(Class enumClass) { ++ return this.buf.readEnum(enumClass); ++ } ++ ++ @Override ++ public Bytebuf writeUTFString(String utf) { ++ buf.writeUtf(utf); ++ return this; ++ } ++ ++ @Override ++ public String readUTFString() { ++ return buf.readUtf(); ++ } ++ ++ @Override ++ public Bytebuf writeComponentPlain(String str) { ++ ComponentSerialization.STREAM_CODEC.encode(new RegistryFriendlyByteBuf(this.buf, RegistryAccess.EMPTY), Component.literal(str)); ++ return this; ++ } ++ ++ @Override ++ public String readComponentPlain() { ++ return ComponentSerialization.STREAM_CODEC.decode(new RegistryFriendlyByteBuf(buf, RegistryAccess.EMPTY)).getString(); ++ } ++ ++ @Override ++ public Bytebuf writeComponentJson(JsonElement json) { ++ Component component = Component.Serializer.fromJson(json, RegistryAccess.EMPTY); ++ if (component == null) { ++ throw new IllegalArgumentException("Null can not be serialize to Minecraft chat component"); ++ } ++ ComponentSerialization.STREAM_CODEC.encode(new RegistryFriendlyByteBuf(buf, RegistryAccess.EMPTY), component); ++ return this; ++ } ++ ++ @Override ++ public JsonElement readComponentJson() { ++ return Component.Serializer.serialize(ComponentSerialization.STREAM_CODEC.decode(new RegistryFriendlyByteBuf(buf, RegistryAccess.EMPTY)), RegistryAccess.EMPTY); ++ } ++ ++ @Override ++ public Bytebuf writeItemStack(ItemStack itemStack) { ++ net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.unwrap(itemStack); ++ net.minecraft.world.item.ItemStack.OPTIONAL_STREAM_CODEC.encode(this.registryBuf, nmsItem); ++ return this; ++ } ++ ++ @Override ++ public ItemStack readItemStack() { ++ net.minecraft.world.item.ItemStack nmsItem = net.minecraft.world.item.ItemStack.OPTIONAL_STREAM_CODEC.decode(this.registryBuf); ++ return nmsItem.asBukkitMirror(); ++ } ++ ++ @Override ++ public Bytebuf copy() { ++ return new WrappedBytebuf(this.buf.copy()); ++ } ++ ++ @Override ++ public boolean release() { ++ return this.buf.release(); ++ } ++} +diff --git a/src/main/java/org/leavesmc/leaves/bytebuf/internal/InternalBytebufHandler.java b/src/main/java/org/leavesmc/leaves/bytebuf/internal/InternalBytebufHandler.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0e8fd87ca5159dd0367f8cc59dd4a3ef13eb37b8 +--- /dev/null ++++ b/src/main/java/org/leavesmc/leaves/bytebuf/internal/InternalBytebufHandler.java +@@ -0,0 +1,200 @@ ++package org.leavesmc.leaves.bytebuf.internal; ++ ++import com.google.common.cache.Cache; ++import com.google.common.cache.CacheBuilder; ++import com.google.common.collect.ImmutableMap; ++import io.netty.buffer.Unpooled; ++import io.netty.channel.ChannelDuplexHandler; ++import io.netty.channel.ChannelHandlerContext; ++import io.netty.channel.ChannelPromise; ++import net.minecraft.network.Connection; ++import net.minecraft.network.FriendlyByteBuf; ++import net.minecraft.network.RegistryFriendlyByteBuf; ++import net.minecraft.network.codec.StreamCodec; ++import net.minecraft.network.protocol.BundleDelimiterPacket; ++import net.minecraft.network.protocol.BundlePacket; ++import net.minecraft.network.protocol.game.*; ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerPlayer; ++import org.bukkit.craftbukkit.entity.CraftPlayer; ++import org.bukkit.entity.Player; ++import org.bukkit.plugin.Plugin; ++import org.leavesmc.leaves.bytebuf.Bytebuf; ++import org.leavesmc.leaves.bytebuf.BytebufManager; ++import org.leavesmc.leaves.bytebuf.SimpleBytebufManager; ++import org.leavesmc.leaves.bytebuf.WrappedBytebuf; ++import org.leavesmc.leaves.bytebuf.packet.Packet; ++import org.leavesmc.leaves.bytebuf.packet.PacketListener; ++import org.leavesmc.leaves.bytebuf.packet.PacketType; ++ ++import java.lang.reflect.Field; ++import java.util.HashMap; ++import java.util.Map; ++import java.util.concurrent.ExecutionException; ++ ++import static org.leavesmc.leaves.bytebuf.packet.PacketType.*; ++ ++public class InternalBytebufHandler { ++ ++ private class PacketHandler extends ChannelDuplexHandler { ++ ++ private final static String handlerName = "leaves-bytebuf-handler"; ++ private final Player player; ++ ++ public PacketHandler(Player player) { ++ this.player = player; ++ } ++ ++ @Override ++ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ++ if (msg instanceof BundlePacket || msg instanceof BundleDelimiterPacket) { ++ super.channelRead(ctx, msg); ++ return; ++ } ++ try { ++ msg = callPacketInEvent(player, createBytebufPacket((net.minecraft.network.protocol.Packet) msg)); ++ } catch (Exception e) { ++ MinecraftServer.LOGGER.error("Error on PacketInEvent.", e); ++ } ++ if (msg != null) { ++ super.channelRead(ctx, msg); ++ } ++ ++ } ++ ++ @Override ++ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { ++ if (msg instanceof BundlePacket || msg instanceof BundleDelimiterPacket) { ++ super.write(ctx, msg, promise); ++ return; ++ } ++ try { ++ msg = callPacketOutEvent(player, createBytebufPacket((net.minecraft.network.protocol.Packet) msg)); ++ } catch (Exception e) { ++ MinecraftServer.LOGGER.error("Error on PacketOutEvent.", e); ++ } ++ if (msg != null) { ++ super.write(ctx, msg, promise); ++ } ++ } ++ } ++ ++ public final Map listenerMap = new HashMap<>(); ++ private final BytebufManager manager = new SimpleBytebufManager(this); ++ private final ImmutableMap type2CodecMap; ++ private final Cache, PacketType> resultCache = CacheBuilder.newBuilder().build(); ++ ++ public InternalBytebufHandler() { ++ ImmutableMap.Builder builder = ImmutableMap.builder(); ++ for (PacketType packet : PacketType.values()) { ++ Class packetClass; ++ try { ++ packetClass = Class.forName("net.minecraft.network.protocol.game." + packet.name() + "Packet"); ++ } catch (ClassNotFoundException e) { ++ try { ++ packetClass = Class.forName("net.minecraft.network.protocol.common." + packet.name() + "Packet"); ++ } catch (ClassNotFoundException e2) { ++ continue; ++ } ++ } ++ try { ++ Field field = packetClass.getDeclaredField("STREAM_CODEC"); ++ builder.put(packet, (StreamCodec>) field.get(null)); ++ } catch (Exception ignored) { ++ } ++ } ++ ++ builder.put(ClientboundMoveEntityPos, ClientboundMoveEntityPacket.Pos.STREAM_CODEC); ++ builder.put(ClientboundMoveEntityPosRot, ClientboundMoveEntityPacket.PosRot.STREAM_CODEC); ++ builder.put(ClientboundMoveEntityRot, ClientboundMoveEntityPacket.Rot.STREAM_CODEC); ++ builder.put(ServerboundMovePlayerPos, ServerboundMovePlayerPacket.Pos.STREAM_CODEC); ++ builder.put(ServerboundMovePlayerPosRot, ServerboundMovePlayerPacket.PosRot.STREAM_CODEC); ++ builder.put(ServerboundMovePlayerRot, ServerboundMovePlayerPacket.Rot.STREAM_CODEC); ++ builder.put(ServerboundMovePlayerStatusOnly, ServerboundMovePlayerPacket.StatusOnly.STREAM_CODEC); ++ ++ type2CodecMap = builder.build(); ++ } ++ ++ public void injectPlayer(ServerPlayer player) { ++ player.connection.connection.channel.pipeline().addBefore("packet_handler", PacketHandler.handlerName, new PacketHandler(player.getBukkitEntity())); ++ } ++ ++ public BytebufManager getManager() { ++ return manager; ++ } ++ ++ public net.minecraft.network.protocol.Packet callPacketInEvent(Player player, Packet packet) { ++ for (PacketListener listener : listenerMap.keySet()) { ++ if (listenerMap.get(listener).isEnabled()) { ++ packet = listener.onPacketIn(player, packet); ++ packet.bytebuf().resetReaderIndex(); ++ } else { ++ listenerMap.remove(listener); ++ } ++ } ++ return createNMSPacket(packet); ++ } ++ ++ public net.minecraft.network.protocol.Packet callPacketOutEvent(Player player, Packet packet) { ++ for (PacketListener listener : listenerMap.keySet()) { ++ if (listenerMap.get(listener).isEnabled()) { ++ packet = listener.onPacketOut(player, packet); ++ packet.bytebuf().resetReaderIndex(); ++ } else { ++ listenerMap.remove(listener); ++ } ++ } ++ return createNMSPacket(packet); ++ } ++ ++ public void applyPacketToPlayer(Player player, Packet packet) { ++ Connection sp = ((CraftPlayer) player).getHandle().connection.connection; ++ sp.send(createNMSPacket(packet)); ++ } ++ ++ public net.minecraft.network.protocol.Packet createNMSPacket(Packet packet) { ++ StreamCodec> codec = type2CodecMap.get(packet.type()); ++ if (codec == null) { ++ throw new UnsupportedOperationException("This feature is not completely finished yet, packet type " + packet.type() + " is not supported temporary."); ++ } ++ return codec.decode(((WrappedBytebuf) packet.bytebuf()).getRegistryBuf()); ++ } ++ ++ private PacketType toEnumType(net.minecraft.network.protocol.PacketType type) { ++ try { ++ return this.resultCache.get(type, () -> { ++ StringBuilder builder = new StringBuilder(); ++ String bound = type.toString().split("/")[0]; ++ String name = type.toString().split(":")[1]; ++ builder.append(bound.substring(0, 1).toUpperCase()).append(bound.substring(1)); ++ boolean flag = true; ++ for (int i = 0; i < name.length(); i++) { ++ if (flag) { ++ builder.append(name.substring(i, i + 1).toUpperCase()); ++ flag = false; ++ continue; ++ } ++ if (name.charAt(i) == '_') { ++ flag = true; ++ } else { ++ builder.append(name.charAt(i)); ++ } ++ } ++ return PacketType.valueOf(builder.toString()); ++ }); ++ } catch (ExecutionException e) { ++ throw new RuntimeException(e); ++ } ++ } ++ ++ public Packet createBytebufPacket(net.minecraft.network.protocol.Packet nmsPacket) { ++ PacketType type = toEnumType(nmsPacket.type()); ++ RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.buffer(8192), MinecraftServer.getServer().registryAccess()); ++ StreamCodec> codec = type2CodecMap.get(type); ++ if (codec == null) { ++ throw new UnsupportedOperationException("This feature is not completely finished yet, packet type " + type + " is not supported temporary."); ++ } ++ codec.encode(buf, nmsPacket); ++ return new Packet(type, Bytebuf.of(buf.array())); ++ } ++} diff --git a/patches/unapplied/api/0011-Bytebuf-API.patch b/patches/unapplied/api/0011-Bytebuf-API.patch deleted file mode 100644 index 63e8bf4a..00000000 --- a/patches/unapplied/api/0011-Bytebuf-API.patch +++ /dev/null @@ -1,224 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lumine1909 <3556577839@qq.com> -Date: Fri, 12 Apr 2024 20:12:33 -0400 -Subject: [PATCH] Bytebuf API - - -diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java -index b068de949e21525d79223e607fafd43b030a8294..1853a5c230de0e3bc66e0617efe01e6dd15ef553 100644 ---- a/src/main/java/org/bukkit/Bukkit.java -+++ b/src/main/java/org/bukkit/Bukkit.java -@@ -2923,6 +2923,14 @@ public final class Bukkit { - return server.getPhotographerManager(); - } - // Leaves end - Photographer API -+ // Leaves start - Bytebuf API -+ public static @NotNull org.leavesmc.leaves.packet.bytebuf.Bytebuf newByteBuf() { -+ return server.newByteBuf(); -+ } -+ public static @NotNull org.leavesmc.leaves.packet.bytebuf.Bytebuf newByteBuf(int initalCapability) { -+ return server.newByteBuf(initalCapability); -+ } -+ // Leaves end - Bytebuf API - - @NotNull - public static Server.Spigot spigot() { -diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 23ac9b72d2a59b23223ad9335ebed63c40ac117f..56b7e84f075af5d10cb23635f52fc0fedb1f7c6f 100644 ---- a/src/main/java/org/bukkit/Server.java -+++ b/src/main/java/org/bukkit/Server.java -@@ -2564,4 +2564,9 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi - // Leaves start - Photographer API - @NotNull PhotographerManager getPhotographerManager(); - // Leaves end - Photographer API -+ // Leaves start - Bytebuf API -+ @NotNull org.leavesmc.leaves.packet.bytebuf.Bytebuf newByteBuf(); -+ @NotNull org.leavesmc.leaves.packet.bytebuf.Bytebuf newByteBuf(int initalCapability); -+ -+ // Leaves end - Bytebuf API - } -diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 6c327a07bf8a6aa11a2d7dad12b2830acc539484..cfd3acc5e4adcd30fd70ca2c5601bcca1357c821 100644 ---- a/src/main/java/org/bukkit/entity/Player.java -+++ b/src/main/java/org/bukkit/entity/Player.java -@@ -3760,6 +3760,10 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM - */ - void resetIdleDuration(); - // Paper end -+ // Leaves start - Bytebuf API -+ void sendPacket(org.leavesmc.leaves.packet.Packet packet); -+ void sendPacket(org.leavesmc.leaves.packet.bytebuf.Bytebuf buf, org.leavesmc.leaves.packet.PacketType packetType); -+ // Leaves end - Bytebuf API - - // Paper start - Add chunk view API - /** -diff --git a/src/main/java/org/leavesmc/leaves/packet/Packet.java b/src/main/java/org/leavesmc/leaves/packet/Packet.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0ea5069b994eb3da2952f696c1fd1bc0e81e281a ---- /dev/null -+++ b/src/main/java/org/leavesmc/leaves/packet/Packet.java -@@ -0,0 +1,8 @@ -+package org.leavesmc.leaves.packet; -+ -+import org.leavesmc.leaves.packet.bytebuf.Bytebuf; -+ -+public interface Packet { -+ PacketType getType(); -+ Bytebuf getBytebuf(); -+} -diff --git a/src/main/java/org/leavesmc/leaves/packet/PacketType.java b/src/main/java/org/leavesmc/leaves/packet/PacketType.java -new file mode 100644 -index 0000000000000000000000000000000000000000..3cf5792ddb7aa52580c4d91c2ddef593a43212af ---- /dev/null -+++ b/src/main/java/org/leavesmc/leaves/packet/PacketType.java -@@ -0,0 +1,115 @@ -+package org.leavesmc.leaves.packet; -+ -+/*** -+ * TODO: API comment -+ */ -+public enum PacketType { -+ ClientboundAddEntity, -+ ClientboundAddExperienceOrb, -+ ClientboundAnimate, -+ ClientboundAwardStats, -+ ClientboundBlockChangedAck, -+ ClientboundBlockDestruction, -+ ClientboundBlockEntityData, -+ ClientboundBlockEvent, -+ ClientboundBlockUpdate, -+ ClientboundBossEvent, -+ // ClientboundBundle, Not a regular packet, see https://wiki.vg/Protocol#Bundle_Delimiter -+ ClientboundChangeDifficulty, -+ ClientboundChunkBatchFinished, -+ ClientboundChunkBatchStart, -+ ClientboundChunksBiomes, -+ ClientboundClearTitles, -+ ClientboundCommands, -+ ClientboundCommandSuggestions, -+ ClientboundContainerClose, -+ ClientboundContainerSetContent, -+ ClientboundContainerSetData, -+ ClientboundContainerSetSlot, -+ ClientboundCooldown, -+ ClientboundCustomChatCompletions, -+ ClientboundDamageEvent, -+ ClientboundDeleteChat, -+ ClientboundDisguisedChat, -+ ClientboundEntityEvent, -+ ClientboundExplode, -+ ClientboundForgetLevelChunk, -+ ClientboundGameEvent, -+ ClientboundHorseScreenOpen, -+ ClientboundHurtAnimation, -+ ClientboundInitializeBorder, -+ ClientboundLevelChunkWithLight, -+ ClientboundLevelEvent, -+ ClientboundLevelParticles, -+ ClientboundLightUpdate, -+ ClientboundLightUpdatePack, -+ ClientboundLogin, -+ ClientboundMapItemData, -+ ClientboundMerchantOffers, -+ // ClientboundMoveEntity, Abstract class -+ ClientboundMoveVehicle, -+ ClientboundOpenBook, -+ ClientboundOpenScreen, -+ ClientboundOpenSignEditor, -+ ClientboundPlaceGhostRecipe, -+ ClientboundPlayerAbilities, -+ ClientboundPlayerChat, -+ ClientboundPlayerCombatEnd, -+ ClientboundPlayerCombatEnter, -+ ClientboundPlayerCombatKill, -+ ClientboundPlayerInfoRemove, -+ ClientboundPlayerInfoUpdate, -+ ClientboundPlayerLookAt, -+ ClientboundPlayerPosition, -+ ClientboundRecipe, -+ ClientboundRemoveEntities, -+ ClientboundRemoveMobEffect, -+ ClientboundResetScore, -+ ClientboundRespawn, -+ ClientboundRotateHead, -+ ClientboundSectionBlocksUpdate, -+ ClientboundSelectAdvancementsTab, -+ ClientboundServerData, -+ ClientboundSetActionBarText, -+ ClientboundSetBorderCenter, -+ ClientboundSetBorderLerpSize, -+ ClientboundSetBorderSize, -+ ClientboundSetBorderWarningDelay, -+ ClientboundSetBorderWarningDistance, -+ ClientboundSetCamera, -+ ClientboundSetCarriedItem, -+ ClientboundSetChunkCacheCenter, -+ ClientboundSetChunkCacheRadius, -+ ClientboundSetDefaultSpawnPosition, -+ ClientboundSetDisplayObjective, -+ ClientboundSetEntityData, -+ ClientboundSetEntityLink, -+ ClientboundSetEntityMotion, -+ ClientboundSetEquipment, -+ ClientboundSetExperience, -+ ClientboundSetHealth, -+ ClientboundSetObjective, -+ ClientboundSetPassengers, -+ ClientboundSetPlayerTeam, -+ ClientboundSetScore, -+ ClientboundSetSimulationDistance, -+ ClientboundSetSubtitleText, -+ ClientboundSetTime, -+ ClientboundSetTitlesAnimation, -+ ClientboundSetTitleText, -+ ClientboundSoundEntity, -+ ClientboundSound, -+ ClientboundStartConfiguration, -+ ClientboundStopSound, -+ ClientboundSystemChat, -+ ClientboundTabList, -+ ClientboundTagQuery, -+ ClientboundTakeItemEntity, -+ ClientboundTeleportEntity, -+ ClientboundTickingState, -+ ClientboundTickingStep, -+ ClientboundUpdateAdvancements, -+ ClientboundUpdateAttributes, -+ ClientboundUpdateMobEffect, -+ ClientboundUpdateRecipes -+} -diff --git a/src/main/java/org/leavesmc/leaves/packet/bytebuf/Bytebuf.java b/src/main/java/org/leavesmc/leaves/packet/bytebuf/Bytebuf.java -new file mode 100644 -index 0000000000000000000000000000000000000000..78a49c0d86742bc98f6b1434cba00a735982fd7a ---- /dev/null -+++ b/src/main/java/org/leavesmc/leaves/packet/bytebuf/Bytebuf.java -@@ -0,0 +1,29 @@ -+package org.leavesmc.leaves.packet.bytebuf; -+ -+import org.bukkit.inventory.ItemStack; -+import org.leavesmc.leaves.packet.Packet; -+import org.leavesmc.leaves.packet.PacketType; -+ -+import java.util.UUID; -+ -+public interface Bytebuf { -+ Packet toPacket(PacketType type); -+ Bytebuf writeByte(int i); -+ Bytebuf writeBoolean(boolean flag); -+ Bytebuf writeFloat(float f); -+ Bytebuf writeInt(int i); -+ Bytebuf writeShort(int i); -+ Bytebuf writeLong(long i); -+ Bytebuf writeVarInt(int value); -+ Bytebuf writeUUID(UUID uuid); -+ Bytebuf writeVarLong(long value); -+ -+ /* -+ In order to bypass NMS in the API, use deserialization of Object here. -+ In the future, it may be adjusted to use API encapsulated content (workload++). -+ */ -+ Bytebuf writeStringNbt(String nbt); -+ Bytebuf writeStringComponent(String component); -+ Bytebuf writeItem(ItemStack itemStack); -+ -+} diff --git a/patches/unapplied/server/0137-Bytebuf-API.patch b/patches/unapplied/server/0137-Bytebuf-API.patch deleted file mode 100644 index da338c75..00000000 --- a/patches/unapplied/server/0137-Bytebuf-API.patch +++ /dev/null @@ -1,314 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Lumine1909 <3556577839@qq.com> -Date: Fri, 12 Apr 2024 20:13:20 -0400 -Subject: [PATCH] Bytebuf API - - -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 70b4f5dc96e285184bd3e676397c6bddd193db37..5e2b61e191f29c59d614c0f3f5bcc17bbd9d1700 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -3288,4 +3288,15 @@ public final class CraftServer implements Server { - return photographerManager; - } - // Leaves end - replay mod api -+ // Leaves start - Bytebuf API -+ @Override -+ public @Nonnull org.leavesmc.leaves.packet.bytebuf.Bytebuf newByteBuf() { -+ return new org.leavesmc.leaves.packet.bytebuf.WrappedBytebuf(); -+ } -+ -+ @Override -+ public @Nonnull org.leavesmc.leaves.packet.bytebuf.Bytebuf newByteBuf(int initalCapability) { -+ return new org.leavesmc.leaves.packet.bytebuf.WrappedBytebuf(initalCapability); -+ } -+ // Leaves end - Bytebuf API - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index be198fa712ced7b61de16bdbc1f13acd2306cb22..d53e88a4261ddddc744c3c48b61564749f3ac28f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -3390,6 +3390,17 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - public void resetIdleDuration() { - this.getHandle().resetLastActionTime(); - } -+ // Leaves start - Bytebuf API -+ @Override -+ public void sendPacket(org.leavesmc.leaves.packet.Packet packet) { -+ this.getHandle().connection.send(((org.leavesmc.leaves.packet.WrappedPacket) packet).getNmsPacket()); -+ } -+ @Override -+ public void sendPacket(org.leavesmc.leaves.packet.bytebuf.Bytebuf buf, org.leavesmc.leaves.packet.PacketType packetType) { -+ org.leavesmc.leaves.packet.Packet packet = buf.toPacket(packetType); -+ this.getHandle().connection.send(((org.leavesmc.leaves.packet.WrappedPacket) packet).getNmsPacket()); -+ } -+ // Leaves end - Bytebuf API - // Paper end - - // Paper start - Add chunk view API -diff --git a/src/main/java/org/leavesmc/leaves/packet/WrappedPacket.java b/src/main/java/org/leavesmc/leaves/packet/WrappedPacket.java -new file mode 100644 -index 0000000000000000000000000000000000000000..dc0dde18d3ae300657d92e20ae3e17136b8b72f4 ---- /dev/null -+++ b/src/main/java/org/leavesmc/leaves/packet/WrappedPacket.java -@@ -0,0 +1,140 @@ -+package org.leavesmc.leaves.packet; -+ -+import net.minecraft.network.protocol.game.*; -+import org.leavesmc.leaves.packet.bytebuf.Bytebuf; -+import org.leavesmc.leaves.packet.bytebuf.WrappedBytebuf; -+ -+public class WrappedPacket implements Packet { -+ private final PacketType type; -+ private final Bytebuf wrappedBytebuf; -+ net.minecraft.network.protocol.Packet nmsPacket; -+ public WrappedPacket(PacketType type, WrappedBytebuf buf) { -+ this.type = type; -+ this.wrappedBytebuf = buf; -+ try { -+ switch (type) { -+ case ClientboundAddEntity -> nmsPacket = new ClientboundAddEntityPacket(buf.getFriendlyByteBuf()); -+ case ClientboundAddExperienceOrb -> nmsPacket = new ClientboundAddExperienceOrbPacket(buf.getFriendlyByteBuf()); -+ case ClientboundAnimate -> nmsPacket = new ClientboundAnimatePacket(buf.getFriendlyByteBuf()); -+ case ClientboundAwardStats -> nmsPacket = new ClientboundAwardStatsPacket(buf.getFriendlyByteBuf()); -+ case ClientboundBlockChangedAck -> nmsPacket = new ClientboundBlockChangedAckPacket(buf.getFriendlyByteBuf()); -+ case ClientboundBlockDestruction -> nmsPacket = new ClientboundBlockDestructionPacket(buf.getFriendlyByteBuf()); -+ case ClientboundBlockEntityData -> nmsPacket = new ClientboundBlockEntityDataPacket(buf.getFriendlyByteBuf()); -+ case ClientboundBlockEvent -> nmsPacket = new ClientboundBlockEventPacket(buf.getFriendlyByteBuf()); -+ case ClientboundBlockUpdate -> nmsPacket = new ClientboundBlockUpdatePacket(buf.getFriendlyByteBuf()); -+ case ClientboundBossEvent -> nmsPacket = new ClientboundBossEventPacket(buf.getFriendlyByteBuf()); -+ case ClientboundChangeDifficulty -> nmsPacket = new ClientboundChangeDifficultyPacket(buf.getFriendlyByteBuf()); -+ case ClientboundChunkBatchFinished -> nmsPacket = new ClientboundChunkBatchFinishedPacket(buf.getFriendlyByteBuf()); -+ case ClientboundChunkBatchStart -> nmsPacket = new ClientboundChunkBatchStartPacket(buf.getFriendlyByteBuf()); -+ case ClientboundChunksBiomes -> nmsPacket = new ClientboundChunksBiomesPacket(buf.getFriendlyByteBuf()); -+ case ClientboundClearTitles -> nmsPacket = new ClientboundClearTitlesPacket(buf.getFriendlyByteBuf()); -+ case ClientboundCommands -> nmsPacket = new ClientboundCommandsPacket(buf.getFriendlyByteBuf()); -+ case ClientboundCommandSuggestions -> nmsPacket = new ClientboundCommandSuggestionsPacket(buf.getFriendlyByteBuf()); -+ case ClientboundContainerClose -> nmsPacket = new ClientboundContainerClosePacket(buf.getFriendlyByteBuf()); -+ case ClientboundContainerSetContent -> nmsPacket = new ClientboundContainerSetContentPacket(buf.getFriendlyByteBuf()); -+ case ClientboundContainerSetData -> nmsPacket = new ClientboundContainerSetDataPacket(buf.getFriendlyByteBuf()); -+ case ClientboundContainerSetSlot -> nmsPacket = new ClientboundContainerSetSlotPacket(buf.getFriendlyByteBuf()); -+ case ClientboundCooldown -> nmsPacket = new ClientboundCooldownPacket(buf.getFriendlyByteBuf()); -+ case ClientboundCustomChatCompletions -> nmsPacket = new ClientboundCustomChatCompletionsPacket(buf.getFriendlyByteBuf()); -+ case ClientboundDamageEvent -> nmsPacket = new ClientboundDamageEventPacket(buf.getFriendlyByteBuf()); -+ case ClientboundDeleteChat -> nmsPacket = new ClientboundDeleteChatPacket(buf.getFriendlyByteBuf()); -+ case ClientboundDisguisedChat -> nmsPacket = new ClientboundDisguisedChatPacket(buf.getFriendlyByteBuf()); -+ case ClientboundEntityEvent -> nmsPacket = new ClientboundEntityEventPacket(buf.getFriendlyByteBuf()); -+ case ClientboundExplode -> nmsPacket = new ClientboundExplodePacket(buf.getFriendlyByteBuf()); -+ case ClientboundForgetLevelChunk -> nmsPacket = new ClientboundForgetLevelChunkPacket(buf.getFriendlyByteBuf()); -+ case ClientboundGameEvent -> nmsPacket = new ClientboundGameEventPacket(buf.getFriendlyByteBuf()); -+ case ClientboundHorseScreenOpen -> nmsPacket = new ClientboundHorseScreenOpenPacket(buf.getFriendlyByteBuf()); -+ case ClientboundHurtAnimation -> nmsPacket = new ClientboundHurtAnimationPacket(buf.getFriendlyByteBuf()); -+ case ClientboundInitializeBorder -> nmsPacket = new ClientboundInitializeBorderPacket(buf.getFriendlyByteBuf()); -+ case ClientboundLevelChunkWithLight -> nmsPacket = new ClientboundLevelChunkWithLightPacket(buf.getFriendlyByteBuf()); -+ case ClientboundLevelEvent -> nmsPacket = new ClientboundLevelEventPacket(buf.getFriendlyByteBuf()); -+ case ClientboundLevelParticles -> nmsPacket = new ClientboundLevelParticlesPacket(buf.getFriendlyByteBuf()); -+ case ClientboundLightUpdate -> nmsPacket = new ClientboundLightUpdatePacket(buf.getFriendlyByteBuf()); -+ case ClientboundLogin -> nmsPacket = new ClientboundLoginPacket(buf.getFriendlyByteBuf()); -+ case ClientboundMapItemData -> nmsPacket = new ClientboundMapItemDataPacket(buf.getFriendlyByteBuf()); -+ case ClientboundMerchantOffers -> nmsPacket = new ClientboundMerchantOffersPacket(buf.getFriendlyByteBuf()); -+ case ClientboundMoveVehicle -> nmsPacket = new ClientboundMoveVehiclePacket(buf.getFriendlyByteBuf()); -+ case ClientboundOpenBook -> nmsPacket = new ClientboundOpenBookPacket(buf.getFriendlyByteBuf()); -+ case ClientboundOpenScreen -> nmsPacket = new ClientboundOpenScreenPacket(buf.getFriendlyByteBuf()); -+ case ClientboundOpenSignEditor -> nmsPacket = new ClientboundOpenSignEditorPacket(buf.getFriendlyByteBuf()); -+ case ClientboundPlaceGhostRecipe -> nmsPacket = new ClientboundPlaceGhostRecipePacket(buf.getFriendlyByteBuf()); -+ case ClientboundPlayerAbilities -> nmsPacket = new ClientboundPlayerAbilitiesPacket(buf.getFriendlyByteBuf()); -+ case ClientboundPlayerChat -> nmsPacket = new ClientboundPlayerChatPacket(buf.getFriendlyByteBuf()); -+ case ClientboundPlayerCombatEnd -> nmsPacket = new ClientboundPlayerCombatEndPacket(buf.getFriendlyByteBuf()); -+ case ClientboundPlayerCombatEnter -> nmsPacket = new ClientboundPlayerCombatEnterPacket(buf.getFriendlyByteBuf()); -+ case ClientboundPlayerCombatKill -> nmsPacket = new ClientboundPlayerCombatKillPacket(buf.getFriendlyByteBuf()); -+ case ClientboundPlayerInfoRemove -> nmsPacket = new ClientboundPlayerInfoRemovePacket(buf.getFriendlyByteBuf()); -+ case ClientboundPlayerInfoUpdate -> nmsPacket = new ClientboundPlayerInfoUpdatePacket(buf.getFriendlyByteBuf()); -+ case ClientboundPlayerLookAt -> nmsPacket = new ClientboundPlayerLookAtPacket(buf.getFriendlyByteBuf()); -+ case ClientboundPlayerPosition -> nmsPacket = new ClientboundPlayerPositionPacket(buf.getFriendlyByteBuf()); -+ case ClientboundRecipe -> nmsPacket = new ClientboundRecipePacket(buf.getFriendlyByteBuf()); -+ case ClientboundRemoveEntities -> nmsPacket = new ClientboundRemoveEntitiesPacket(buf.getFriendlyByteBuf()); -+ case ClientboundRemoveMobEffect -> nmsPacket = new ClientboundRemoveMobEffectPacket(buf.getFriendlyByteBuf()); -+ case ClientboundResetScore -> nmsPacket = new ClientboundResetScorePacket(buf.getFriendlyByteBuf()); -+ case ClientboundRespawn -> nmsPacket = new ClientboundRespawnPacket(buf.getFriendlyByteBuf()); -+ case ClientboundRotateHead -> nmsPacket = new ClientboundRotateHeadPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSectionBlocksUpdate -> nmsPacket = new ClientboundSectionBlocksUpdatePacket(buf.getFriendlyByteBuf()); -+ case ClientboundSelectAdvancementsTab -> nmsPacket = new ClientboundSelectAdvancementsTabPacket(buf.getFriendlyByteBuf()); -+ case ClientboundServerData -> nmsPacket = new ClientboundServerDataPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetActionBarText -> nmsPacket = new ClientboundSetActionBarTextPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetBorderCenter -> nmsPacket = new ClientboundSetBorderCenterPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetBorderLerpSize -> nmsPacket = new ClientboundSetBorderLerpSizePacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetBorderSize -> nmsPacket = new ClientboundSetBorderSizePacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetBorderWarningDelay -> nmsPacket = new ClientboundSetBorderWarningDelayPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetBorderWarningDistance -> nmsPacket = new ClientboundSetBorderWarningDistancePacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetCamera -> nmsPacket = new ClientboundSetCameraPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetCarriedItem -> nmsPacket = new ClientboundSetCarriedItemPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetChunkCacheCenter -> nmsPacket = new ClientboundSetChunkCacheCenterPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetChunkCacheRadius -> nmsPacket = new ClientboundSetChunkCacheRadiusPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetDefaultSpawnPosition -> nmsPacket = new ClientboundSetDefaultSpawnPositionPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetDisplayObjective -> nmsPacket = new ClientboundSetDisplayObjectivePacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetEntityData -> nmsPacket = new ClientboundSetEntityDataPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetEntityLink -> nmsPacket = new ClientboundSetEntityLinkPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetEntityMotion -> nmsPacket = new ClientboundSetEntityMotionPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetEquipment -> nmsPacket = new ClientboundSetEquipmentPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetExperience -> nmsPacket = new ClientboundSetExperiencePacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetHealth -> nmsPacket = new ClientboundSetHealthPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetObjective -> nmsPacket = new ClientboundSetObjectivePacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetPassengers -> nmsPacket = new ClientboundSetPassengersPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetPlayerTeam -> nmsPacket = new ClientboundSetPlayerTeamPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetScore -> nmsPacket = new ClientboundSetScorePacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetSimulationDistance -> nmsPacket = new ClientboundSetSimulationDistancePacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetSubtitleText -> nmsPacket = new ClientboundSetSubtitleTextPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetTime -> nmsPacket = new ClientboundSetTimePacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetTitlesAnimation -> nmsPacket = new ClientboundSetTitlesAnimationPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSetTitleText -> nmsPacket = new ClientboundSetTitleTextPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSoundEntity -> nmsPacket = new ClientboundSoundEntityPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSound -> nmsPacket = new ClientboundSoundPacket(buf.getFriendlyByteBuf()); -+ case ClientboundStartConfiguration -> nmsPacket = new ClientboundStartConfigurationPacket(buf.getFriendlyByteBuf()); -+ case ClientboundStopSound -> nmsPacket = new ClientboundStopSoundPacket(buf.getFriendlyByteBuf()); -+ case ClientboundSystemChat -> nmsPacket = new ClientboundSystemChatPacket(buf.getFriendlyByteBuf()); -+ case ClientboundTabList -> nmsPacket = new ClientboundTabListPacket(buf.getFriendlyByteBuf()); -+ case ClientboundTagQuery -> nmsPacket = new ClientboundTagQueryPacket(buf.getFriendlyByteBuf()); -+ case ClientboundTakeItemEntity -> nmsPacket = new ClientboundTakeItemEntityPacket(buf.getFriendlyByteBuf()); -+ case ClientboundTeleportEntity -> nmsPacket = new ClientboundTeleportEntityPacket(buf.getFriendlyByteBuf()); -+ case ClientboundTickingState -> nmsPacket = new ClientboundTickingStatePacket(buf.getFriendlyByteBuf()); -+ case ClientboundTickingStep -> nmsPacket = new ClientboundTickingStepPacket(buf.getFriendlyByteBuf()); -+ case ClientboundUpdateAdvancements -> nmsPacket = new ClientboundUpdateAdvancementsPacket(buf.getFriendlyByteBuf()); -+ case ClientboundUpdateAttributes -> nmsPacket = new ClientboundUpdateAttributesPacket(buf.getFriendlyByteBuf()); -+ case ClientboundUpdateMobEffect -> nmsPacket = new ClientboundUpdateMobEffectPacket(buf.getFriendlyByteBuf()); -+ case ClientboundUpdateRecipes -> nmsPacket = new ClientboundUpdateRecipesPacket(buf.getFriendlyByteBuf()); -+ -+ } -+ } catch (Exception e) { -+ throw new UnsupportedOperationException("This feature is not completely finished yet, packet type " + type + " is not supported temporary."); -+ } -+ } -+ @Override -+ public PacketType getType() { -+ return type; -+ } -+ -+ @Override -+ public Bytebuf getBytebuf() { -+ return wrappedBytebuf; -+ } -+ -+ public net.minecraft.network.protocol.Packet getNmsPacket() { -+ return nmsPacket; -+ } -+} -diff --git a/src/main/java/org/leavesmc/leaves/packet/bytebuf/WrappedBytebuf.java b/src/main/java/org/leavesmc/leaves/packet/bytebuf/WrappedBytebuf.java -new file mode 100644 -index 0000000000000000000000000000000000000000..7444fab5dba74abfcf7b33eb39ea51d53a283a15 ---- /dev/null -+++ b/src/main/java/org/leavesmc/leaves/packet/bytebuf/WrappedBytebuf.java -@@ -0,0 +1,114 @@ -+package org.leavesmc.leaves.packet.bytebuf; -+ -+import com.mojang.brigadier.exceptions.CommandSyntaxException; -+import io.netty.buffer.Unpooled; -+import net.minecraft.nbt.Tag; -+import net.minecraft.nbt.TagParser; -+import net.minecraft.network.FriendlyByteBuf; -+import net.minecraft.network.chat.Component; -+import org.bukkit.craftbukkit.inventory.CraftItemStack; -+import org.bukkit.inventory.ItemStack; -+import org.leavesmc.leaves.packet.WrappedPacket; -+import org.leavesmc.leaves.packet.Packet; -+import org.leavesmc.leaves.packet.PacketType; -+ -+import java.util.UUID; -+ -+public class WrappedBytebuf implements Bytebuf { -+ private final FriendlyByteBuf friendlyByteBuf; -+ public WrappedBytebuf() { -+ this(256); -+ } -+ public WrappedBytebuf(int initialCapacity) { -+ friendlyByteBuf = new FriendlyByteBuf(Unpooled.buffer(initialCapacity)); -+ } -+ -+ @Override -+ public Packet toPacket(PacketType type) { -+ return new WrappedPacket(type, this); -+ } -+ -+ @Override -+ public Bytebuf writeByte(int i) { -+ friendlyByteBuf.writeByte(i); -+ return this; -+ } -+ -+ @Override -+ public Bytebuf writeBoolean(boolean flag) { -+ friendlyByteBuf.writeBoolean(flag); -+ return this; -+ } -+ -+ @Override -+ public Bytebuf writeFloat(float f) { -+ friendlyByteBuf.writeFloat(f); -+ return this; -+ } -+ -+ @Override -+ public Bytebuf writeInt(int i) { -+ friendlyByteBuf.writeInt(i); -+ return this; -+ } -+ -+ @Override -+ public Bytebuf writeShort(int i) { -+ friendlyByteBuf.writeShort(i); -+ return this; -+ } -+ -+ @Override -+ public Bytebuf writeLong(long i) { -+ friendlyByteBuf.writeLong(i); -+ return this; -+ } -+ -+ @Override -+ public Bytebuf writeVarInt(int value) { -+ friendlyByteBuf.writeVarInt(value); -+ return this; -+ } -+ -+ @Override -+ public Bytebuf writeUUID(UUID uuid) { -+ return null; -+ } -+ -+ @Override -+ public Bytebuf writeVarLong(long value) { -+ friendlyByteBuf.writeVarLong(value); -+ return this; -+ } -+ -+ @Override -+ public Bytebuf writeStringNbt(String nbt) { -+ try { -+ Tag tag = TagParser.parseTag(nbt); -+ friendlyByteBuf.writeNbt(tag); -+ } catch (CommandSyntaxException e) { -+ throw new IllegalArgumentException(e); -+ } -+ return this; -+ } -+ -+ @Override -+ public Bytebuf writeStringComponent(String component) { -+ try { -+ friendlyByteBuf.writeComponent(Component.Serializer.fromJson(component)); -+ } catch (Exception e) { -+ throw new IllegalArgumentException(e); -+ } -+ return this; -+ } -+ -+ @Override -+ public Bytebuf writeItem(ItemStack itemStack) { -+ friendlyByteBuf.writeItem(((CraftItemStack) itemStack).handle); -+ return this; -+ } -+ -+ public FriendlyByteBuf getFriendlyByteBuf() { -+ return friendlyByteBuf; -+ } -+}