Skip to content

Commit

Permalink
Merge branch 'master' into injector-cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Ingrim4 authored Jun 11, 2024
2 parents 820c012 + 4051cac commit 617377e
Show file tree
Hide file tree
Showing 32 changed files with 2,443 additions and 581 deletions.
16 changes: 11 additions & 5 deletions src/main/java/com/comphenix/protocol/PacketType.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@
import java.util.UUID;
import java.util.function.BiConsumer;

import org.apache.commons.lang.WordUtils;
import org.bukkit.Bukkit;

import com.comphenix.protocol.PacketTypeLookup.ClassLookup;
import com.comphenix.protocol.events.ConnectionSide;
import com.comphenix.protocol.injector.packet.PacketRegistry;
import com.comphenix.protocol.scheduler.UniversalRunnable;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.utility.MinecraftVersion;

import com.google.common.base.Preconditions;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Iterables;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Bukkit;
/**
* Represents the type of a packet in a specific protocol.
* <p>
Expand Down Expand Up @@ -477,8 +477,8 @@ public static class Client extends PacketTypeEnum {
public static final PacketType UPDATE_SIGN = new PacketType(PROTOCOL, SENDER, 0x35, "SignUpdate", "UpdateSign", "CPacketUpdateSign");
public static final PacketType ARM_ANIMATION = new PacketType(PROTOCOL, SENDER, 0x36, "Swing", "ArmAnimation", "CPacketAnimation");
public static final PacketType SPECTATE = new PacketType(PROTOCOL, SENDER, 0x37, "TeleportToEntity", "Spectate", "CPacketSpectate");
public static final PacketType USE_ITEM = new PacketType(PROTOCOL, SENDER, 0x38, "UseItemOn", "UseItem", "CPacketPlayerTryUseItemOnBlock");
public static final PacketType BLOCK_PLACE = new PacketType(PROTOCOL, SENDER, 0x39, "BlockPlace", "CPacketPlayerTryUseItem");
public static final PacketType USE_ITEM_ON = new PacketType(PROTOCOL, SENDER, 0x38, "UseItemOn", "BlockPlace", "CPacketPlayerTryUseItemOnBlock");
public static final PacketType USE_ITEM = new PacketType(PROTOCOL, SENDER, 0x39, "UseItem", "CPacketPlayerTryUseItem");

/**
* @deprecated Removed in 1.17
Expand All @@ -498,6 +498,12 @@ public static class Client extends PacketTypeEnum {
@Deprecated
public static final PacketType CHAT_PREVIEW = new PacketType(PROTOCOL, SENDER, 253, "ChatPreview");

/**
* @deprecated Renamed to USE_ITEM_ON
*/
@Deprecated
public static final PacketType BLOCK_PLACE = USE_ITEM_ON.clone();

private static final Client INSTANCE = new Client();

// Prevent accidental construction
Expand Down
49 changes: 49 additions & 0 deletions src/main/java/com/comphenix/protocol/events/AbstractStructure.java
Original file line number Diff line number Diff line change
Expand Up @@ -870,6 +870,55 @@ public StructureModifier<EnumWrappers.ChatType> getChatTypes() {
EnumWrappers.getChatTypeConverter());
}

/**
* Retrieve a read/write structure for the DisplaySlot enum in 1.20.2.
* @return A modifier for DisplaySlot enum fields.
*/
public StructureModifier<EnumWrappers.DisplaySlot> getDisplaySlots() {
return structureModifier.withType(
EnumWrappers.getDisplaySlotClass(),
EnumWrappers.getDisplaySlotConverter());
}

/**
* Retrieve a read/write structure for the RenderType enum.
* @return A modifier for RenderType enum fields.
*/
public StructureModifier<EnumWrappers.RenderType> getRenderTypes() {
return structureModifier.withType(
EnumWrappers.getRenderTypeClass(),
EnumWrappers.getRenderTypeConverter());
}

/**
* Retrieve a read/write structure for the ChatFormatting enum.
* @return A modifier for ChatFormatting enum fields.
*/
public StructureModifier<EnumWrappers.ChatFormatting> getChatFormattings() {
return structureModifier.withType(
EnumWrappers.getChatFormattingClass(),
EnumWrappers.getChatFormattingConverter());
}

/**
* Retrieve a read/write structure for optional team parameters in 1.17+.
* @return A modifier for optional team parameters fields.
*/
public StructureModifier<Optional<WrappedTeamParameters>> getOptionalTeamParameters() {
return getOptionals(BukkitConverters.getWrappedTeamParametersConverter());
}

/**
* Retrieve a read/write structure for the NumberFormat class in 1.20.4+.
* @return A modifier for NumberFormat fields.
*/
public StructureModifier<WrappedNumberFormat> getNumberFormats() {
return structureModifier.withType(
MinecraftReflection.getNumberFormatClass().orElse(null),
BukkitConverters.getWrappedNumberFormatConverter());
}


