@@ -25,32 +25,20 @@ of this software and associated documentation files (the "Software"), to deal
2525
2626package bwapi ;
2727
28- import com .sun .jna .Native ;
29- import com .sun .jna .Pointer ;
30- import com .sun .jna .platform .win32 .Kernel32 ;
31- import com .sun .jna .win32 .W32APIOptions ;
32-
33- import java .io .RandomAccessFile ;
34-
3528class Client {
36- interface MappingKernel extends Kernel32 {
37- MappingKernel INSTANCE = Native .load (MappingKernel .class , W32APIOptions .DEFAULT_OPTIONS );
38-
39- HANDLE OpenFileMapping (int desiredAccess , boolean inherit , String name );
40- }
41-
42- private static final int READ_WRITE = 0x1 | 0x2 | 0x4 ;
4329 private static final int SUPPORTED_BWAPI_VERSION = 10003 ;
4430
4531 private ClientData clientData ;
4632 private BWClient bwClient ;
4733 private boolean connected = false ;
48- private RandomAccessFile pipeObjectHandle = null ;
49- private WrappedBuffer gameTableFileHandle = null ;
50- private WrappedBuffer mapFileHandle = null ;
34+ private WrappedBuffer mapShm = null ;
35+ private WrappedBuffer gameTableShm = null ;
36+ private final ClientConnection clientConnector ;
5137
5238 Client (BWClient bwClient ) {
5339 this .bwClient = bwClient ;
40+ boolean windowsOs = System .getProperty ("os.name" ).toLowerCase ().contains ("win" );
41+ clientConnector = windowsOs ? new ClientConnectionW32 () : new ClientConnectionPosix ();
5442 }
5543
5644 /**
@@ -59,14 +47,15 @@ interface MappingKernel extends Kernel32 {
5947 Client (final WrappedBuffer buffer ) {
6048 clientData = new ClientData ();
6149 clientData .setBuffer (buffer );
50+ clientConnector = null ;
6251 }
6352
6453 ClientData liveClientData () {
6554 return clientData ;
6655 }
6756
6857 WrappedBuffer mapFile () {
69- return mapFileHandle ;
58+ return mapShm ;
7059 }
7160
7261 boolean isConnected () {
@@ -87,18 +76,9 @@ private void disconnect() {
8776 if (!connected ) {
8877 return ;
8978 }
90-
91- if (pipeObjectHandle != null ) {
92- try {
93- pipeObjectHandle .close ();
94- } catch (Exception e ) {
95- e .printStackTrace ();
96- }
97- pipeObjectHandle = null ;
98- }
99-
100- gameTableFileHandle = null ;
101- mapFileHandle = null ;
79+ clientConnector .disconnect ();
80+ mapShm = null ;
81+ gameTableShm = null ;
10282 clientData = null ;
10383 connected = false ;
10484 }
@@ -114,18 +94,16 @@ boolean connect() {
11494
11595 // Expose the BWAPI list of games from shared memory via a ByteBuffer
11696 try {
117- final Pointer gameTableView = Kernel32 .INSTANCE .MapViewOfFile (MappingKernel .INSTANCE
118- .OpenFileMapping (READ_WRITE , false , "Local\\ bwapi_shared_memory_game_list" ), READ_WRITE ,
119- 0 , 0 , GameTable .SIZE );
120- gameTableFileHandle = new WrappedBuffer (gameTableView , GameTable .SIZE );
121- } catch (Exception e ) {
97+ gameTableShm = clientConnector .getGameTable ();
98+ }
99+ catch (Exception e ) {
122100 System .err .println ("Game table mapping not found." );
123101 return false ;
124102 }
125103
126104 GameTable gameTable ;
127105 try {
128- gameTable = new GameTable (gameTableFileHandle );
106+ gameTable = new GameTable (this . gameTableShm );
129107 } catch (Exception e ) {
130108 System .err .println ("Unable to map Game table." );
131109 if (bwClient .getConfiguration ().getDebugConnection ()) {
@@ -134,13 +112,13 @@ boolean connect() {
134112 return false ;
135113 }
136114
137- int latest = 0 ;
115+ int oldest = Integer . MAX_VALUE ;
138116 for (int i = 0 ; i < GameTable .MAX_GAME_INSTANCES ; i ++) {
139117 GameInstance gameInstance = gameTable .gameInstances [i ];
140118 System .out .println (i + " | " + gameInstance .serverProcessID + " | " + (gameInstance .isConnected ? 1 : 0 ) + " | " + gameInstance .lastKeepAliveTime );
141119 if (gameInstance .serverProcessID != 0 && !gameInstance .isConnected ) {
142- if (gameTableIndex == -1 || latest == 0 || gameInstance .lastKeepAliveTime < latest ) {
143- latest = gameInstance .lastKeepAliveTime ;
120+ if (gameTableIndex == -1 || gameInstance .lastKeepAliveTime < oldest ) {
121+ oldest = gameInstance .lastKeepAliveTime ;
144122 gameTableIndex = i ;
145123 }
146124 }
@@ -155,46 +133,40 @@ boolean connect() {
155133 return false ;
156134 }
157135
158- final String sharedMemoryName = "Local\\ bwapi_shared_memory_" + serverProcID ;
159- final String communicationPipe = "\\ \\ .\\ pipe\\ bwapi_pipe_" + serverProcID ;
160136 try {
161- pipeObjectHandle = new RandomAccessFile (communicationPipe , "rw" );
162- } catch (Exception e ) {
163- System .err .println ("Unable to open communications pipe: " + communicationPipe );
137+ mapShm = clientConnector .getSharedMemory (serverProcID );
138+ }
139+ catch (Exception e ) {
140+ System .err .println ("Unable to open shared memory mapping: " + e .getMessage ());
164141 if (bwClient .getConfiguration ().getDebugConnection ()) {
165142 e .printStackTrace ();
166143 }
167- gameTableFileHandle = null ;
144+ this . gameTableShm = null ;
168145 return false ;
169146 }
170- System .out .println ("Connected" );
171-
172- // Expose the raw game data from shared memory via a ByteBuffer
173147 try {
174- final Pointer mapFileView = Kernel32 .INSTANCE .MapViewOfFile (MappingKernel .INSTANCE
175- .OpenFileMapping (READ_WRITE , false , sharedMemoryName ), READ_WRITE ,
176- 0 , 0 , ClientData .GameData .SIZE );
177- mapFileHandle = new WrappedBuffer (mapFileView , ClientData .GameData .SIZE );
148+ clientData = new ClientData ();
149+ clientData .setBuffer (mapShm );
178150 } catch (Exception e ) {
179- System .err .println ("Unable to open shared memory mapping: " + sharedMemoryName );
151+ System .err .println ("Unable to map game data." );
180152 if (bwClient .getConfiguration ().getDebugConnection ()) {
181153 e .printStackTrace ();
182154 }
183- pipeObjectHandle = null ;
184- gameTableFileHandle = null ;
185155 return false ;
186156 }
157+
158+
187159 try {
188- clientData = new ClientData ();
189- clientData .setBuffer (mapFileHandle );
190- }
191- catch (Exception e ) {
192- System .err .println ("Unable to map game data." );
160+ clientConnector .connectSharedLock (serverProcID );
161+ } catch (Exception e ) {
162+ System .err .println (e .getMessage ());
193163 if (bwClient .getConfiguration ().getDebugConnection ()) {
194164 e .printStackTrace ();
195165 }
166+ this .gameTableShm = null ;
196167 return false ;
197168 }
169+ System .out .println ("Connected" );
198170
199171 if (SUPPORTED_BWAPI_VERSION != clientData .gameData ().getClient_version ()) {
200172 System .err .println ("Error: Client and Server are not compatible!" );
@@ -204,18 +176,16 @@ boolean connect() {
204176 sleep (2000 );
205177 return false ;
206178 }
207- byte code = 1 ;
208- while (code != 2 ) {
209- try {
210- code = pipeObjectHandle .readByte ();
211- } catch (Exception e ) {
212- System .err .println ("Unable to read pipe object." );
213- if (bwClient .getConfiguration ().getDebugConnection ()) {
214- e .printStackTrace ();
215- }
216- disconnect ();
217- return false ;
179+
180+ try {
181+ clientConnector .waitForServerData ();
182+ } catch (Exception e ) {
183+ System .err .println (e .getMessage ());
184+ if (bwClient .getConfiguration ().getDebugConnection ()) {
185+ e .printStackTrace ();
218186 }
187+ disconnect ();
188+ return false ;
219189 }
220190
221191 System .out .println ("Connection successful" );
@@ -233,16 +203,13 @@ void sendFrameReceiveFrame() {
233203 metrics .getCommunicationSendToSent ().startTiming ();
234204 }
235205 try {
236- // 1 is the "frame done" signal to BWAPI
237- pipeObjectHandle .writeByte (1 );
238- }
239- catch (Exception e ) {
206+ clientConnector .submitClientData ();
207+ } catch (Exception e ) {
240208 System .err .println ("failed, disconnecting" );
241209 if (bwClient .getConfiguration ().getDebugConnection ()) {
242210 e .printStackTrace ();
243211 }
244212 disconnect ();
245- return ;
246213 }
247214 metrics .getCommunicationSendToSent ().stopTiming ();
248215 metrics .getFrameDurationReceiveToSent ().stopTiming ();
@@ -256,19 +223,16 @@ void sendFrameReceiveFrame() {
256223 if (bwClient .doTime ()) {
257224 metrics .getCommunicationListenToReceive ().startTiming ();
258225 }
259- boolean frameReady = false ;
260- while (!frameReady ) {
261- try {
262- // 2 is the "frame ready" signal from BWAPI
263- frameReady = pipeObjectHandle .readByte () == 2 ;
264- } catch (Exception e ) {
265- System .err .println ("failed, disconnecting" );
266- if (bwClient .getConfiguration ().getDebugConnection ()) {
267- e .printStackTrace ();
268- }
269- disconnect ();
270- break ;
226+ try {
227+ clientConnector .waitForServerData ();
228+ }
229+ catch (Exception e ) {
230+ System .err .println ("failed, disconnecting" );
231+ if (bwClient .getConfiguration ().getDebugConnection ()) {
232+ e .printStackTrace ();
271233 }
234+ disconnect ();
235+ return ;
272236 }
273237
274238 metrics .getCommunicationListenToReceive ().stopTiming ();
@@ -288,6 +252,7 @@ private void sleep(final int millis) {
288252 try {
289253 Thread .sleep (millis );
290254 } catch (Exception ignored ) {
255+ // Not relevant
291256 }
292257 }
293258}
0 commit comments