33import java .io .IOException ;
44import java .net .http .WebSocket ;
55import java .util .HashMap ;
6+ import java .util .UUID ;
67import java .util .concurrent .CountDownLatch ;
78
8- import org .codegame .client .Api .GameInfo ;
9+ import com .google .gson .annotations .SerializedName ;
10+ import com .google .gson .reflect .TypeToken ;
911
1012public class GameSocket {
13+ @ FunctionalInterface
14+ public interface EventCallback <T > {
15+ void cb (T data );
16+ }
17+
18+ private class Callbacks <T > {
19+ Class <T > type ;
20+ HashMap <String , EventCallback <T >> callbacks ;
21+
22+ Callbacks (Class <T > type ) {
23+ this .type = type ;
24+ this .callbacks = new HashMap <>();
25+ }
26+ }
27+
1128 private Api api ;
1229 private Session session = new Session ();
1330 private WebSocket websocket ;
1431 private HashMap <String , String > usernameCache = new HashMap <>();
32+ @ SuppressWarnings ("rawtypes" )
33+ private HashMap <String , Callbacks > eventListeners = new HashMap <>();
1534 private CountDownLatch exitEvent = new CountDownLatch (1 );
1635
1736 public GameSocket (String url ) {
@@ -77,7 +96,7 @@ public void connect(String gameId) throws IOException {
7796 usernameCache = api .fetchPlayers (gameId );
7897 }
7998
80- public void block () {
99+ public void listen () {
81100 try {
82101 exitEvent .await ();
83102 } catch (InterruptedException e ) {
@@ -87,7 +106,67 @@ public void block() {
87106
88107 public void close () {
89108 websocket .sendClose (WebSocket .NORMAL_CLOSURE , "Normal closure." );
90- block ();
109+ listen ();
110+ }
111+
112+ public static class Event <T > {
113+ @ SerializedName ("name" )
114+ String name ;
115+ @ SerializedName ("data" )
116+ T data ;
117+
118+ public Event () {
119+ }
120+
121+ public Event (String name , T data ) {
122+ this .name = name ;
123+ this .data = data ;
124+ }
125+ }
126+
127+ @ SuppressWarnings ("unchecked" )
128+ public <T > String on (String eventName , Class <T > type , EventCallback <T > callback ) {
129+ if (!eventListeners .containsKey (eventName ))
130+ eventListeners .put (eventName , new Callbacks <>(type ));
131+
132+ var id = UUID .randomUUID ().toString ();
133+ var callbacks = (Callbacks <T >) eventListeners .get (eventName );
134+ if (!callbacks .type .getTypeName ().equals (type .getTypeName ()))
135+ throw new IllegalArgumentException ("Wrong event listener type." );
136+ callbacks .type = type ;
137+ callbacks .callbacks .put (id , callback );
138+ return id ;
139+ }
140+
141+ @ SuppressWarnings ("unchecked" )
142+ public <T > String once (String eventName , Class <T > type , EventCallback <T > callback ) {
143+ if (!eventListeners .containsKey (eventName ))
144+ eventListeners .put (eventName , new Callbacks <>(type ));
145+
146+ var id = UUID .randomUUID ().toString ();
147+ var callbacks = (Callbacks <T >) eventListeners .get (eventName );
148+ if (!callbacks .type .getTypeName ().equals (type .getTypeName ()))
149+ throw new IllegalArgumentException ("Wrong event listener type." );
150+ callbacks .type = type ;
151+ callbacks .callbacks .put (id , (data ) -> {
152+ callback .cb (data );
153+ removeCallback (eventName , id );
154+ });
155+ return id ;
156+ }
157+
158+ public <T > void send (String commandName , T data ) {
159+ if (websocket == null || session .getPlayerId () == "" )
160+ throw new IllegalStateException ("The socket is not connected to a player." );
161+ Event <T > e = new Event <>(commandName , data );
162+ var json = Api .json .toJson (e , TypeToken .getParameterized (Event .class , data .getClass ()).getType ());
163+ websocket .sendText (json , true ).join ();
164+ }
165+
166+ public void removeCallback (String eventName , String id ) {
167+ if (!eventListeners .containsKey (eventName ))
168+ return ;
169+ eventListeners .get (eventName ).callbacks .remove (id );
91170 }
92171
93172 public Api getApi () {
@@ -98,8 +177,21 @@ public Session getSession() {
98177 return session ;
99178 }
100179
180+ private class EventMessage {
181+ @ SerializedName ("name" )
182+ String name ;
183+ }
184+
185+ @ SuppressWarnings ({ "unchecked" , "rawtypes" })
101186 private void onMessage (String message ) {
102- System .out .println ("Received: " + message );
187+ var emptyEvent = Api .json .fromJson (message , EventMessage .class );
188+ if (!eventListeners .containsKey (emptyEvent .name ))
189+ return ;
190+ var callbacks = eventListeners .get (emptyEvent .name );
191+ Event event = Api .json .fromJson (message , TypeToken .getParameterized (Event .class , callbacks .type ).getType ());
192+ for (EventCallback cb : ((HashMap <String , EventCallback >) callbacks .callbacks ).values ()) {
193+ cb .cb (event .data );
194+ }
103195 }
104196
105197 private void onClose () {
0 commit comments