/**
* Retrieve a read/write structure for the MinecraftKey class.
* @return A modifier for MinecraftKey fields.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import javax.annotation.Nullable;

import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.injector.StructureCache;
Expand Down Expand Up @@ -58,10 +59,10 @@
import com.comphenix.protocol.utility.MinecraftVersion;
import com.comphenix.protocol.wrappers.Converters;
import com.comphenix.protocol.wrappers.WrappedStreamCodec;

import com.google.common.collect.Sets;
import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;
import javax.annotation.Nullable;

/**
* Represents a Minecraft packet indirectly.
Expand All @@ -80,7 +81,7 @@ public class PacketContainer extends AbstractStructure implements Serializable {
// Used to clone packets
private static final AggregateCloner DEEP_CLONER = AggregateCloner
.newBuilder()
.instanceProvider(StructureCache::newPacket)
.instanceProvider(StructureCache::newInstance)
.andThen(BukkitCloner.class)
.andThen(ImmutableDetector.class)
.andThen(JavaOptionalCloner.class)
Expand All @@ -91,7 +92,7 @@ public class PacketContainer extends AbstractStructure implements Serializable {

private static final AggregateCloner SHALLOW_CLONER = AggregateCloner
.newBuilder()
.instanceProvider(StructureCache::newPacket)
.instanceProvider(StructureCache::newInstance)
.andThen(param -> {
if (param == null)
throw new IllegalArgumentException("Cannot be NULL.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,25 @@

package com.comphenix.protocol.events;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

import com.comphenix.protocol.reflect.accessors.Accessors;
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
import com.comphenix.protocol.utility.ByteBuddyFactory;
import com.comphenix.protocol.utility.Util;

import net.bytebuddy.description.ByteCodeElement;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
Expand All @@ -35,27 +50,19 @@
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import org.bukkit.*;
import org.bukkit.BanEntry;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Statistic;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.profile.PlayerProfile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
* Represents a player object that can be serialized by Java.
*
Expand Down
111 changes: 62 additions & 49 deletions src/main/java/com/comphenix/protocol/injector/StructureCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
import com.comphenix.protocol.reflect.instances.DefaultInstances;
import com.comphenix.protocol.reflect.instances.PacketCreator;
import com.comphenix.protocol.reflect.instances.InstanceCreator;
import com.comphenix.protocol.utility.ByteBuddyFactory;
import com.comphenix.protocol.utility.MinecraftMethods;
import com.comphenix.protocol.utility.MinecraftReflection;
Expand All @@ -57,7 +57,7 @@
public class StructureCache {

// Structure modifiers
private static final Map<Class<?>, Supplier<Object>> PACKET_INSTANCE_CREATORS = new ConcurrentHashMap<>();
private static final Map<Class<?>, Supplier<Object>> CACHED_INSTANCE_CREATORS = new ConcurrentHashMap<>();
private static final Map<PacketType, StructureModifier<Object>> STRUCTURE_MODIFIER_CACHE = new ConcurrentHashMap<>();

// packet data serializer which always returns an empty nbt tag compound
Expand All @@ -67,77 +67,90 @@ public class StructureCache {
private static Supplier<Object> TRICKED_DATA_SERIALIZER_BASE;
private static Supplier<Object> TRICKED_DATA_SERIALIZER_JSON;

/**
* @deprecated Renamed to {@link #newInstance(Class)}.
*/
@Deprecated
public static Object newPacket(Class<?> packetClass) {
Supplier<Object> packetConstructor = PACKET_INSTANCE_CREATORS.computeIfAbsent(packetClass, packetClassKey -> {
PacketCreator creator = PacketCreator.forPacket(packetClassKey);
return newInstance(packetClass);
}

public static Object newInstance(Class<?> clazz) {
Supplier<Object> creator = CACHED_INSTANCE_CREATORS.computeIfAbsent(clazz, StructureCache::determineBestCreator);
return creator.get();
}

static Supplier<Object> determineBestCreator(Class<?> clazz) {
try {
InstanceCreator creator = InstanceCreator.forClass(clazz);
if (creator.get() != null) {
return creator;
}
} catch (Exception ignored) {
}

WrappedStreamCodec streamCodec = PacketRegistry.getStreamCodec(packetClassKey);
WrappedStreamCodec streamCodec = PacketRegistry.getStreamCodec(clazz);

// use the new stream codec for versions above 1.20.5 if possible
if (streamCodec != null && tryInitTrickDataSerializer()) {
// use the new stream codec for versions above 1.20.5 if possible
if (streamCodec != null && tryInitTrickDataSerializer()) {
try {
// first try with the base accessor
Object serializer = TRICKED_DATA_SERIALIZER_BASE.get();
streamCodec.decode(serializer); // throwaway instance, for testing

// method is working
return () -> streamCodec.decode(serializer);
} catch (Exception ignored) {
try {
// first try with the base accessor
Object serializer = TRICKED_DATA_SERIALIZER_BASE.get();
// try with the json accessor
Object serializer = TRICKED_DATA_SERIALIZER_JSON.get();
streamCodec.decode(serializer); // throwaway instance, for testing

// method is working
return () -> streamCodec.decode(serializer);
} catch (Exception ignored) {
try {
// try with the json accessor
Object serializer = TRICKED_DATA_SERIALIZER_JSON.get();
streamCodec.decode(serializer); // throwaway instance, for testing

// method is working
return () -> streamCodec.decode(serializer);
} catch (Exception ignored1) {
// shrug, fall back to default behaviour
}
} catch (Exception ignored1) {
// shrug, fall back to default behaviour
}
}
}

// prefer construction via PacketDataSerializer constructor on 1.17 and above
if (MinecraftVersion.CAVES_CLIFFS_1.atOrAbove()) {
ConstructorAccessor serializerAccessor = Accessors.getConstructorAccessorOrNull(
packetClassKey,
MinecraftReflection.getPacketDataSerializerClass());
if (serializerAccessor != null) {
// check if the method is possible
if (tryInitTrickDataSerializer()) {
// prefer construction via PacketDataSerializer constructor on 1.17 and above
if (MinecraftVersion.CAVES_CLIFFS_1.atOrAbove()) {
ConstructorAccessor serializerAccessor = Accessors.getConstructorAccessorOrNull(
clazz,
MinecraftReflection.getPacketDataSerializerClass());
if (serializerAccessor != null) {
// check if the method is possible
if (tryInitTrickDataSerializer()) {
try {
// first try with the base accessor
Object serializer = TRICKED_DATA_SERIALIZER_BASE.get();
serializerAccessor.invoke(serializer); // throwaway instance, for testing

// method is working
return () -> serializerAccessor.invoke(serializer);
} catch (Exception ignored) {
try {
// first try with the base accessor
Object serializer = TRICKED_DATA_SERIALIZER_BASE.get();
// try with the json accessor
Object serializer = TRICKED_DATA_SERIALIZER_JSON.get();
serializerAccessor.invoke(serializer); // throwaway instance, for testing

// method is working
return () -> serializerAccessor.invoke(serializer);
} catch (Exception ignored) {
try {
// try with the json accessor
Object serializer = TRICKED_DATA_SERIALIZER_JSON.get();
serializerAccessor.invoke(serializer); // throwaway instance, for testing

// method is working
return () -> serializerAccessor.invoke(serializer);
} catch (Exception ignored1) {
// shrug, fall back to default behaviour
}
} catch (Exception ignored1) {
// shrug, fall back to default behaviour
}
}
}
}
}

// try via DefaultInstances as fallback
return () -> {
Object packetInstance = DefaultInstances.DEFAULT.create(packetClassKey);
Objects.requireNonNull(packetInstance, "Unable to create packet instance for class " + packetClassKey + " - " + tryInitTrickDataSerializer() + " - " + streamCodec);
return packetInstance;
};
});
return packetConstructor.get();
// try via DefaultInstances as fallback
return () -> {
Object packetInstance = DefaultInstances.DEFAULT.create(clazz);
Objects.requireNonNull(packetInstance, "Unable to create instance for class " + clazz + " - " + tryInitTrickDataSerializer() + " - " + streamCodec);
return packetInstance;
};
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ private static void fromManual(Supplier<Class<?>> getClass, Function<Object, Obj
static {
fromManual(MinecraftReflection::getItemStackClass, source ->
MinecraftReflection.getMinecraftItemStack(MinecraftReflection.getBukkitItemStack(source).clone()));
fromWrapper(MinecraftReflection::getDataWatcherClass, WrappedDataWatcher::new);
fromManual(MinecraftReflection::getDataWatcherClass, source -> new WrappedDataWatcher(source).deepClone().getHandle());
fromConverter(MinecraftReflection::getBlockPositionClass, BlockPosition.getConverter());
fromWrapper(MinecraftReflection::getServerPingClass, WrappedServerPing::fromHandle);
fromConverter(MinecraftReflection::getMinecraftKeyClass, MinecraftKey.getConverter());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ public class ImmutableDetector implements Cloner {
add(MinecraftReflection::getDataWatcherSerializerClass);
add(MinecraftReflection::getBlockClass);
add(MinecraftReflection::getItemClass);
add("sounds.SoundEffect", "sounds.SoundEvents", "SoundEffect");
add(MinecraftReflection::getSoundEffectClass);

if (MinecraftVersion.AQUATIC_UPDATE.atOrAbove()) {
add(MinecraftReflection::getFluidTypeClass);
add(MinecraftReflection::getParticleTypeClass);
add("core.particles.Particle","core.particles.ParticleType", "Particle");
add(MinecraftReflection::getParticleClass);
}

if (MinecraftVersion.VILLAGE_UPDATE.atOrAbove()) {
Expand Down
Loading

0 comments on commit 617377e

Please sign in to comment.