From fc41ad36f7bd25fabcf4dc07873286536057ec90 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 30 Jul 2021 11:58:01 -0400 Subject: [PATCH] Fixed damaged building memory leak --- core/src/mindustry/ai/BlockIndexer.java | 59 ++++++++++--------- core/src/mindustry/entities/Units.java | 2 +- .../mindustry/entities/comp/BuildingComp.java | 13 ++++ core/src/mindustry/maps/Maps.java | 2 + core/src/mindustry/maps/SectorDamage.java | 2 +- core/src/mindustry/world/Tile.java | 2 +- .../world/blocks/ConstructBlock.java | 5 ++ 7 files changed, 54 insertions(+), 31 deletions(-) diff --git a/core/src/mindustry/ai/BlockIndexer.java b/core/src/mindustry/ai/BlockIndexer.java index a01e6e1b39..6cc184ad38 100644 --- a/core/src/mindustry/ai/BlockIndexer.java +++ b/core/src/mindustry/ai/BlockIndexer.java @@ -13,7 +13,6 @@ import mindustry.game.Teams.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; -import mindustry.world.blocks.*; import mindustry.world.meta.*; 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. */ private IntSeq[][][] ores; /** Stores all damaged tile entities by team. */ - private ObjectSet[] damagedTiles = new ObjectSet[Team.all.length]; + private Seq[] damagedTiles = new Seq[Team.all.length]; /** All ores available on this map. */ private ObjectSet allOres = new ObjectSet<>(); /** Stores teams that are present here as tiles. */ @@ -59,7 +58,7 @@ public class BlockIndexer{ }); 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]; activeTeams = new Seq<>(Team.class); @@ -74,10 +73,6 @@ public class BlockIndexer{ for(Tile tile : world.tiles){ process(tile); - if(tile.build != null && tile.build.damaged()){ - notifyTileDamaged(tile.build); - } - var drop = tile.drop(); if(drop != null){ @@ -104,6 +99,7 @@ public class BlockIndexer{ public void removeIndex(Tile tile){ var team = tile.team(); if(tile.build != null && tile.isCenter()){ + var build = tile.build; var flags = tile.block().flags; var data = team.data(); @@ -118,7 +114,15 @@ public class BlockIndexer{ //unregister building from building quadtree 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. */ - public ObjectSet getDamaged(Team team){ - breturnArray.clear(); - + public Seq getDamaged(Team team){ if(damagedTiles[team.id] == null){ - damagedTiles[team.id] = new ObjectSet<>(); + return null; } - ObjectSet set = 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; + return damagedTiles[team.id]; } /** Get all allied blocks with a flag. */ @@ -271,12 +262,22 @@ public class BlockIndexer{ return returnArray; } - public void notifyTileDamaged(Building entity){ - if(damagedTiles[entity.team.id] == null){ - damagedTiles[entity.team.id] = new ObjectSet<>(); + public void notifyBuildHealed(Building build){ + if(build.wasDamaged && !build.damaged() && damagedTiles[build.team.id] != null){ + 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 cons){ @@ -417,6 +418,8 @@ public class BlockIndexer{ data.buildings = new QuadTree<>(new Rect(0, 0, world.unitWidth(), world.unitHeight())); } data.buildings.insert(tile.build); + + notifyBuildDamaged(tile.build); } if(!tile.block().isStatic()){ diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java index 52e6ad749c..ae4f8e00eb 100644 --- a/core/src/mindustry/entities/Units.java +++ b/core/src/mindustry/entities/Units.java @@ -143,7 +143,7 @@ public class Units{ /** Returns the nearest damaged tile. */ 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. */ diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 25e0114e23..d5bedacc3e 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -63,6 +63,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, transient boolean enabled = true; transient float enabledControlTime; transient String lastAccessed; + transient boolean wasDamaged; //used only by the indexer PowerModule power; ItemModule items; @@ -1344,6 +1345,18 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, 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 public float hitSize(){ return tile.block().size * tilesize; diff --git a/core/src/mindustry/maps/Maps.java b/core/src/mindustry/maps/Maps.java index 613067f61f..b6a2f1fc1e 100644 --- a/core/src/mindustry/maps/Maps.java +++ b/core/src/mindustry/maps/Maps.java @@ -420,6 +420,8 @@ public class Maps{ writeCache(map); }catch(Exception e){ e.printStackTrace(); + }finally{ + pix.dispose(); } }); }catch(Exception e){ diff --git a/core/src/mindustry/maps/SectorDamage.java b/core/src/mindustry/maps/SectorDamage.java index 786074c3dd..5ee6e1f15a 100644 --- a/core/src/mindustry/maps/SectorDamage.java +++ b/core/src/mindustry/maps/SectorDamage.java @@ -496,7 +496,7 @@ public class SectorDamage{ other.build.addPlan(false); other.remove(); }else{ - indexer.notifyTileDamaged(other.build); + indexer.notifyBuildDamaged(other.build); } }else if(other.solid() && !other.synthetic()){ //skip damage propagation through solid blocks diff --git a/core/src/mindustry/world/Tile.java b/core/src/mindustry/world/Tile.java index ebe5d21414..624dc300b6 100644 --- a/core/src/mindustry/world/Tile.java +++ b/core/src/mindustry/world/Tile.java @@ -675,7 +675,7 @@ public class Tile implements Position, QuadTreeObject, Displayable{ build.health = health; if(build.damaged()){ - indexer.notifyTileDamaged(build); + indexer.notifyBuildDamaged(build); } } diff --git a/core/src/mindustry/world/blocks/ConstructBlock.java b/core/src/mindustry/world/blocks/ConstructBlock.java index 0bc7115142..63f66a9afa 100644 --- a/core/src/mindustry/world/blocks/ConstructBlock.java +++ b/core/src/mindustry/world/blocks/ConstructBlock.java @@ -84,6 +84,11 @@ public class ConstructBlock extends Block{ if(builder != null && builder.getControllerName() != null){ 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()