@@ -25,32 +25,20 @@ of this software and associated documentation files (the "Software"), to deal
25
25
26
26
package bwapi ;
27
27
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
-
35
28
class 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 ;
43
29
private static final int SUPPORTED_BWAPI_VERSION = 10003 ;
44
30
45
31
private ClientData clientData ;
46
32
private BWClient bwClient ;
47
33
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 ;
51
37
52
38
Client (BWClient bwClient ) {
53
39
this .bwClient = bwClient ;
40
+ boolean windowsOs = System .getProperty ("os.name" ).toLowerCase ().contains ("win" );
41
+ clientConnector = windowsOs ? new ClientConnectionW32 () : new ClientConnectionPosix ();
54
42
}
55
43
56
44
/**
@@ -59,14 +47,15 @@ interface MappingKernel extends Kernel32 {
59
47
Client (final WrappedBuffer buffer ) {
60
48
clientData = new ClientData ();
61
49
clientData .setBuffer (buffer );
50
+ clientConnector = null ;
62
51
}
63
52
64
53
ClientData liveClientData () {
65
54
return clientData ;
66
55
}
67
56
68
57
WrappedBuffer mapFile () {
69
- return mapFileHandle ;
58
+ return mapShm ;
70
59
}
71
60
72
61
boolean isConnected () {
@@ -87,18 +76,9 @@ private void disconnect() {
87
76
if (!connected ) {
88
77
return ;
89
78
}
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 ;
102
82
clientData = null ;
103
83
connected = false ;
104
84
}
@@ -114,18 +94,16 @@ boolean connect() {
114
94
115
95
// Expose the BWAPI list of games from shared memory via a ByteBuffer
116
96
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 ) {
122
100
System .err .println ("Game table mapping not found." );
123
101
return false ;
124
102
}
125
103
126
104
GameTable gameTable ;
127
105
try {
128
- gameTable = new GameTable (gameTableFileHandle );
106
+ gameTable = new GameTable (this . gameTableShm );
129
107
} catch (Exception e ) {
130
108
System .err .println ("Unable to map Game table." );
131
109
if (bwClient .getConfiguration ().getDebugConnection ()) {
@@ -134,13 +112,13 @@ boolean connect() {
134
112
return false ;
135
113
}
136
114
137
- int latest = 0 ;
115
+ int oldest = Integer . MAX_VALUE ;
138
116
for (int i = 0 ; i < GameTable .MAX_GAME_INSTANCES ; i ++) {
139
117
GameInstance gameInstance = gameTable .gameInstances [i ];
140
118
System .out .println (i + " | " + gameInstance .serverProcessID + " | " + (gameInstance .isConnected ? 1 : 0 ) + " | " + gameInstance .lastKeepAliveTime );
141
119
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 ;
144
122
gameTableIndex = i ;
145
123
}
146
124
}
@@ -155,46 +133,40 @@ boolean connect() {
155
133
return false ;
156
134
}
157
135
158
- final String sharedMemoryName = "Local\\ bwapi_shared_memory_" + serverProcID ;
159
- final String communicationPipe = "\\ \\ .\\ pipe\\ bwapi_pipe_" + serverProcID ;
160
136
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 ());
164
141
if (bwClient .getConfiguration ().getDebugConnection ()) {
165
142
e .printStackTrace ();
166
143
}
167
- gameTableFileHandle = null ;
144
+ this . gameTableShm = null ;
168
145
return false ;
169
146
}
170
- System .out .println ("Connected" );
171
-
172
- // Expose the raw game data from shared memory via a ByteBuffer
173
147
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 );
178
150
} catch (Exception e ) {
179
- System .err .println ("Unable to open shared memory mapping: " + sharedMemoryName );
151
+ System .err .println ("Unable to map game data." );
180
152
if (bwClient .getConfiguration ().getDebugConnection ()) {
181
153
e .printStackTrace ();
182
154
}
183
- pipeObjectHandle = null ;
184
- gameTableFileHandle = null ;
185
155
return false ;
186
156
}
157
+
158
+
187
159
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 ());
193
163
if (bwClient .getConfiguration ().getDebugConnection ()) {
194
164
e .printStackTrace ();
195
165
}
166
+ this .gameTableShm = null ;
196
167
return false ;
197
168
}
169
+ System .out .println ("Connected" );
198
170
199
171
if (SUPPORTED_BWAPI_VERSION != clientData .gameData ().getClient_version ()) {
200
172
System .err .println ("Error: Client and Server are not compatible!" );
@@ -204,18 +176,16 @@ boolean connect() {
204
176
sleep (2000 );
205
177
return false ;
206
178
}
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 ();
218
186
}
187
+ disconnect ();
188
+ return false ;
219
189
}
220
190
221
191
System .out .println ("Connection successful" );
@@ -233,16 +203,13 @@ void sendFrameReceiveFrame() {
233
203
metrics .getCommunicationSendToSent ().startTiming ();
234
204
}
235
205
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 ) {
240
208
System .err .println ("failed, disconnecting" );
241
209
if (bwClient .getConfiguration ().getDebugConnection ()) {
242
210
e .printStackTrace ();
243
211
}
244
212
disconnect ();
245
- return ;
246
213
}
247
214
metrics .getCommunicationSendToSent ().stopTiming ();
248
215
metrics .getFrameDurationReceiveToSent ().stopTiming ();
@@ -256,19 +223,16 @@ void sendFrameReceiveFrame() {
256
223
if (bwClient .doTime ()) {
257
224
metrics .getCommunicationListenToReceive ().startTiming ();
258
225
}
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 ();
271
233
}
234
+ disconnect ();
235
+ return ;
272
236
}
273
237
274
238
metrics .getCommunicationListenToReceive ().stopTiming ();
@@ -288,6 +252,7 @@ private void sleep(final int millis) {
288
252
try {
289
253
Thread .sleep (millis );
290
254
} catch (Exception ignored ) {
255
+ // Not relevant
291
256
}
292
257
}
293
258
}
0 commit comments