diff --git a/api/src/main/java/com/github/retrooper/packetevents/netty/buffer/ByteBufHelper.java b/api/src/main/java/com/github/retrooper/packetevents/netty/buffer/ByteBufHelper.java index 581c364ba..6142d183a 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/netty/buffer/ByteBufHelper.java +++ b/api/src/main/java/com/github/retrooper/packetevents/netty/buffer/ByteBufHelper.java @@ -23,6 +23,7 @@ import java.nio.charset.Charset; public class ByteBufHelper { + public static int capacity(Object buffer) { return PacketEvents.getAPI().getNettyManager().getByteBufOperator().capacity(buffer); } diff --git a/api/src/main/java/com/github/retrooper/packetevents/netty/buffer/ByteBufOperator.java b/api/src/main/java/com/github/retrooper/packetevents/netty/buffer/ByteBufOperator.java index 4b20c3f83..5bc72c29b 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/netty/buffer/ByteBufOperator.java +++ b/api/src/main/java/com/github/retrooper/packetevents/netty/buffer/ByteBufOperator.java @@ -21,6 +21,7 @@ import java.nio.charset.Charset; public interface ByteBufOperator { + int capacity(Object buffer); Object capacity(Object buffer, int capacity); int readerIndex(Object buffer); diff --git a/api/src/main/java/com/github/retrooper/packetevents/util/meta/PacketWrapperMeta.java b/api/src/main/java/com/github/retrooper/packetevents/util/meta/PacketWrapperMeta.java new file mode 100644 index 000000000..0d141419e --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/util/meta/PacketWrapperMeta.java @@ -0,0 +1,33 @@ +package com.github.retrooper.packetevents.util.meta; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class PacketWrapperMeta { + private final Map data = new HashMap<>(); + private final long timestamp = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(10); + + public void put(@NotNull String key, @NotNull Object value) { + this.data.put(key, value); + } + + public boolean has(@NotNull String key) { + return this.data.containsKey(key); + } + + public @Nullable Object get(@NotNull String key) { + return this.data.get(key); + } + + public long getTimestamp() { + return this.timestamp; + } + + public boolean isExpired() { + return getTimestamp() < System.currentTimeMillis(); + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/util/meta/PacketWrapperMetaCache.java b/api/src/main/java/com/github/retrooper/packetevents/util/meta/PacketWrapperMetaCache.java new file mode 100644 index 000000000..260c3175e --- /dev/null +++ b/api/src/main/java/com/github/retrooper/packetevents/util/meta/PacketWrapperMetaCache.java @@ -0,0 +1,78 @@ +package com.github.retrooper.packetevents.util.meta; + +import org.jetbrains.annotations.NotNull; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; + +public class PacketWrapperMetaCache { + private static final Map META_CACHE = new ConcurrentHashMap<>(); + + public static void setMeta(@NotNull Object buffer, @NotNull String key, @NotNull Object value) { + META_CACHE.computeIfAbsent(new IdentityKey(buffer), unused -> new PacketWrapperMeta()) + .put(key, value); + } + + public static boolean hasMeta(@NotNull Object buffer, @NotNull String key) { + return META_CACHE.computeIfAbsent(new IdentityKey(buffer), unused -> new PacketWrapperMeta()) + .has(key); + } + + public static Object getMeta(@NotNull Object buffer, @NotNull String key) { + return META_CACHE.computeIfAbsent(new IdentityKey(buffer), unused -> new PacketWrapperMeta()) + .get(key); + } + + public static void clean() { + Set toRemoveKeys = new HashSet<>(); + META_CACHE.forEach((identityKey, meta) -> { + if (meta.isExpired()) { + toRemoveKeys.add(identityKey); + } + }); + toRemoveKeys.forEach(META_CACHE::remove); + } + + static { + ThreadFactory threadFactory = new ThreadFactory() { + private int counter = 0; + + @Override + public @NotNull Thread newThread(@NotNull Runnable runnable) { + Thread thread = new Thread(runnable); + thread.setName("packet-events - meta clean #" + counter++); + thread.setDaemon(false); + return thread; + } + }; + + ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(threadFactory); + executor.scheduleAtFixedRate(PacketWrapperMetaCache::clean, 0, 10, TimeUnit.SECONDS); + } + + private static final class IdentityKey { + private final Object ref; + + public IdentityKey(Object ref) { + this.ref = ref; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + IdentityKey that = (IdentityKey) o; + return ref == that.ref; + } + + @Override + public int hashCode() { + return System.identityHashCode(ref); + } + } +} diff --git a/api/src/main/java/com/github/retrooper/packetevents/wrapper/PacketWrapper.java b/api/src/main/java/com/github/retrooper/packetevents/wrapper/PacketWrapper.java index e83c0c36a..2d40e5066 100644 --- a/api/src/main/java/com/github/retrooper/packetevents/wrapper/PacketWrapper.java +++ b/api/src/main/java/com/github/retrooper/packetevents/wrapper/PacketWrapper.java @@ -51,15 +51,8 @@ import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper; import com.github.retrooper.packetevents.netty.channel.ChannelHelper; import com.github.retrooper.packetevents.protocol.PacketSide; -import com.github.retrooper.packetevents.protocol.chat.ChatType; -import com.github.retrooper.packetevents.protocol.chat.ChatTypes; -import com.github.retrooper.packetevents.protocol.chat.LastSeenMessages; -import com.github.retrooper.packetevents.protocol.chat.MessageSignature; -import com.github.retrooper.packetevents.protocol.chat.Node; -import com.github.retrooper.packetevents.protocol.chat.Parsers; +import com.github.retrooper.packetevents.protocol.chat.*; import com.github.retrooper.packetevents.protocol.chat.Parsers.Parser; -import com.github.retrooper.packetevents.protocol.chat.RemoteChatSession; -import com.github.retrooper.packetevents.protocol.chat.SignedCommandArgument; import com.github.retrooper.packetevents.protocol.chat.filter.FilterMask; import com.github.retrooper.packetevents.protocol.chat.filter.FilterMaskType; import com.github.retrooper.packetevents.protocol.entity.data.EntityData; @@ -89,11 +82,7 @@ import com.github.retrooper.packetevents.protocol.world.Dimension; import com.github.retrooper.packetevents.protocol.world.WorldBlockPosition; import com.github.retrooper.packetevents.resources.ResourceLocation; -import com.github.retrooper.packetevents.util.Either; -import com.github.retrooper.packetevents.util.KnownPack; -import com.github.retrooper.packetevents.util.MathUtil; -import com.github.retrooper.packetevents.util.StringUtil; -import com.github.retrooper.packetevents.util.Vector3i; +import com.github.retrooper.packetevents.util.*; import com.github.retrooper.packetevents.util.adventure.AdventureSerializer; import com.github.retrooper.packetevents.util.crypto.MinecraftEncryptionUtil; import com.github.retrooper.packetevents.util.crypto.SaltSignature; @@ -101,6 +90,7 @@ import com.github.retrooper.packetevents.util.mappings.GlobalRegistryHolder; import com.github.retrooper.packetevents.util.mappings.IRegistry; import com.github.retrooper.packetevents.util.mappings.IRegistryHolder; +import com.github.retrooper.packetevents.util.meta.PacketWrapperMetaCache; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.Style; import org.jetbrains.annotations.ApiStatus; @@ -112,31 +102,26 @@ import java.nio.charset.StandardCharsets; import java.security.PublicKey; import java.time.Instant; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collection; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.IntFunction; public class PacketWrapper> { + @Nullable public Object buffer; @ApiStatus.Internal public final Object bufferLock = new Object(); + @Nullable + private Map metadata; + protected ClientVersion clientVersion; protected ServerVersion serverVersion; - private PacketTypeData packetTypeData; + private final PacketTypeData packetTypeData; // For sending chunk data packets, which need this data @Nullable protected User user; @@ -236,6 +221,9 @@ public final void prepareForSend(Object channel, boolean outgoing, boolean proxy buffer = ChannelHelper.pooledByteBuf(channel); } + // Wrapped meta system + writeMeta(); + //On proxies, we must rewrite the packet ID in a format compatible for the targeted client version if (proxy) { User user = PacketEvents.getAPI().getProtocolManager().getUser(channel); @@ -259,6 +247,36 @@ public final void prepareForSend(Object channel, boolean outgoing) { prepareForSend(channel, outgoing, PacketEvents.getAPI().getInjector().isProxy()); } + public void setMeta(@NotNull String key, @NotNull Object value) { + if (this.metadata == null) { + this.metadata = new HashMap<>(); + } + + this.metadata.put(key, value); + } + + public Object getMeta(@NotNull String key) { + if (this.buffer != null) { + return PacketWrapperMetaCache.getMeta(this.buffer, key); + } + + return null; + } + + public boolean hasMeta(@NotNull String key) { + if (this.buffer != null) { + return PacketWrapperMetaCache.hasMeta(this.buffer, key); + } + + return false; + } + + public void writeMeta() { + if (this.buffer != null && this.metadata != null) { + this.metadata.forEach((key, value) -> PacketWrapperMetaCache.setMeta(this.buffer, key, value)); + } + } + public void read() { } @@ -281,6 +299,7 @@ public final void readEvent(ProtocolPacketEvent event) { } else { read(); } + event.setLastUsedWrapper(this); } diff --git a/fabric/src/main/java/io/github/retrooper/packetevents/handler/PacketDecoder.java b/fabric/src/main/java/io/github/retrooper/packetevents/handler/PacketDecoder.java index 4788e6bf4..6e589c353 100644 --- a/fabric/src/main/java/io/github/retrooper/packetevents/handler/PacketDecoder.java +++ b/fabric/src/main/java/io/github/retrooper/packetevents/handler/PacketDecoder.java @@ -46,8 +46,10 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List out) if (!msg.isReadable()) { return; } + PacketEventsImplHelper.handlePacket(ctx.channel(), this.user, this.player, msg, false, this.side); + if (msg.isReadable()) { out.add(msg.retain()); } diff --git a/netty-common/src/main/java/io/github/retrooper/packetevents/impl/netty/buffer/ByteBufOperatorImpl.java b/netty-common/src/main/java/io/github/retrooper/packetevents/impl/netty/buffer/ByteBufOperatorImpl.java index af4180e39..434dbf297 100644 --- a/netty-common/src/main/java/io/github/retrooper/packetevents/impl/netty/buffer/ByteBufOperatorImpl.java +++ b/netty-common/src/main/java/io/github/retrooper/packetevents/impl/netty/buffer/ByteBufOperatorImpl.java @@ -24,6 +24,7 @@ import java.nio.charset.Charset; public class ByteBufOperatorImpl implements ByteBufOperator { + @Override public int capacity(Object buffer) { return ((ByteBuf)buffer).capacity(); diff --git a/spigot/src/main/java/io/github/retrooper/packetevents/injector/handlers/PacketEventsEncoder.java b/spigot/src/main/java/io/github/retrooper/packetevents/injector/handlers/PacketEventsEncoder.java index b6ecbe88d..8aef21072 100644 --- a/spigot/src/main/java/io/github/retrooper/packetevents/injector/handlers/PacketEventsEncoder.java +++ b/spigot/src/main/java/io/github/retrooper/packetevents/injector/handlers/PacketEventsEncoder.java @@ -26,10 +26,8 @@ import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper; import com.github.retrooper.packetevents.protocol.ConnectionState; import com.github.retrooper.packetevents.protocol.player.User; -import com.github.retrooper.packetevents.util.EventCreationUtil; import com.github.retrooper.packetevents.util.ExceptionUtil; import com.github.retrooper.packetevents.util.PacketEventsImplHelper; -import com.github.retrooper.packetevents.wrapper.PacketWrapper; import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDisconnect; import io.github.retrooper.packetevents.injector.connection.ServerConnectionInitializer; import io.github.retrooper.packetevents.util.SpigotReflectionUtil; diff --git a/spigot/src/main/java/io/github/retrooper/packetevents/netty/buffer/ByteBufOperatorModernImpl.java b/spigot/src/main/java/io/github/retrooper/packetevents/netty/buffer/ByteBufOperatorModernImpl.java index 082b831da..d6c81a0a7 100644 --- a/spigot/src/main/java/io/github/retrooper/packetevents/netty/buffer/ByteBufOperatorModernImpl.java +++ b/spigot/src/main/java/io/github/retrooper/packetevents/netty/buffer/ByteBufOperatorModernImpl.java @@ -24,226 +24,227 @@ import java.nio.charset.Charset; public class ByteBufOperatorModernImpl implements ByteBufOperator { + @Override public int capacity(Object buffer) { - return ((ByteBuf)buffer).capacity(); + return ((ByteBuf) buffer).capacity(); } @Override public Object capacity(Object buffer, int capacity) { - return ((ByteBuf)buffer).capacity(capacity); + return ((ByteBuf) buffer).capacity(capacity); } @Override public int readerIndex(Object buffer) { - return ((ByteBuf)buffer).readerIndex(); + return ((ByteBuf) buffer).readerIndex(); } @Override public Object readerIndex(Object buffer, int readerIndex) { - return ((ByteBuf)buffer).readerIndex(readerIndex); + return ((ByteBuf) buffer).readerIndex(readerIndex); } @Override public int writerIndex(Object buffer) { - return ((ByteBuf)buffer).writerIndex(); + return ((ByteBuf) buffer).writerIndex(); } @Override public Object writerIndex(Object buffer, int writerIndex) { - return ((ByteBuf)buffer).writerIndex(writerIndex); + return ((ByteBuf) buffer).writerIndex(writerIndex); } @Override public int readableBytes(Object buffer) { - return ((ByteBuf)buffer).readableBytes(); + return ((ByteBuf) buffer).readableBytes(); } @Override public int writableBytes(Object buffer) { - return ((ByteBuf)buffer).writableBytes(); + return ((ByteBuf) buffer).writableBytes(); } @Override public Object clear(Object buffer) { - return ((ByteBuf)buffer).clear(); + return ((ByteBuf) buffer).clear(); } @Override public byte readByte(Object buffer) { - return ((ByteBuf)buffer).readByte(); + return ((ByteBuf) buffer).readByte(); } @Override public short readShort(Object buffer) { - return ((ByteBuf)buffer).readShort(); + return ((ByteBuf) buffer).readShort(); } @Override public int readMedium(Object buffer) { - return ((ByteBuf)buffer).readMedium(); + return ((ByteBuf) buffer).readMedium(); } @Override public int readInt(Object buffer) { - return ((ByteBuf)buffer).readInt(); + return ((ByteBuf) buffer).readInt(); } @Override public long readUnsignedInt(Object buffer) { - return ((ByteBuf)buffer).readUnsignedInt(); + return ((ByteBuf) buffer).readUnsignedInt(); } @Override public long readLong(Object buffer) { - return ((ByteBuf)buffer).readLong(); + return ((ByteBuf) buffer).readLong(); } @Override public void writeByte(Object buffer, int value) { - ((ByteBuf)buffer).writeByte(value); + ((ByteBuf) buffer).writeByte(value); } @Override public void writeShort(Object buffer, int value) { - ((ByteBuf)buffer).writeShort(value); + ((ByteBuf) buffer).writeShort(value); } @Override public void writeMedium(Object buffer, int value) { - ((ByteBuf)buffer).writeMedium(value); + ((ByteBuf) buffer).writeMedium(value); } @Override public void writeInt(Object buffer, int value) { - ((ByteBuf)buffer).writeInt(value); + ((ByteBuf) buffer).writeInt(value); } @Override public void writeLong(Object buffer, long value) { - ((ByteBuf)buffer).writeLong(value); + ((ByteBuf) buffer).writeLong(value); } @Override public Object getBytes(Object buffer, int index, byte[] destination) { - return ((ByteBuf)buffer).getBytes(index, destination); + return ((ByteBuf) buffer).getBytes(index, destination); } @Override public short getUnsignedByte(Object buffer, int index) { - return ((ByteBuf)buffer).getUnsignedByte(index); + return ((ByteBuf) buffer).getUnsignedByte(index); } @Override public boolean isReadable(Object buffer) { - return ((ByteBuf)buffer).isReadable(); + return ((ByteBuf) buffer).isReadable(); } @Override public Object copy(Object buffer) { - return ((ByteBuf)buffer).copy(); + return ((ByteBuf) buffer).copy(); } @Override public Object duplicate(Object buffer) { - return ((ByteBuf)buffer).duplicate(); + return ((ByteBuf) buffer).duplicate(); } @Override public boolean hasArray(Object buffer) { - return ((ByteBuf)buffer).hasArray(); + return ((ByteBuf) buffer).hasArray(); } @Override public byte[] array(Object buffer) { - return ((ByteBuf)buffer).array(); + return ((ByteBuf) buffer).array(); } @Override public Object retain(Object buffer) { - return ((ByteBuf)buffer).retain(); + return ((ByteBuf) buffer).retain(); } @Override public Object retainedDuplicate(Object buffer) { - return ((ByteBuf)buffer).duplicate().retain(); + return ((ByteBuf) buffer).duplicate().retain(); } @Override public Object readSlice(Object buffer, int length) { - return ((ByteBuf)buffer).readSlice(length); + return ((ByteBuf) buffer).readSlice(length); } @Override public Object readBytes(Object buffer, byte[] destination, int destinationIndex, int length) { - return ((ByteBuf)buffer).readBytes(destination, destinationIndex, length); + return ((ByteBuf) buffer).readBytes(destination, destinationIndex, length); } @Override public Object readBytes(Object buffer, int length) { - return ((ByteBuf)buffer).readBytes(length); + return ((ByteBuf) buffer).readBytes(length); } @Override public Object writeBytes(Object buffer, Object src) { - return ((ByteBuf)buffer).writeBytes((ByteBuf) src); + return ((ByteBuf) buffer).writeBytes((ByteBuf) src); } @Override public Object writeBytes(Object buffer, byte[] bytes) { - return ((ByteBuf)buffer).writeBytes(bytes); + return ((ByteBuf) buffer).writeBytes(bytes); } @Override public Object writeBytes(Object buffer, byte[] bytes, int offset, int length) { - return ((ByteBuf)buffer).writeBytes(bytes, offset, length); + return ((ByteBuf) buffer).writeBytes(bytes, offset, length); } @Override public void readBytes(Object buffer, byte[] bytes) { - ((ByteBuf)buffer).readBytes(bytes); + ((ByteBuf) buffer).readBytes(bytes); } @Override public boolean release(Object buffer) { - return ((ByteBuf)buffer).release(); + return ((ByteBuf) buffer).release(); } @Override public int refCnt(Object buffer) { - return ((ByteBuf)buffer).refCnt(); + return ((ByteBuf) buffer).refCnt(); } @Override public Object skipBytes(Object buffer, int length) { - return ((ByteBuf)buffer).skipBytes(length); + return ((ByteBuf) buffer).skipBytes(length); } @Override public String toString(Object buffer, int index, int length, Charset charset) { - return ((ByteBuf)buffer).toString(index, length, charset); + return ((ByteBuf) buffer).toString(index, length, charset); } @Override public Object markReaderIndex(Object buffer) { - return ((ByteBuf)buffer).markReaderIndex(); + return ((ByteBuf) buffer).markReaderIndex(); } @Override public Object resetReaderIndex(Object buffer) { - return ((ByteBuf)buffer).resetReaderIndex(); + return ((ByteBuf) buffer).resetReaderIndex(); } @Override public Object markWriterIndex(Object buffer) { - return ((ByteBuf)buffer).markWriterIndex(); + return ((ByteBuf) buffer).markWriterIndex(); } @Override public Object resetWriterIndex(Object buffer) { - return ((ByteBuf)buffer).resetWriterIndex(); + return ((ByteBuf) buffer).resetWriterIndex(); } @Override diff --git a/sponge/src/main/java/io/github/retrooper/packetevents/sponge/netty/buffer/ByteBufOperatorModernImpl.java b/sponge/src/main/java/io/github/retrooper/packetevents/sponge/netty/buffer/ByteBufOperatorModernImpl.java index 76f70a75e..f920d7a58 100644 --- a/sponge/src/main/java/io/github/retrooper/packetevents/sponge/netty/buffer/ByteBufOperatorModernImpl.java +++ b/sponge/src/main/java/io/github/retrooper/packetevents/sponge/netty/buffer/ByteBufOperatorModernImpl.java @@ -24,6 +24,7 @@ import java.nio.charset.Charset; public class ByteBufOperatorModernImpl implements ByteBufOperator { + @Override public int capacity(Object buffer) { return ((ByteBuf)buffer).capacity();