Skip to content

Commit 04db785

Browse files
committed
Disabled latency compensation in async mode.
1 parent 00b1266 commit 04db785

File tree

4 files changed

+45
-6
lines changed

4 files changed

+45
-6
lines changed

src/main/java/bwapi/BWClientConfiguration.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ int getMaxFrameDurationMs() {
7575
* returns control to StarCraft, allowing the game to proceed while the bot continues to step in the background. This increases the likelihood of meeting
7676
* real-time performance requirements, while not fully guaranteeing it (subject to the whims of the JVM thread scheduler), at a cost of the bot possibly
7777
* issuing commands later than intended, and a marginally larger memory footprint.
78+
*
79+
* Asynchronous mode is not compatible with latency compensation. Enabling asynchronous mode automatically disables latency compensation.
7880
*/
7981
public BWClientConfiguration withAsync(boolean value) {
8082
throwIfLocked();

src/main/java/bwapi/BotWrapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void startNewGame(WrappedBuffer liveData, PerformanceMetrics performanceMetrics)
3636
}
3737
this.performanceMetrics = performanceMetrics;
3838
botGame = new Game();
39+
botGame.setConfiguration(configuration);
3940
botGame.botClientData().setBuffer(liveData);
4041
liveClientData.setBuffer(liveData);
4142
this.liveData = liveData;

src/main/java/bwapi/Game.java

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public final class Game {
9595
// USER DEFINED
9696

9797
private Text.Size textSize = Text.Size.Default;
98+
private BWClientConfiguration configuration = new BWClientConfiguration();
9899
private boolean latcom = true;
99100

100101
final SideEffectQueue sideEffects = new SideEffectQueue();
@@ -103,6 +104,10 @@ public final class Game {
103104
clientData = new ClientData();
104105
}
105106

107+
void setConfiguration(BWClientConfiguration configuration) {
108+
this.configuration = configuration;
109+
}
110+
106111
ClientData botClientData() {
107112
return clientData;
108113
}
@@ -270,7 +275,7 @@ void init() {
270275
observers = playerSet.stream().filter(p -> !p.equals(self()) && p.isObserver())
271276
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
272277
}
273-
setLatCom(true);
278+
setLatCom(!configuration.getAsync());
274279
}
275280

276281
void unitCreate(final int id) {
@@ -2171,6 +2176,9 @@ final public boolean isLatComEnabled() {
21712176
* @see #isLatComEnabled
21722177
*/
21732178
public void setLatCom(final boolean isEnabled) {
2179+
if (isEnabled && configuration.getAsync()) {
2180+
throw new IllegalStateException("Latency compensation is not compatible with JBWAPI asynchronous mode.");
2181+
}
21742182
//update shared memory
21752183
gameData().setHasLatCom(isEnabled);
21762184
//update internal memory
@@ -2654,35 +2662,49 @@ public int getRandomSeed() {
26542662
* Convenience method for adding a unit command from raw arguments.
26552663
*/
26562664
void addUnitCommand(final int type, final int unit, final int target, final int x, final int y, final int extra) {
2657-
sideEffects.enqueue(SideEffect.addUnitCommand(type, unit, target, x, y, extra));
2665+
enqueueOrDo(SideEffect.addUnitCommand(type, unit, target, x, y, extra));
26582666
}
26592667

26602668
/**
26612669
* Convenience method for adding a game command from raw arguments.
26622670
*/
26632671
void addCommand(final CommandType type, final int value1, final int value2) {
2664-
sideEffects.enqueue(SideEffect.addCommand(type, value1, value2));
2672+
enqueueOrDo(SideEffect.addCommand(type, value1, value2));
26652673
}
26662674

26672675
/**
26682676
* Convenience method for adding a game command from raw arguments.
26692677
*/
26702678
void addCommand(final CommandType type, final String value1, final int value2) {
2671-
sideEffects.enqueue(SideEffect.addCommand(type, value1, value2));
2679+
enqueueOrDo(SideEffect.addCommand(type, value1, value2));
26722680
}
26732681

26742682
/**
26752683
* Convenience method for adding a shape from raw arguments.
26762684
*/
26772685
void addShape(final ShapeType type, final CoordinateType coordType, final int x1, final int y1, final int x2, final int y2, final int extra1, final int extra2, final int color, final boolean isSolid) {
2678-
sideEffects.enqueue(SideEffect.addShape(type, coordType, x1, y1, x2, y2, extra1, extra2, color, isSolid));
2686+
enqueueOrDo(SideEffect.addShape(type, coordType, x1, y1, x2, y2, extra1, extra2, color, isSolid));
26792687
}
26802688

26812689
/**
26822690
* Convenience method for adding a shape from raw arguments.
26832691
*/
26842692
void addShape(final ShapeType type, final CoordinateType coordType, final int x1, final int y1, final int x2, final int y2, final String text, final int extra2, final int color, final boolean isSolid) {
2685-
sideEffects.enqueue(SideEffect.addShape(type, coordType, x1, y1, x2, y2, text, extra2, color, isSolid));
2693+
enqueueOrDo(SideEffect.addShape(type, coordType, x1, y1, x2, y2, text, extra2, color, isSolid));
2694+
}
2695+
2696+
/**
2697+
* Applies a side effect, either immediately (if operating synchronously)
2698+
* or by enqueuing it for later execution (if operating asynchronously).
2699+
*
2700+
* @param sideEffect
2701+
*/
2702+
void enqueueOrDo(SideEffect sideEffect) {
2703+
if (configuration.getAsync()) {
2704+
sideEffects.enqueue(sideEffect);
2705+
} else {
2706+
sideEffect.apply(gameData());
2707+
}
26862708
}
26872709

26882710
void setAllUnits(List<Unit> units) {

src/test/java/bwapi/SynchronizationTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,18 @@ public void async_MeasurePerformance_IntentionallyBlocking() {
284284
});
285285
environment.runGame(3);
286286
}
287+
288+
@Test
289+
public void async_DisablesLatencyCompensation() {
290+
SynchronizationEnvironment environmentSync = new SynchronizationEnvironment();
291+
environmentSync.configuration.withAsync(false);
292+
environmentSync.onFrame(1, () -> { assertTrue(environmentSync.bwClient.getGame().isLatComEnabled()); });
293+
environmentSync.runGame(2);
294+
295+
SynchronizationEnvironment environmentAsync = new SynchronizationEnvironment();
296+
environmentAsync.configuration.withAsync(true).withAsyncFrameBufferCapacity(2);
297+
environmentAsync.onFrame(1, () -> { assertFalse(environmentAsync.bwClient.getGame().isLatComEnabled()); });
298+
environmentAsync.onFrame(2, () -> { assertThrows(IllegalStateException.class, () -> environmentAsync.bwClient.getGame().setLatCom(true)); });
299+
environmentAsync.runGame(3);
300+
}
287301
}

0 commit comments

Comments
 (0)