1010
1111import java .io .InputStream ;
1212import java .lang .reflect .Field ;
13+ import java .lang .reflect .Method ;
1314import java .lang .reflect .Modifier ;
1415import java .util .*;
1516import java .util .concurrent .ConcurrentHashMap ;
17+ import java .util .concurrent .CopyOnWriteArrayList ;
18+ import java .util .concurrent .Exchanger ;
1619import java .util .function .Function ;
1720
1821/**
@@ -23,7 +26,7 @@ public class PacketFactoryImpl implements PacketFactory {
2326 private final PacketEncoder encoder ;
2427 private final SerializerProvider serializerProvider ;
2528
26- private final Map <Class <?>, PacketGroup > packet2Group = new ConcurrentHashMap <>();
29+ private final Map <Class <?>, List < PacketGroup > > packet2Group = new ConcurrentHashMap <>();
2730 private final Map <String , PacketGroup > groups = new ConcurrentHashMap <>();
2831
2932 public PacketFactoryImpl (PacketEncoder encoder , SerializerProvider serializerProvider ) {
@@ -54,17 +57,23 @@ public <PacketType> void addPacket(Class<PacketType> packetClass) {
5457 public <PacketType > void addPacket (Class <PacketType > packetClass , PacketReader <PacketType > reader , PacketWriter <PacketType > writer ) {
5558 Packet annotation = packetClass .getAnnotation (Packet .class );
5659 if (annotation == null ) throw new IllegalArgumentException ("Class " + packetClass .getName () + " is not a valid packet class" );
57- addPacket (packetClass , reader , writer , computePacketID (packetClass ), annotation .group ());
60+ for (String group : annotation .group ())
61+ addPacket (packetClass , reader , writer , computePacketID (packetClass , group ), group );
5862 }
5963
6064 @ Override
6165 public <PacketType > void addPacket (Class <PacketType > packetClass , PacketReader <PacketType > reader , PacketWriter <PacketType > writer , int packetID , String group ) {
6266 if (packetClass == null || reader == null || writer == null ) throw new NullPointerException ();
6367 if (packetID == Packet .INVALID_PACKET ) return ; // invalid packets should be ignored
6468 if (packetID < 0 ) throw new IllegalArgumentException ("Invalid packet ID for packet " + packetClass .getName ());
65- PacketGroup packetGroup = groups .computeIfAbsent (group , PacketGroup ::new );
69+
70+ PacketGroup packetGroup = this .groups .computeIfAbsent (group , PacketGroup ::new );
6671 packetGroup .addPacket (packetID , packetClass , reader , writer ); // throws illegal exception if packet ID already exists
67- packet2Group .put (packetClass , packetGroup );
72+
73+ List <PacketGroup > groupsList = new CopyOnWriteArrayList <>(packet2Group .computeIfAbsent (packetClass , __ -> new ArrayList <>()));
74+ groupsList .add (packetGroup );
75+
76+ packet2Group .put (packetClass , Collections .unmodifiableList (groupsList ));
6877 }
6978
7079 @ Override
@@ -96,15 +105,15 @@ public <PacketType> Optional<Class<PacketType>> getPacketClass(int packetID, Str
96105 }
97106
98107 @ Override
99- public <PacketType > int getPacketID (Class <PacketType > packetClass ) {
100- PacketGroup packetGroup = packet2Group .get (packetClass );
108+ public <PacketType > int getPacketID (Class <PacketType > packetClass , String group ) {
109+ PacketGroup packetGroup = groups .get (group );
101110 if (packetGroup == null ) return -1 ;
102111 return packetGroup .getID (packetClass );
103112 }
104113
105114 @ Override
106- public <PacketType > Optional <String > getPacketGroup (Class <PacketType > packetClass ) {
107- return Optional .ofNullable (packet2Group .get (packetClass )).map (PacketGroup ::getName );
115+ public <PacketType > Optional <String [] > getPacketGroup (Class <PacketType > packetClass ) {
116+ return Optional .ofNullable (packet2Group .get (packetClass )).map (l -> l . stream (). map ( PacketGroup ::getName ). toArray ( String []:: new ) );
108117 }
109118
110119 @ Override
@@ -138,10 +147,10 @@ public <PacketType> PacketType create(int packetID, String group, DataVisitor vi
138147
139148 @ Override
140149 @ SuppressWarnings ("unchecked" )
141- public <PacketType > void write (PacketType packet , DataVisitor visitor ) {
150+ public <PacketType > void write (PacketType packet , String group , DataVisitor visitor ) {
142151 Class <?> packetClass = packet .getClass ();
143- PacketGroup packetGroup = packet2Group .get (packetClass );
144- if (packetGroup == null ) throw new NullPointerException ("Packet " + packetClass . getName () + " is not assigned to any group " );
152+ PacketGroup packetGroup = groups .get (group );
153+ if (packetGroup == null ) throw new NullPointerException ("Group " + group + " is not registered " );
145154
146155 int packetID = packetGroup .getID (packetClass );
147156 if (packetID < 0 ) throw new IllegalArgumentException ("Invalid packet ID: " + packetID );
@@ -156,26 +165,64 @@ public <PacketType> void write(PacketType packet, DataVisitor visitor) {
156165 encoder .encode (visitor , serializerProvider , packetGroup .getName (), new PacketEncoder .Encoded (packetID , packetData ));
157166 }
158167
159- private int computePacketID (Class <?> packetClass ) {
168+ private int computePacketID (Class <?> packetClass , String group ) {
160169 Packet annotation = packetClass .getAnnotation (Packet .class );
161170 if (annotation == null ) throw new IllegalArgumentException ("Class " + packetClass .getName () + " is not a valid packet class" );
171+
162172 if (annotation .id () == Packet .INVALID_PACKET ) return Packet .INVALID_PACKET ;
173+
163174 if (annotation .id () == Packet .DYNAMIC_PACKET ) {
175+
164176 Field [] packetIDFields = Arrays .stream (packetClass .getDeclaredFields ())
165177 .filter (f -> Modifier .isStatic (f .getModifiers ()))
166178 .filter (f -> f .getType ().equals (int .class ))
167179 .filter (f -> f .isAnnotationPresent (PacketID .class ))
168180 .toArray (Field []::new );
169- if (packetIDFields .length == 0 ) throw new IllegalStateException ("Class " + packetClass .getName () + " is missing packet ID field" );
170181 if (packetIDFields .length > 1 ) throw new IllegalStateException ("Class " + packetClass .getName () + " has more than one packet ID field" );
182+ if (packetIDFields .length == 1 ) {
183+ try {
184+ packetIDFields [0 ].setAccessible (true );
185+ return checkPacketID ((int ) packetIDFields [0 ].get (null ));
186+ } catch (Exception exception ) {
187+ throw new RuntimeException (exception );
188+ }
189+ }
190+
191+ Method [] packetIDMethods = Arrays .stream (packetClass .getDeclaredMethods ())
192+ .filter (m -> Modifier .isStatic (m .getModifiers ()))
193+ .filter (m -> m .getReturnType ().equals (int .class ))
194+ .filter (m -> m .getParameterTypes ().length == 0 )
195+ .filter (m -> m .isAnnotationPresent (PacketID .class ))
196+ .toArray (Method []::new );
197+ if (packetIDMethods .length == 0 ) throw new IllegalStateException ("Class " + packetClass .getName () + " is missing packet ID field or method" );
198+ if (packetIDMethods .length > 1 ) throw new IllegalStateException ("Class " + packetClass .getName () + " has more than one packet ID method" );
171199 try {
172- packetIDFields [0 ].setAccessible (true );
173- return (int ) packetIDFields [0 ].get (null );
200+ packetIDMethods [0 ].setAccessible (true );
201+ Exchanger <Integer > idResolver = new Exchanger <>();
202+ Thread .ofVirtual ().start (() -> {
203+ try {
204+ PacketRegistrationContext .threadLocal .set (new PacketRegistrationContext (group ));
205+ idResolver .exchange ((int ) packetIDMethods [0 ].invoke (null ));
206+ } catch (Throwable throwable ) {
207+ try {
208+ idResolver .exchange (Packet .DYNAMIC_PACKET );
209+ } catch (InterruptedException exception ) {
210+ throw new RuntimeException (exception );
211+ }
212+ }
213+ });
214+ int resolved = idResolver .exchange (null );
215+ return checkPacketID (resolved );
174216 } catch (Exception exception ) {
175217 throw new RuntimeException (exception );
176218 }
177219 }
178- return annotation .id ();
220+ return checkPacketID (annotation .id ());
221+ }
222+
223+ private int checkPacketID (int id ) {
224+ if (id > 0 || id == Packet .INVALID_PACKET ) return id ;
225+ throw new RuntimeException ("Invalid packet ID: " + id );
179226 }
180227
181228 static class PacketGroup {
0 commit comments