Skip to content

Commit e3e6795

Browse files
committed
cache calls to connected&loaded units per frame
1 parent d21d42e commit e3e6795

File tree

2 files changed

+66
-9
lines changed

2 files changed

+66
-9
lines changed

src/main/java/bwapi/Game.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public final class Game {
4343
private static final int REGION_DATA_SIZE = 5000;
4444

4545
private final Set<Integer> visibleUnits = new HashSet<>();
46+
private final Map<Unit, List<Unit>> connectedUnits = new HashMap<>();
47+
private int lastConnectedUnitsUpdate = -1;
48+
private final Map<Unit, List<Unit>> loadedUnits = new HashMap<>();
49+
private int lastLoadedUnitsUpdate = -1;
50+
4651
private List<Unit> allUnits;
4752
private final ClientData clientData;
4853

@@ -146,6 +151,10 @@ private static boolean hasPower(final int x, final int y, final UnitType unitTyp
146151
*/
147152
void init() {
148153
visibleUnits.clear();
154+
connectedUnits.clear();
155+
lastConnectedUnitsUpdate = -1;
156+
loadedUnits.clear();
157+
lastLoadedUnitsUpdate = -1;
149158

150159
final int forceCount = gameData().getForceCount();
151160
forces = new Force[forceCount];
@@ -310,6 +319,60 @@ void onFrame(final int frame) {
310319
getAllUnits().forEach(u -> u.updatePosition(frame));
311320
}
312321

322+
/**
323+
* Lazily update connectedUnits. Only users of the calls pay for it, and only
324+
* pay once per frame.
325+
* Avoids previous O(n^2) implementation which would be costly for
326+
* lategame carrier fights
327+
*/
328+
public List<Unit> getConnected(final Unit unit) {
329+
final int frame = getFrameCount();
330+
if (lastConnectedUnitsUpdate < frame) {
331+
connectedUnits.clear();
332+
for (final Unit u : getAllUnits()) {
333+
Unit owner = u.getCarrier();
334+
if (owner == null) {
335+
owner = u.getHatchery();
336+
}
337+
if (owner != null) {
338+
if (!connectedUnits.containsKey(owner)) {
339+
connectedUnits.put(owner, new ArrayList<>());
340+
}
341+
connectedUnits.get(owner).add(u);
342+
}
343+
}
344+
lastConnectedUnitsUpdate = frame;
345+
}
346+
if (!connectedUnits.containsKey(unit)) {
347+
return Collections.emptyList();
348+
}
349+
return new ArrayList<>(connectedUnits.get(unit));
350+
}
351+
352+
/**
353+
* @see #getConnected
354+
*/
355+
public List<Unit> getLoadedUnits(final Unit unit) {
356+
final int frame = getFrameCount();
357+
if (lastLoadedUnitsUpdate < frame) {
358+
loadedUnits.clear();
359+
for (final Unit u : getAllUnits()) {
360+
final Unit owner = u.getTransport();
361+
if (owner != null) {
362+
if (!loadedUnits.containsKey(owner)) {
363+
loadedUnits.put(owner, new ArrayList<>());
364+
}
365+
loadedUnits.get(owner).add(u);
366+
}
367+
}
368+
lastLoadedUnitsUpdate = frame;
369+
}
370+
if (!loadedUnits.containsKey(unit)) {
371+
return Collections.emptyList();
372+
}
373+
return new ArrayList<>(loadedUnits.get(unit));
374+
}
375+
313376
/**
314377
* Retrieves the set of all teams/forces. Forces are commonly seen in @UMS
315378
* game types and some others such as @TvB and the team versions of game types.

src/main/java/bwapi/Unit.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,9 +1157,7 @@ public List<Unit> getLoadedUnits() {
11571157
if (getType().spaceProvided() < 1) {
11581158
return Collections.emptyList();
11591159
}
1160-
return game.getAllUnits().stream()
1161-
.filter(u -> equals(u.getTransport()))
1162-
.collect(Collectors.toList());
1160+
return game.getLoadedUnits(this);
11631161
}
11641162

11651163
/**
@@ -1199,9 +1197,7 @@ public List<Unit> getInterceptors() {
11991197
if (getType() != Protoss_Carrier && getType() != Hero_Gantrithor) {
12001198
return Collections.emptyList();
12011199
}
1202-
return game.getAllUnits().stream()
1203-
.filter(u -> equals(u.getCarrier()))
1204-
.collect(Collectors.toList());
1200+
return game.getConnected(this);
12051201
}
12061202

12071203
/**
@@ -1229,9 +1225,7 @@ public List<Unit> getLarva() {
12291225
if (!getType().producesLarva()) {
12301226
return Collections.emptyList();
12311227
}
1232-
return game.getAllUnits().stream()
1233-
.filter(u -> equals(u.getHatchery()))
1234-
.collect(Collectors.toList());
1228+
return game.getConnected(this);
12351229
}
12361230

12371231
public List<Unit> getUnitsInRadius(final int radius) {

0 commit comments

Comments
 (0)