3131import java .util .Arrays ;
3232import java .util .Collections ;
3333import java .util .EnumMap ;
34+ import java .util .List ;
3435import java .util .Map ;
3536import java .util .function .Supplier ;
37+ import java .util .stream .Collectors ;
38+ import java .util .stream .Stream ;
3639import net .elytrium .commons .utils .reflection .ReflectionException ;
3740import net .elytrium .limboapi .api .protocol .PacketDirection ;
3841import net .elytrium .limboapi .api .protocol .packets .PacketMapping ;
42+ import net .elytrium .limboapi .api .utils .OverlayMap ;
3943import net .elytrium .limboapi .protocol .packets .c2s .MoveOnGroundOnlyPacket ;
4044import net .elytrium .limboapi .protocol .packets .c2s .MovePacket ;
4145import net .elytrium .limboapi .protocol .packets .c2s .MovePositionOnlyPacket ;
@@ -67,8 +71,11 @@ public class LimboProtocol {
6771
6872 public static final String READ_TIMEOUT = "limboapi-read-timeout" ;
6973
74+ public static final MethodHandle VERSIONS_GETTER ;
7075 public static final Field VERSIONS_FIELD ;
76+ public static final MethodHandle PACKET_ID_TO_SUPPLIER_GETTER ;
7177 public static final Field PACKET_ID_TO_SUPPLIER_FIELD ;
78+ public static final MethodHandle PACKET_CLASS_TO_ID_GETTER ;
7279 public static final Field PACKET_CLASS_TO_ID_FIELD ;
7380 public static final StateRegistry .PacketRegistry PLAY_CLIENTBOUND_REGISTRY ;
7481 public static final StateRegistry .PacketRegistry PLAY_SERVERBOUND_REGISTRY ;
@@ -85,12 +92,18 @@ public class LimboProtocol {
8592
8693 LIMBO_STATE_REGISTRY = (StateRegistry ) UNSAFE .allocateInstance (StateRegistry .class );
8794
95+ VERSIONS_GETTER = MethodHandles .privateLookupIn (StateRegistry .PacketRegistry .class , MethodHandles .lookup ())
96+ .findGetter (StateRegistry .PacketRegistry .class , "versions" , Map .class );
8897 VERSIONS_FIELD = StateRegistry .PacketRegistry .class .getDeclaredField ("versions" );
8998 VERSIONS_FIELD .setAccessible (true );
9099
100+ PACKET_ID_TO_SUPPLIER_GETTER = MethodHandles .privateLookupIn (StateRegistry .PacketRegistry .ProtocolRegistry .class , MethodHandles .lookup ())
101+ .findGetter (StateRegistry .PacketRegistry .ProtocolRegistry .class , "packetIdToSupplier" , IntObjectMap .class );
91102 PACKET_ID_TO_SUPPLIER_FIELD = StateRegistry .PacketRegistry .ProtocolRegistry .class .getDeclaredField ("packetIdToSupplier" );
92103 PACKET_ID_TO_SUPPLIER_FIELD .setAccessible (true );
93104
105+ PACKET_CLASS_TO_ID_GETTER = MethodHandles .privateLookupIn (StateRegistry .PacketRegistry .ProtocolRegistry .class , MethodHandles .lookup ())
106+ .findGetter (StateRegistry .PacketRegistry .ProtocolRegistry .class , "packetClassToId" , Object2IntMap .class );
94107 PACKET_CLASS_TO_ID_FIELD = StateRegistry .PacketRegistry .ProtocolRegistry .class .getDeclaredField ("packetClassToId" );
95108 PACKET_CLASS_TO_ID_FIELD .setAccessible (true );
96109
@@ -121,7 +134,7 @@ public class LimboProtocol {
121134 }
122135
123136 private static void overlayRegistry (StateRegistry stateRegistry ,
124- String registryName , StateRegistry .PacketRegistry playRegistry ) throws ReflectiveOperationException {
137+ String registryName , StateRegistry .PacketRegistry playRegistry ) throws Throwable {
125138 StateRegistry .PacketRegistry registry = (StateRegistry .PacketRegistry ) UNSAFE .allocateInstance (StateRegistry .PacketRegistry .class );
126139
127140 Field directionField = StateRegistry .PacketRegistry .class .getDeclaredField ("direction" );
@@ -133,7 +146,8 @@ private static void overlayRegistry(StateRegistry stateRegistry,
133146
134147 // Overlay packets from PLAY state registry.
135148 // P.S. I hate it when someone uses var in code, but there I had no choice.
136- var playProtocolRegistryVersions = (Map <ProtocolVersion , StateRegistry .PacketRegistry .ProtocolRegistry >) VERSIONS_FIELD .get (playRegistry );
149+ var playProtocolRegistryVersions =
150+ (Map <ProtocolVersion , StateRegistry .PacketRegistry .ProtocolRegistry >) VERSIONS_GETTER .invokeExact (playRegistry );
137151 Map <ProtocolVersion , StateRegistry .PacketRegistry .ProtocolRegistry > versions = new EnumMap <>(ProtocolVersion .class );
138152 for (ProtocolVersion version : ProtocolVersion .values ()) {
139153 if (!version .isLegacy () && !version .isUnknown ()) {
@@ -142,10 +156,10 @@ private static void overlayRegistry(StateRegistry stateRegistry,
142156
143157 versionField .set (protoRegistry , version );
144158
145- var playPacketIDToSupplier = (IntObjectMap <Supplier <? extends MinecraftPacket >>) PACKET_ID_TO_SUPPLIER_FIELD . get (playProtoRegistry );
159+ var playPacketIDToSupplier = (IntObjectMap <Supplier <? extends MinecraftPacket >>) PACKET_ID_TO_SUPPLIER_GETTER . invokeExact (playProtoRegistry );
146160 PACKET_ID_TO_SUPPLIER_FIELD .set (protoRegistry , new OverlayIntObjectMap <>(playPacketIDToSupplier , new IntObjectHashMap <>(16 , 0.5F )));
147161
148- var playPacketClassToID = (Object2IntMap <Class <? extends MinecraftPacket >>) PACKET_CLASS_TO_ID_FIELD . get (playProtoRegistry );
162+ var playPacketClassToID = (Object2IntMap <Class <? extends MinecraftPacket >>) PACKET_CLASS_TO_ID_GETTER . invokeExact (playProtoRegistry );
149163 Object2IntMap <Class <? extends MinecraftPacket >> packetClassToID = new Object2IntOpenHashMap <>(16 , 0.5F );
150164 packetClassToID .defaultReturnValue (playPacketClassToID .defaultReturnValue ());
151165 PACKET_CLASS_TO_ID_FIELD .set (protoRegistry , new OverlayObject2IntMap <>(playPacketClassToID , packetClassToID ));
@@ -448,7 +462,27 @@ public static void register(StateRegistry stateRegistry,
448462 public static void register (StateRegistry .PacketRegistry registry ,
449463 Class <?> packetClass , Supplier <?> packetSupplier , StateRegistry .PacketMapping ... mappings ) {
450464 try {
465+ var versions = (Map <ProtocolVersion , StateRegistry .PacketRegistry .ProtocolRegistry >) VERSIONS_GETTER .invokeExact (registry );
466+ List <OverlayMap <?, ?>> overlayMaps = versions .values ().stream ().flatMap (protocolRegistry -> {
467+ try {
468+ var idToSupplier = (IntObjectMap <Supplier <? extends MinecraftPacket >>) PACKET_ID_TO_SUPPLIER_GETTER .invokeExact (protocolRegistry );
469+ var classToId = (Object2IntMap <Class <? extends MinecraftPacket >>) PACKET_CLASS_TO_ID_GETTER .invokeExact (protocolRegistry );
470+ if (idToSupplier instanceof OverlayMap <?, ?> && classToId instanceof OverlayMap <?, ?>) {
471+ return Stream .of (
472+ (OverlayMap <?, ?>) idToSupplier ,
473+ (OverlayMap <?, ?>) classToId
474+ );
475+ } else {
476+ return Stream .empty ();
477+ }
478+ } catch (Throwable e ) {
479+ throw new ReflectionException (e );
480+ }
481+ }).collect (Collectors .toList ());
482+
483+ overlayMaps .forEach (overlayMap -> overlayMap .setOverride (true ));
451484 REGISTER_METHOD .invokeExact (registry , packetClass , packetSupplier , mappings );
485+ overlayMaps .forEach (overlayMap -> overlayMap .setOverride (false ));
452486 } catch (Throwable e ) {
453487 throw new ReflectionException (e );
454488 }
0 commit comments