Skip to content

Commit 77a6e21

Browse files
committed
1 parent e3abe79 commit 77a6e21

File tree

9 files changed

+276
-107
lines changed

9 files changed

+276
-107
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
import bwapi.BWClient;
12
import bwapi.DefaultBWListener;
23

34
public class SittingDuck extends DefaultBWListener {
5+
public static void main(String[] args) {
6+
new BWClient(new SittingDuck()).startGame();
7+
}
48
}

it/openbw/BWAPILauncher

2.42 MB
Binary file not shown.

it/sc-docker-support/java.dockerfile

Lines changed: 0 additions & 17 deletions
This file was deleted.

pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@
108108
</reporting>
109109

110110
<dependencies>
111+
<dependency>
112+
<groupId>no.fiken.oss.junixsocket</groupId>
113+
<artifactId>junixsocket-common</artifactId>
114+
<version>1.0.2</version>
115+
</dependency>
116+
<dependency>
117+
<groupId>no.fiken.oss.junixsocket</groupId>
118+
<artifactId>junixsocket-native-common</artifactId>
119+
<version>1.0.2</version>
120+
</dependency>
121+
111122
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
112123
<dependency>
113124
<groupId>net.java.dev.jna</groupId>

src/main/java/bwapi/BWClient.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package bwapi;
22

3-
import com.sun.jna.platform.win32.Kernel32;
4-
53
import java.util.Objects;
64

75
/**

src/main/java/bwapi/Client.java

Lines changed: 53 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -25,32 +25,20 @@ of this software and associated documentation files (the "Software"), to deal
2525

2626
package 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-
3528
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;
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
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package bwapi;
2+
3+
import java.io.IOException;
4+
5+
/**
6+
* Client - Server connection abstraction
7+
*/
8+
interface ClientConnection {
9+
void disconnect();
10+
11+
WrappedBuffer getGameTable();
12+
13+
WrappedBuffer getSharedMemory(int serverProcID);
14+
15+
void connectSharedLock(int serverProcID) throws IOException;
16+
17+
void waitForServerData() throws IOException;
18+
19+
void submitClientData() throws IOException;
20+
}
21+
22+
class SharedMemoryConnectionException extends RuntimeException {
23+
public SharedMemoryConnectionException(String message, Throwable cause) {
24+
super(message, cause);
25+
}
26+
}
27+
28+
class SharedLockConnectionException extends RuntimeException {
29+
public SharedLockConnectionException(String message, Throwable cause) {
30+
super(message, cause);
31+
}
32+
}

0 commit comments

Comments
 (0)