Fixed damaged building memory leak

This commit is contained in:
Anuken
2021-07-30 11:58:01 -04:00
parent 9e1ba3e235
commit fc41ad36f7
7 changed files with 54 additions and 31 deletions

View File

@@ -13,7 +13,6 @@ import mindustry.game.Teams.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.*;
import mindustry.world.meta.*; import mindustry.world.meta.*;
import java.util.*; import java.util.*;
@@ -32,7 +31,7 @@ public class BlockIndexer{
/** Stores all ore quadrants on the map. Maps ID to qX to qY to a list of tiles with that ore. */ /** Stores all ore quadrants on the map. Maps ID to qX to qY to a list of tiles with that ore. */
private IntSeq[][][] ores; private IntSeq[][][] ores;
/** Stores all damaged tile entities by team. */ /** Stores all damaged tile entities by team. */
private ObjectSet<Building>[] damagedTiles = new ObjectSet[Team.all.length]; private Seq<Building>[] damagedTiles = new Seq[Team.all.length];
/** All ores available on this map. */ /** All ores available on this map. */
private ObjectSet<Item> allOres = new ObjectSet<>(); private ObjectSet<Item> allOres = new ObjectSet<>();
/** Stores teams that are present here as tiles. */ /** Stores teams that are present here as tiles. */
@@ -59,7 +58,7 @@ public class BlockIndexer{
}); });
Events.on(WorldLoadEvent.class, event -> { Events.on(WorldLoadEvent.class, event -> {
damagedTiles = new ObjectSet[Team.all.length]; damagedTiles = new Seq[Team.all.length];
flagMap = new TileArray[Team.all.length][BlockFlag.all.length]; flagMap = new TileArray[Team.all.length][BlockFlag.all.length];
activeTeams = new Seq<>(Team.class); activeTeams = new Seq<>(Team.class);
@@ -74,10 +73,6 @@ public class BlockIndexer{
for(Tile tile : world.tiles){ for(Tile tile : world.tiles){
process(tile); process(tile);
if(tile.build != null && tile.build.damaged()){
notifyTileDamaged(tile.build);
}
var drop = tile.drop(); var drop = tile.drop();
if(drop != null){ if(drop != null){
@@ -104,6 +99,7 @@ public class BlockIndexer{
public void removeIndex(Tile tile){ public void removeIndex(Tile tile){
var team = tile.team(); var team = tile.team();
if(tile.build != null && tile.isCenter()){ if(tile.build != null && tile.isCenter()){
var build = tile.build;
var flags = tile.block().flags; var flags = tile.block().flags;
var data = team.data(); var data = team.data();
@@ -118,7 +114,15 @@ public class BlockIndexer{
//unregister building from building quadtree //unregister building from building quadtree
if(data.buildings != null){ if(data.buildings != null){
data.buildings.remove(tile.build); data.buildings.remove(build);
}
//is no longer registered
build.wasDamaged = false;
//unregister damaged buildings
if(build.damaged() && damagedTiles[team.id] != null){
damagedTiles[team.id].remove(build);
} }
} }
} }
@@ -175,25 +179,12 @@ public class BlockIndexer{
} }
/** Returns all damaged tiles by team. */ /** Returns all damaged tiles by team. */
public ObjectSet<Building> getDamaged(Team team){ public Seq<Building> getDamaged(Team team){
breturnArray.clear();
if(damagedTiles[team.id] == null){ if(damagedTiles[team.id] == null){
damagedTiles[team.id] = new ObjectSet<>(); return null;
} }
ObjectSet<Building> set = damagedTiles[team.id]; return damagedTiles[team.id];
for(Building build : set){
if((!build.isValid() || build.team != team || !build.damaged()) || build.block instanceof ConstructBlock){
breturnArray.add(build);
}
}
for(Building tile : breturnArray){
set.remove(tile);
}
return set;
} }
/** Get all allied blocks with a flag. */ /** Get all allied blocks with a flag. */
@@ -271,12 +262,22 @@ public class BlockIndexer{
return returnArray; return returnArray;
} }
public void notifyTileDamaged(Building entity){ public void notifyBuildHealed(Building build){
if(damagedTiles[entity.team.id] == null){ if(build.wasDamaged && !build.damaged() && damagedTiles[build.team.id] != null){
damagedTiles[entity.team.id] = new ObjectSet<>(); damagedTiles[build.team.id].remove(build);
build.wasDamaged = false;
}
}
public void notifyBuildDamaged(Building build){
if(build.wasDamaged || !build.damaged()) return;
if(damagedTiles[build.team.id] == null){
damagedTiles[build.team.id] = new Seq<>(false);
} }
damagedTiles[entity.team.id].add(entity); damagedTiles[build.team.id].add(build);
build.wasDamaged = true;
} }
public void allBuildings(float x, float y, float range, Cons<Building> cons){ public void allBuildings(float x, float y, float range, Cons<Building> cons){
@@ -417,6 +418,8 @@ public class BlockIndexer{
data.buildings = new QuadTree<>(new Rect(0, 0, world.unitWidth(), world.unitHeight())); data.buildings = new QuadTree<>(new Rect(0, 0, world.unitWidth(), world.unitHeight()));
} }
data.buildings.insert(tile.build); data.buildings.insert(tile.build);
notifyBuildDamaged(tile.build);
} }
if(!tile.block().isStatic()){ if(!tile.block().isStatic()){

View File

@@ -143,7 +143,7 @@ public class Units{
/** Returns the nearest damaged tile. */ /** Returns the nearest damaged tile. */
public static Building findDamagedTile(Team team, float x, float y){ public static Building findDamagedTile(Team team, float x, float y){
return Geometry.findClosest(x, y, indexer.getDamaged(team)); return indexer.getDamaged(team).min(b -> b.dst2(x, y));
} }
/** Returns the nearest ally tile in a range. */ /** Returns the nearest ally tile in a range. */

View File

@@ -63,6 +63,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
transient boolean enabled = true; transient boolean enabled = true;
transient float enabledControlTime; transient float enabledControlTime;
transient String lastAccessed; transient String lastAccessed;
transient boolean wasDamaged; //used only by the indexer
PowerModule power; PowerModule power;
ItemModule items; ItemModule items;
@@ -1344,6 +1345,18 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return tile.build == self() && !dead(); return tile.build == self() && !dead();
} }
@MethodPriority(100)
@Override
public void heal(){
indexer.notifyBuildHealed(self());
}
@MethodPriority(100)
@Override
public void heal(float amount){
indexer.notifyBuildHealed(self());
}
@Override @Override
public float hitSize(){ public float hitSize(){
return tile.block().size * tilesize; return tile.block().size * tilesize;

View File

@@ -420,6 +420,8 @@ public class Maps{
writeCache(map); writeCache(map);
}catch(Exception e){ }catch(Exception e){
e.printStackTrace(); e.printStackTrace();
}finally{
pix.dispose();
} }
}); });
}catch(Exception e){ }catch(Exception e){

View File

@@ -496,7 +496,7 @@ public class SectorDamage{
other.build.addPlan(false); other.build.addPlan(false);
other.remove(); other.remove();
}else{ }else{
indexer.notifyTileDamaged(other.build); indexer.notifyBuildDamaged(other.build);
} }
}else if(other.solid() && !other.synthetic()){ //skip damage propagation through solid blocks }else if(other.solid() && !other.synthetic()){ //skip damage propagation through solid blocks

View File

@@ -675,7 +675,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{
build.health = health; build.health = health;
if(build.damaged()){ if(build.damaged()){
indexer.notifyTileDamaged(build); indexer.notifyBuildDamaged(build);
} }
} }

View File

@@ -84,6 +84,11 @@ public class ConstructBlock extends Block{
if(builder != null && builder.getControllerName() != null){ if(builder != null && builder.getControllerName() != null){
tile.build.lastAccessed = builder.getControllerName(); tile.build.lastAccessed = builder.getControllerName();
} }
//make sure block indexer knows it's damaged
if(tile.build.damaged()){
indexer.notifyBuildDamaged(tile.build);
}
} }
//last builder was this local client player, call placed() //last builder was this local client player, call placed()