@@ -43,6 +43,11 @@ public final class Game {
43
43
private static final int REGION_DATA_SIZE = 5000 ;
44
44
45
45
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
+
46
51
private List <Unit > allUnits ;
47
52
private final ClientData clientData ;
48
53
@@ -146,6 +151,10 @@ private static boolean hasPower(final int x, final int y, final UnitType unitTyp
146
151
*/
147
152
void init () {
148
153
visibleUnits .clear ();
154
+ connectedUnits .clear ();
155
+ lastConnectedUnitsUpdate = -1 ;
156
+ loadedUnits .clear ();
157
+ lastLoadedUnitsUpdate = -1 ;
149
158
150
159
final int forceCount = gameData ().getForceCount ();
151
160
forces = new Force [forceCount ];
@@ -310,6 +319,60 @@ void onFrame(final int frame) {
310
319
getAllUnits ().forEach (u -> u .updatePosition (frame ));
311
320
}
312
321
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
+
313
376
/**
314
377
* Retrieves the set of all teams/forces. Forces are commonly seen in @UMS
315
378
* game types and some others such as @TvB and the team versions of game types.
0 commit comments