@@ -20,23 +20,27 @@ public class Game {
2020 private final GameData gameData ;
2121
2222 // CONSTANT
23- private final Map <Integer , Player > players = new HashMap <>();
24- private final Map <Integer , Region > regions = new HashMap <>();
25- private final Map <Integer , Force > forces = new HashMap <>();
26- private final Map <Integer , Bullet > bullets = new HashMap <>();
23+ private Player [] players ;
24+ private Region [] regions ;
25+ private Force [] forces ;
26+ private Bullet [] bullets ;
27+
28+ private Set <Force > forceSet ;
29+ private Set <Player > playerSet ;
30+ private Set <Region > regionSet ;
2731
2832 private final Set <Unit > staticMinerals = new HashSet <>();
2933 private final Set <Unit > staticGeysers = new HashSet <>();
3034 private final Set <Unit > staticNeutralUnits = new HashSet <>();
3135
3236 // CHANGING
33- private final Map < Integer , Unit > units = new HashMap <>() ;
37+ private Unit [] units ;
3438 private final Set <Integer > visibleUnits = new HashSet <>();
3539
3640 //CACHED
3741 private int randomSeed ;
3842 private int revision ;
39- private boolean debug ;
43+ private boolean debug ;
4044 private Player self ;
4145 private Player enemy ;
4246 private Player neutral ;
@@ -53,6 +57,12 @@ public class Game {
5357
5458 private boolean [][] buildable ;
5559 private boolean [][] walkable ;
60+ private int [][] groundHeight ;
61+
62+ private short [][] mapTileRegionID ;
63+ private short [] mapSplitTilesMiniTileMask ;
64+ private short [] mapSplitTilesRegion1 ;
65+ private short [] mapSplitTilesRegion2 ;
5666
5767 // USER DEFINED
5868 private TextSize textSize = TextSize .Default ;
@@ -63,46 +73,52 @@ public Game(final GameData gameData) {
6373
6474 /*
6575 Call this method in EventHander::OnMatchStart
66- */
67- void reset () {
68- clear ();
69- init ();
70- }
71-
72- private void clear () {
73- players .clear ();
74- regions .clear ();
75- forces .clear ();
76+ */
77+ void init () {
7678 staticMinerals .clear ();
7779 staticGeysers .clear ();
7880 staticNeutralUnits .clear ();
79- units .clear ();
8081 visibleUnits .clear ();
81- bullets .clear ();
82- }
8382
84- private void init () {
85- for (int id =0 ; id < gameData .getForceCount (); id ++) {
86- forces .put (id , new Force (gameData .getForce (id ), this ));
83+ final int forceCount = gameData .getForceCount ();
84+ forces = new Force [forceCount ];
85+ for (int id =0 ; id < forceCount ; id ++) {
86+ forces [id ] = new Force (gameData .getForce (id ), this );
87+ }
88+
89+ forceSet = Collections .unmodifiableSet (new HashSet <>(Arrays .asList (forces )));
90+
91+ final int playerCount = gameData .getPlayerCount ();
92+ players = new Player [playerCount ];
93+ for (int id =0 ; id < playerCount ; id ++) {
94+ players [id ] = new Player (gameData .getPlayer (id ), this );
8795 }
88- for (int id =0 ; id < gameData .getPlayerCount (); id ++) {
89- players .put (id , new Player (gameData .getPlayer (id ), this ));
96+
97+ playerSet = Collections .unmodifiableSet (new HashSet <>(Arrays .asList (players )));
98+
99+ final int bulletCount = gameData .bulletCount ();
100+ bullets = new Bullet [bulletCount ];
101+ for (int id =0 ; id < bulletCount ; id ++) {
102+ bullets [id ] = new Bullet (gameData .getBullet (id ), this );
90103 }
91104
92- for (int id =0 ; id < gameData .bulletCount (); id ++) {
93- bullets .put (id , new Bullet (gameData .getBullet (id ), this ));
105+ final int regionCount = gameData .regionCount ();
106+ regions = new Region [regionCount ];
107+ for (int id =0 ; id < regionCount ; id ++) {
108+ regions [id ] = new Region (gameData .getRegion (id ), this );
94109 }
95110
96- for (int id = 0 ; id < gameData . regionCount (); id ++ ) {
97- regions . put ( id , new Region ( gameData . getRegion ( id ), this ) );
111+ for (final Region region : regions ) {
112+ region . updateNeighbours ( );
98113 }
99114
100- regions . values (). forEach ( Region :: updateNeighbours );
115+ regionSet = Collections . unmodifiableSet ( new HashSet <>( Arrays . asList ( regions )) );
101116
117+ units = new Unit [1000 ];
102118 for (int id =0 ; id < gameData .getInitialUnitCount (); id ++) {
103119 final Unit unit = new Unit (gameData .getUnit (id ), this );
104120
105- units . put ( id , unit ) ;
121+ units [ id ] = unit ;
106122
107123 if (unit .getType ().isMineralField ()) {
108124 staticMinerals .add (unit );
@@ -118,9 +134,9 @@ private void init() {
118134 randomSeed = gameData .randomSeed ();
119135 revision = gameData .getRevision ();
120136 debug = gameData .isDebug ();
121- self = players . get ( gameData .self ()) ;
122- enemy = players . get ( gameData .enemy ()) ;
123- neutral = players . get ( gameData .neutral ()) ;
137+ self = players [ gameData .self ()] ;
138+ enemy = players [ gameData .enemy ()] ;
139+ neutral = players [ gameData .neutral ()] ;
124140 replay = gameData .isReplay ();
125141 multiplayer = gameData .isMultiplayer ();
126142 battleNet = gameData .isBattleNet ();
@@ -135,9 +151,13 @@ private void init() {
135151 mapHash = gameData .mapHash ();
136152
137153 buildable = new boolean [mapWidth ][mapHeight ];
138- for (int i =0 ; i < mapWidth ; i ++) {
139- for (int j =0 ; j < mapHeight ; j ++) {
140- buildable [i ][j ] = gameData .buildable (i , j );
154+ groundHeight = new int [mapWidth ][mapHeight ];
155+ mapTileRegionID = new short [mapWidth ][mapHeight ];
156+ for (int x =0 ; x < mapWidth ; x ++) {
157+ for (int y =0 ; y < mapHeight ; y ++) {
158+ buildable [x ][y ] = gameData .buildable (x , y );
159+ groundHeight [x ][y ] = gameData .groundHeight (x , y );
160+ mapTileRegionID [x ][y ] = gameData .mapTileRegionID (x , y );
141161 }
142162 }
143163 walkable = new boolean [mapWidth *4 ][mapHeight *4 ];
@@ -146,11 +166,26 @@ private void init() {
146166 walkable [i ][j ] = gameData .walkable (i , j );
147167 }
148168 }
169+
170+ mapSplitTilesMiniTileMask = new short [5000 ];
171+ mapSplitTilesRegion1 = new short [5000 ];
172+ mapSplitTilesRegion2 = new short [5000 ];
173+ for (int i =0 ; i < 5000 ; i ++) {
174+ mapSplitTilesMiniTileMask [i ] = gameData .mapSplitTilesMiniTileMask (i );
175+ mapSplitTilesRegion1 [i ] = gameData .mapSplitTilesRegion1 (i );
176+ mapSplitTilesRegion2 [i ] = gameData .mapSplitTilesRegion2 (i );
177+ }
149178 }
150179
151180 void unitShow (final int id ) {
152- if (!units .containsKey (id )) {
153- units .put (id , new Unit (gameData .getUnit (id ), this ));
181+ if (id > units .length ) {
182+ //rescale unit array if needed
183+ final Unit [] largerUnitsArray = new Unit [2 *units .length ];
184+ System .arraycopy (units , 0 , largerUnitsArray , 0 , units .length );
185+ units = largerUnitsArray ;
186+ }
187+ if (units [id ] == null ) {
188+ units [id ] = new Unit (gameData .getUnit (id ), this );
154189 }
155190 visibleUnits .add (id );
156191 }
@@ -171,21 +206,28 @@ void addShape(final int type, final int coordType, final int x1, final int y1, f
171206 gameData .addShape (new Client .Shape (type , coordType , x1 , y1 , x2 , y2 , extra1 , extra2 , color , isSolid ));
172207 }
173208
209+
174210 public Set <Force > getForces () {
175- return new HashSet <>( forces . values ()) ;
211+ return forceSet ;
176212 }
177213
178214 public Set <Player > getPlayers () {
179- return new HashSet <>( players . values ()) ;
215+ return playerSet ;
180216 }
181217
182218
183219 public Set <Unit > getAllUnits () {
184220 if (getFrameCount () == 0 ) {
185- return new HashSet <>(units .values ());
221+ final HashSet <Unit > us = new HashSet <>();
222+ for (final Unit u : units ) {
223+ if (u != null ) {
224+ us .add (u );
225+ }
226+ }
227+ return us ;
186228 }
187229 return visibleUnits .stream ()
188- .map (units :: get )
230+ .map (i -> units [ i ] )
189231 .collect (Collectors .toSet ());
190232 }
191233
@@ -220,9 +262,13 @@ public Set<Unit> getStaticNeutralUnits() {
220262 }
221263
222264 public Set <Bullet > getBullets () {
223- return bullets .values ().stream ()
224- .filter (Bullet ::exists )
225- .collect (Collectors .toSet ());
265+ final Set <Bullet > bs = new HashSet <>();
266+ for (final Bullet bullet : bullets ) {
267+ if (bullet .exists ()) {
268+ bs .add (bullet );
269+ }
270+ }
271+ return bs ;
226272 }
227273
228274 public Set <Position > getNukeDots () {
@@ -233,19 +279,22 @@ public Set<Position> getNukeDots() {
233279
234280
235281 public Force getForce (final int forceID ) {
236- return forces . get ( forceID ) ;
282+ return forces [ forceID ] ;
237283 }
238284
239285 public Player getPlayer (final int playerID ) {
240- return players . get ( playerID ) ;
286+ return players [ playerID ] ;
241287 }
242288
243289 public Unit getUnit (final int unitID ) {
244- return units .get (unitID );
290+ if (unitID < 0 ) {
291+ return null ;
292+ }
293+ return units [unitID ];
245294 }
246295
247296 public Region getRegion (final int regionID ) {
248- return regions . get ( regionID ) ;
297+ return regions [ regionID ] ;
249298 }
250299
251300 public GameType getGameType () {
@@ -395,7 +444,7 @@ public int getGroundHeight(final TilePosition position) {
395444 if (!position .isValid (this )) {
396445 return -1 ;
397446 }
398- return gameData . groundHeight ( position .x , position .y ) ;
447+ return groundHeight [ position .x ][ position .y ] ;
399448 }
400449
401450 public boolean isBuildable (final int tileX , final int tileY ) {
@@ -954,7 +1003,7 @@ public boolean issueCommand(final Collection<Unit> units, final UnitCommand comm
9541003
9551004 public Set <Unit > getSelectedUnits () {
9561005 return IntStream .range (0 , gameData .selectedUnitCount ())
957- .mapToObj (i -> units . get ( gameData .selectedUnit (i )) )
1006+ .mapToObj (i -> units [ gameData .selectedUnit (i )] )
9581007 .collect (Collectors .toSet ());
9591008 }
9601009
@@ -1396,15 +1445,34 @@ public int countdownTimer() {
13961445 }
13971446
13981447 public Set <Region > getAllRegions () {
1399- return new HashSet <>( regions . values ()) ;
1448+ return regionSet ;
14001449 }
14011450
14021451 public Region getRegionAt (final int x , final int y ) {
1403- return regions . get (( int ) gameData . mapTileRegionID (x , y ));
1452+ return getRegionAt ( new Position (x , y ));
14041453 }
14051454
14061455 public Region getRegionAt (final Position position ) {
1407- return getRegionAt (position .x , position .y );
1456+ if ( !position .isValid (this )) {
1457+ return null ;
1458+ }
1459+ final short idx = mapTileRegionID [position .x /32 ][position .y /32 ];
1460+ if ( (idx & 0x2000 ) != 0 ) {
1461+ final int minitileShift = ((position .x &0x1F )/8 ) + ((position .y &0x1F )/8 ) * 4 ;
1462+ final int index = idx & 0x1FFF ;
1463+
1464+ if (index >= 5000 ) {
1465+ return null ;
1466+ }
1467+
1468+ if (((mapSplitTilesMiniTileMask [index ] >> minitileShift ) & 1 ) != 0 ) {
1469+ return getRegion (mapSplitTilesRegion2 [index ]);
1470+ }
1471+ else {
1472+ return getRegion (mapSplitTilesRegion1 [index ]);
1473+ }
1474+ }
1475+ return getRegion (idx );
14081476 }
14091477
14101478
@@ -1416,8 +1484,6 @@ public TilePosition getBuildLocation(final UnitType type, final TilePosition des
14161484 return getBuildLocation (type , desiredPosition , 64 );
14171485 }
14181486
1419-
1420-
14211487 public TilePosition getBuildLocation (final UnitType type , TilePosition desiredPosition , final int maxRange , final boolean creep ) {
14221488 return BuildingPlacer .getBuildLocation (type , desiredPosition , maxRange , creep , this );
14231489 }
0 commit comments