9
0
mirror of https://github.com/LeavesMC/Leaves.git synced 2025-12-21 15:59:33 +00:00

Fix and rewrite bytebuf api (#218)

---------

Co-authored-by: violetc <58360096+s-yh-china@users.noreply.github.com>
This commit is contained in:
Lumine1909
2024-05-25 04:55:57 -04:00
committed by GitHub
parent 6b62f76d96
commit 46ac3c65f8
5 changed files with 989 additions and 553 deletions

View File

@@ -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 extends Enum<T>> T readEnum(Class<T> 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
+}

View File

@@ -1,15 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MC_XiaoHei <xiaohei.xor7studio@foxmail.com>
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
+

View File

@@ -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<Component> {
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 extends Enum<T>> T readEnum(Class<T> 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<PacketListener, Plugin> listenerMap = new HashMap<>();
+ private final BytebufManager manager = new SimpleBytebufManager(this);
+ private final ImmutableMap<PacketType, StreamCodec> type2CodecMap;
+ private final Cache<net.minecraft.network.protocol.PacketType<?>, PacketType> resultCache = CacheBuilder.newBuilder().build();
+
+ public InternalBytebufHandler() {
+ ImmutableMap.Builder<PacketType, StreamCodec> 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<FriendlyByteBuf, net.minecraft.network.protocol.Packet<?>>) 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<FriendlyByteBuf, net.minecraft.network.protocol.Packet<?>> 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<FriendlyByteBuf, net.minecraft.network.protocol.Packet<?>> 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()));
+ }
+}

View File

@@ -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);
+
+}

View File

@@ -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;
+ }
+}