5555
5656import com .simsilica .event .EventBus ;
5757import com .simsilica .sim .GameSystemManager ;
58+ import com .simsilica .sim .SimTime ;
5859
5960import example .net .GameSession ;
6061import example .net .GameSessionListener ;
62+ import example .sim .Body ;
63+ import example .sim .PhysicsListener ;
6164import example .sim .ShipDriver ;
6265import example .sim .SimplePhysics ;
6366
@@ -82,6 +85,8 @@ public class GameSessionHostedService extends AbstractHostedConnectionService {
8285 private AccountObserver accountObserver = new AccountObserver ();
8386
8487 private List <GameSessionImpl > players = new CopyOnWriteArrayList <>();
88+ // FIXME: remove array when we get rid of the naive listener
89+ private volatile GameSessionImpl [] playersArray = null ;
8590
8691 public GameSessionHostedService ( GameSystemManager gameSystems ) {
8792
@@ -118,6 +123,7 @@ public void start() {
118123 if ( physics == null ) {
119124 throw new RuntimeException ("GameSessionHostedService requires a SimplePhysics system." );
120125 }
126+ physics .addPhysicsListener (new NaivePhysicsSender ());
121127 }
122128
123129 @ Override
@@ -131,8 +137,13 @@ public void startHostingOnConnection( HostedConnection conn ) {
131137 // Expose the session as an RMI resource to the client
132138 RmiRegistry rmi = rmiService .getRmiRegistry (conn );
133139 rmi .share (session , GameSession .class );
134-
135- players .add (session );
140+
141+ // FIXME: remove sync when we get rid of the naive listener
142+ synchronized ( players ) {
143+ players .add (session );
144+ playersArray = null ;
145+ }
146+ session .initialize ();
136147
137148 // Notify all of our sessions
138149 for ( GameSessionImpl player : players ) {
@@ -150,7 +161,11 @@ public void stopHostingOnConnection( HostedConnection conn ) {
150161
151162 GameSessionImpl session = getGameSession (conn );
152163 if ( session != null ) {
153- players .remove (session );
164+ // FIXME: remove sync when we get rid of the naive listener
165+ synchronized ( players ) {
166+ players .remove (session );
167+ playersArray = null ;
168+ }
154169
155170 // Notify all of our sessions
156171 for ( GameSessionImpl player : players ) {
@@ -170,6 +185,24 @@ public void stopHostingOnConnection( HostedConnection conn ) {
170185 // when we've stopped hosting our service on it.
171186 }
172187 }
188+
189+ private GameSessionImpl [] getPlayerArray () {
190+ // Copy the reference so we're sure we are returning
191+ // what we null-check.
192+ GameSessionImpl [] result = playersArray ;
193+ if ( result != null ) {
194+ return result ;
195+ }
196+
197+ synchronized (players ) {
198+ // Check again
199+ if ( playersArray == null ) {
200+ playersArray = new GameSessionImpl [players .size ()];
201+ playersArray = players .toArray (playersArray );
202+ }
203+ return playersArray ;
204+ }
205+ }
173206
174207 private class AccountObserver {
175208
@@ -183,6 +216,28 @@ public void onPlayerLoggedOff( AccountEvent event ) {
183216 stopHostingOnConnection (event .getConnection ());
184217 }
185218 }
219+
220+ /**
221+ * A naive implementation of a physics listener that just blasts
222+ * everything out to all of the clients over UDP.
223+ */
224+ private class NaivePhysicsSender implements PhysicsListener {
225+
226+ public void beginFrame ( SimTime time ) {
227+ }
228+
229+ public void updateBody ( Body body ) {
230+ // Lots of garbage created here but it's temporary
231+ Quaternion orientation = body .orientation .toQuaternion ();
232+ Vector3f pos = body .pos .toVector3f ();
233+ for ( GameSessionImpl session : getPlayerArray () ) {
234+ session .updateObject (body .bodyId , orientation , pos );
235+ }
236+ }
237+
238+ public void endFrame ( SimTime time ) {
239+ }
240+ }
186241
187242 /**
188243 * The connection-specific 'host' for the GameSession.
@@ -202,11 +257,38 @@ public GameSessionImpl( HostedConnection conn ) {
202257 this .bodyId = physics .createBody (shipDriver );
203258 }
204259
260+ public void initialize () {
261+ }
262+
205263 public void close () {
206264 // Remove out physics body
207265 physics .removeBody (bodyId );
208266 }
209267
268+ @ Override
269+ public int getPlayerObject () {
270+
271+ // Cheat and tell this player about the other players by
272+ // sending late join messages
273+ // FIXME - this is a big hack because we're using it as the side-effect
274+ // of a remote get.
275+ for ( GameSessionImpl player : players ) {
276+ playerJoined (player );
277+ }
278+
279+ return bodyId ;
280+ }
281+
282+ @ Override
283+ public void move ( Quaternion rotation , Vector3f thrust ) {
284+ if ( log .isTraceEnabled () ) {
285+ log .trace ("move(" + rotation + ", " + thrust + ")" );
286+ }
287+
288+ // Need to forward this to the game world
289+ shipDriver .applyMovementState (rotation , thrust );
290+ }
291+
210292 public void playerJoined ( GameSessionImpl player ) {
211293 getCallback ().playerJoined (player .conn .getId (),
212294 AccountHostedService .getPlayerName (player .conn ),
@@ -219,6 +301,10 @@ public void playerLeft( GameSessionImpl player ) {
219301 player .bodyId );
220302 }
221303
304+ public void updateObject ( int bodyId , Quaternion orientation , Vector3f pos ) {
305+ getCallback ().updateObject (bodyId , orientation , pos );
306+ }
307+
222308 protected GameSessionListener getCallback () {
223309 if ( callback == null ) {
224310 RmiRegistry rmi = rmiService .getRmiRegistry (conn );
@@ -230,15 +316,6 @@ protected GameSessionListener getCallback() {
230316 return callback ;
231317 }
232318
233- @ Override
234- public void move ( Quaternion rotation , Vector3f thrust ) {
235- if ( log .isTraceEnabled () ) {
236- log .trace ("move(" + rotation + ", " + thrust + ")" );
237- }
238-
239- // Need to forward this to the game world
240- shipDriver .applyMovementState (rotation , thrust );
241- }
242319 }
243320}
244321
0 commit comments