Skip to content

Commit 736ff2c

Browse files
committed
Configuration now can not be modified after game starts
1 parent e021d19 commit 736ff2c

File tree

11 files changed

+907
-896
lines changed

11 files changed

+907
-896
lines changed

src/main/java/bwapi/BWClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public void startGame(boolean autoContinue) {
9191
* @param gameConfiguration Settings for playing games with this client.
9292
*/
9393
public void startGame(BWClientConfiguration gameConfiguration) {
94-
gameConfiguration.validate();
94+
gameConfiguration.validateAndLock();
9595
this.configuration = gameConfiguration;
9696
this.performanceMetrics = new PerformanceMetrics(configuration);
9797
botWrapper = new BotWrapper(configuration, eventListener);

src/main/java/bwapi/BWClientConfiguration.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public class BWClientConfiguration {
99
* Set to `true` for more explicit error messages (which might spam the terminal).
1010
*/
1111
public BWClientConfiguration withDebugConnection(boolean value) {
12+
throwIfLocked();
1213
debugConnection = value;
1314
return this;
1415
}
@@ -21,6 +22,7 @@ boolean getDebugConnection() {
2122
* When true, restarts the client loop when a game ends, allowing the client to play multiple games without restarting.
2223
*/
2324
public BWClientConfiguration withAutoContinue(boolean value) {
25+
throwIfLocked();
2426
autoContinue = value;
2527
return this;
2628
}
@@ -38,6 +40,7 @@ boolean getAutoContinue() {
3840
* Asynchronous operation will block until the bot's event handlers are complete.
3941
*/
4042
public BWClientConfiguration withUnlimitedFrameZero(boolean value) {
43+
throwIfLocked();
4144
unlimitedFrameZero = value;
4245
return this;
4346
}
@@ -53,6 +56,7 @@ boolean getUnlimitedFrameZero() {
5356
* Real-time human play typically uses the "fastest" game speed, which has 42.86ms (42,860ns) between frames.
5457
*/
5558
public BWClientConfiguration withMaxFrameDurationMs(int value) {
59+
throwIfLocked();
5660
maxFrameDurationMs = value;
5761
return this;
5862
}
@@ -73,6 +77,7 @@ int getMaxFrameDurationMs() {
7377
* issuing commands later than intended, and a marginally larger memory footprint.
7478
*/
7579
public BWClientConfiguration withAsync(boolean value) {
80+
throwIfLocked();
7681
async = value;
7782
return this;
7883
}
@@ -86,6 +91,7 @@ boolean getAsync() {
8691
* Each frame buffered adds about 33 megabytes to JBWAPI's memory footprint.
8792
*/
8893
public BWClientConfiguration withAsyncFrameBufferCapacity(int size) {
94+
throwIfLocked();
8995
asyncFrameBufferCapacity = size;
9096
return this;
9197
}
@@ -102,6 +108,7 @@ int getAsyncFrameBufferCapacity() {
102108
* the non-thread-safe switc from shared memory reads to frame buffer reads.
103109
*/
104110
public BWClientConfiguration withAsyncUnsafe(boolean value) {
111+
throwIfLocked();
105112
asyncUnsafe = value;
106113
return this;
107114
}
@@ -114,6 +121,7 @@ boolean getAsyncUnsafe() {
114121
* Toggles verbose logging, particularly of synchronization steps.
115122
*/
116123
public BWClientConfiguration withLogVerbosely(boolean value) {
124+
throwIfLocked();
117125
logVerbosely = value;
118126
return this;
119127
}
@@ -125,7 +133,7 @@ boolean getLogVerbosely() {
125133
/**
126134
* Checks that the configuration is in a valid state. Throws an IllegalArgumentException if it isn't.
127135
*/
128-
void validate() {
136+
void validateAndLock() {
129137
if (asyncUnsafe && ! async) {
130138
throw new IllegalArgumentException("asyncUnsafe mode needs async mode.");
131139
}
@@ -135,6 +143,14 @@ void validate() {
135143
if (async && asyncFrameBufferCapacity < 1) {
136144
throw new IllegalArgumentException("asyncFrameBufferCapacity needs to be a positive number (There needs to be at least one frame buffer).");
137145
}
146+
locked = true;
147+
}
148+
private boolean locked = false;
149+
150+
void throwIfLocked() {
151+
if (locked) {
152+
throw new RuntimeException("Configuration can not be modified after the game has started");
153+
}
138154
}
139155

140156
void log(String value) {

src/main/java/bwapi/BotWrapper.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ void startNewGame(ByteBuffer liveData, PerformanceMetrics performanceMetrics) {
3636
}
3737
this.performanceMetrics = performanceMetrics;
3838
botGame = new Game();
39-
botGame.clientData().setBuffer(liveData);
39+
botGame.botClientData().setBuffer(liveData);
4040
liveClientData.setBuffer(liveData);
4141
this.liveData = liveData;
4242
botThread = null;
@@ -76,7 +76,7 @@ void onFrame() {
7676
if (configuration.getAsync()) {
7777
configuration.log("Main: onFrame asynchronous start");
7878
long startNanos = System.nanoTime();
79-
long endNanos = startNanos + configuration.getMaxFrameDurationMs() * 1000000;
79+
long endNanos = startNanos + (long) configuration.getMaxFrameDurationMs() * 1000000;
8080
if (botThread == null) {
8181
configuration.log("Main: Starting bot thread");
8282
botThread = createBotThread();
@@ -94,7 +94,7 @@ void onFrame() {
9494
try {
9595
if (frameBuffer.empty()) {
9696
configuration.log("Main: Putting bot on live data");
97-
botGame.clientData().setBuffer(liveData);
97+
botGame.botClientData().setBuffer(liveData);
9898
setUnsafeReadReady(true);
9999
} else {
100100
setUnsafeReadReady(false);
@@ -125,7 +125,7 @@ void onFrame() {
125125
// so there's no guarantee of safety here.
126126
if (configuration.getAsyncUnsafe() && frameBuffer.size() == 1) {
127127
configuration.log("Main: Weaning bot off live data");
128-
botGame.clientData().setBuffer(frameBuffer.peek());
128+
botGame.botClientData().setBuffer(frameBuffer.peek());
129129
}
130130

131131
// Make bot exceptions fall through to the main thread.
@@ -209,7 +209,7 @@ private Thread createBotThread() {
209209
// TODO: Maybe we should point it at live data from here?
210210
} else {
211211
configuration.log("Bot: Peeking next frame from buffer");
212-
botGame.clientData().setBuffer(frameBuffer.peek());
212+
botGame.botClientData().setBuffer(frameBuffer.peek());
213213
}
214214

215215
configuration.log("Bot: Handling events on frame #" + botGame.getFrameCount());
@@ -235,22 +235,22 @@ private Thread createBotThread() {
235235
}
236236

237237
private void handleEvents() {
238-
ClientData.GameData gameData = botGame.clientData().gameData();
238+
ClientData.GameData botGameData = botGame.botClientData().gameData();
239239

240240
// Populate gameOver before invoking event handlers (in case the bot throws)
241-
for (int i = 0; i < gameData.getEventCount(); i++) {
242-
gameOver = gameOver || gameData.getEvents(i).getType() == EventType.MatchEnd;
241+
for (int i = 0; i < botGameData.getEventCount(); i++) {
242+
gameOver = gameOver || botGameData.getEvents(i).getType() == EventType.MatchEnd;
243243
}
244244

245245
if (configuration.getAsync()) {
246246
performanceMetrics.getFramesBehind().record(Math.max(1, frameBuffer.framesBuffered()) - 1);
247247
}
248248

249249
performanceMetrics.getBotResponse().timeIf(
250-
! gameOver && (gameData.getFrameCount() > 0 || ! configuration.getUnlimitedFrameZero()),
250+
! gameOver && (botGameData.getFrameCount() > 0 || ! configuration.getUnlimitedFrameZero()),
251251
() -> {
252-
for (int i = 0; i < gameData.getEventCount(); i++) {
253-
EventHandler.operation(eventListener, botGame, gameData.getEvents(i));
252+
for (int i = 0; i < botGameData.getEventCount(); i++) {
253+
EventHandler.operation(eventListener, botGame, botGameData.getEvents(i));
254254
}
255255
});
256256
}

0 commit comments

Comments
 (0)