mirror of
https://github.com/LeavesMC/Leaves.git
synced 2025-12-19 14:59:32 +00:00
650 lines
24 KiB
Diff
650 lines
24 KiB
Diff
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 5941800692ed06e17925ec6526ea38793a65de12..f77b2e12fb43039cf16a8511c9820859874c5c97 100644
|
|
--- a/src/main/java/net/minecraft/network/chat/Component.java
|
|
+++ b/src/main/java/net/minecraft/network/chat/Component.java
|
|
@@ -302,7 +302,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 13dea31c8232cdb08aff09627e84711d2ef0aa6b..44371c123e4cdd2d5257cfeaaf3139b20e785769 100644
|
|
--- a/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
+++ b/src/main/java/net/minecraft/server/players/PlayerList.java
|
|
@@ -471,6 +471,12 @@ public abstract class PlayerList {
|
|
return;
|
|
}
|
|
|
|
+ // Leaves start - Bytebuf API
|
|
+ if (!(player instanceof ServerBot) && !(player instanceof ServerPhotographer)) {
|
|
+ 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 ea4def367b645a442e7ee4fd8b1b2075b8604ccb..54d99e5b42082c306e0ac16b2b5ba9ff3c43a1b0 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
@@ -315,6 +315,7 @@ public final class CraftServer implements Server {
|
|
public final io.papermc.paper.SparksFly spark; // Paper - spark
|
|
private final org.leavesmc.leaves.entity.CraftBotManager botManager; // 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();
|
|
@@ -3298,4 +3299,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 d0132751fb057dc29e13ae3489beedb580225fa7..723db803297e06c053e160fd593dbed597eab82c 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
|
|
@@ -3580,4 +3580,16 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
|
|
this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundEntityEventPacket(((CraftEntity) target).getHandle(), effect.getData()));
|
|
}
|
|
// Paper end - entity effect API
|
|
+
|
|
+ // Leaves start - Bytebuf API
|
|
+ @Override
|
|
+ public void sendPacket(org.leavesmc.leaves.bytebuf.packet.Packet packet) {
|
|
+ this.server.getBytebufHandler().applyPacketToPlayer(this.getHandle(), packet);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void sendPacket(org.leavesmc.leaves.bytebuf.Bytebuf bytebuf, org.leavesmc.leaves.bytebuf.packet.PacketType type) {
|
|
+ this.server.getBytebufHandler().applyPacketToPlayer(this.getHandle(), 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..9601eb5aa8cbcf1836cba7853af9ece2d93ec9c3
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/bytebuf/WrappedBytebuf.java
|
|
@@ -0,0 +1,277 @@
|
|
+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.List;
|
|
+import java.util.UUID;
|
|
+
|
|
+public class WrappedBytebuf implements Bytebuf {
|
|
+
|
|
+ private final FriendlyByteBuf buf;
|
|
+ private final RegistryFriendlyByteBuf registryBuf;
|
|
+
|
|
+ public WrappedBytebuf(ByteBuf buf) {
|
|
+ if (buf instanceof RegistryFriendlyByteBuf) {
|
|
+ this.buf = (FriendlyByteBuf) buf;
|
|
+ this.registryBuf = (RegistryFriendlyByteBuf) buf;
|
|
+ } else {
|
|
+ this.buf = new FriendlyByteBuf(buf);
|
|
+ this.registryBuf = new RegistryFriendlyByteBuf(this.buf, MinecraftServer.getServer().registryAccess());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public RegistryFriendlyByteBuf getRegistryBuf() {
|
|
+ return registryBuf;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public byte[] toArray() {
|
|
+ int length = buf.readableBytes();
|
|
+ byte[] data = new byte[length];
|
|
+ buf.getBytes(buf.readerIndex(), data);
|
|
+ return data;
|
|
+ }
|
|
+
|
|
+ @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 writeItemStackList(List<ItemStack> itemStacks) {
|
|
+ List<net.minecraft.world.item.ItemStack> nmsItemList = itemStacks.stream().map(CraftItemStack::unwrap).toList();
|
|
+ net.minecraft.world.item.ItemStack.OPTIONAL_LIST_STREAM_CODEC.encode(this.registryBuf, nmsItemList);
|
|
+ return this;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public List<ItemStack> readItemStackList() {
|
|
+ List<net.minecraft.world.item.ItemStack> nmsItemList = net.minecraft.world.item.ItemStack.OPTIONAL_LIST_STREAM_CODEC.decode(this.registryBuf);
|
|
+ return nmsItemList.stream().map(net.minecraft.world.item.ItemStack::asBukkitMirror).toList();
|
|
+ }
|
|
+
|
|
+ @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..04dbb4cb7c3ea4979c33dba595208e22e6552b0a
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/leavesmc/leaves/bytebuf/internal/InternalBytebufHandler.java
|
|
@@ -0,0 +1,234 @@
|
|
+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.common.ClientboundCustomPayloadPacket;
|
|
+import net.minecraft.network.protocol.game.*;
|
|
+import net.minecraft.server.MinecraftServer;
|
|
+import net.minecraft.server.level.ServerPlayer;
|
|
+import org.bukkit.entity.Player;
|
|
+import org.bukkit.plugin.Plugin;
|
|
+import org.jetbrains.annotations.Nullable;
|
|
+import org.leavesmc.leaves.LeavesConfig;
|
|
+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 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;
|
|
+ }
|
|
+
|
|
+ if (msg instanceof net.minecraft.network.protocol.Packet<?> nmsPacket) {
|
|
+ try {
|
|
+ msg = callPacketInEvent(player, nmsPacket);
|
|
+ } 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;
|
|
+ }
|
|
+
|
|
+ if (msg instanceof net.minecraft.network.protocol.Packet<?> nmsPacket) {
|
|
+ try {
|
|
+ msg = callPacketOutEvent(player, nmsPacket);
|
|
+ } catch (Exception e) {
|
|
+ MinecraftServer.LOGGER.error("Error on PacketInEvent.", 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) {
|
|
+ try {
|
|
+ packetClass = Class.forName("net.minecraft.network.protocol.ping." + packet.name() + "Packet");
|
|
+ } catch (ClassNotFoundException ignored) {
|
|
+ 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);
|
|
+ builder.put(ClientboundCustomPayload, ClientboundCustomPayloadPacket.GAMEPLAY_STREAM_CODEC);
|
|
+
|
|
+ type2CodecMap = builder.build();
|
|
+ }
|
|
+
|
|
+ public void injectPlayer(ServerPlayer player) {
|
|
+ if (LeavesConfig.mics.leavesPacketEvent) {
|
|
+ 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, net.minecraft.network.protocol.Packet<?> nmsPacket) {
|
|
+ if (listenerMap.isEmpty()) {
|
|
+ return nmsPacket;
|
|
+ }
|
|
+ PacketType type = toEnumType(nmsPacket.type());
|
|
+ if (type == null) {
|
|
+ return nmsPacket;
|
|
+ }
|
|
+ Packet packet = createBytebufPacket(type, nmsPacket);
|
|
+ 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, net.minecraft.network.protocol.Packet<?> nmsPacket) {
|
|
+ if (listenerMap.isEmpty()) {
|
|
+ return nmsPacket;
|
|
+ }
|
|
+ PacketType type = toEnumType(nmsPacket.type());
|
|
+ if (type == null) {
|
|
+ return nmsPacket;
|
|
+ }
|
|
+ Packet packet = createBytebufPacket(type, nmsPacket);
|
|
+ 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(ServerPlayer player, Packet packet) {
|
|
+ Connection sp = player.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());
|
|
+ }
|
|
+
|
|
+ @Nullable
|
|
+ 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));
|
|
+ }
|
|
+ }
|
|
+ try {
|
|
+ return PacketType.valueOf(builder.toString());
|
|
+ } catch (IllegalArgumentException e) {
|
|
+ throw new RuntimeException(e);
|
|
+ }
|
|
+ });
|
|
+ } catch (Exception ignore) {
|
|
+ return null;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public Packet createBytebufPacket(PacketType type, net.minecraft.network.protocol.Packet<?> nmsPacket) {
|
|
+ RegistryFriendlyByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.buffer(), 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, new WrappedBytebuf(buf));
|
|
+ }
|
|
+}
|