mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-10-02 03:00:29 +03:00
Optimization to bulk team changes (reduces campaign core destruction lag)
This commit is contained in:
@@ -176,29 +176,58 @@ public class BlockIndexer{
|
||||
}
|
||||
}
|
||||
|
||||
//no longer part of the building list
|
||||
data.buildings.remove(build);
|
||||
data.buildingTypes.get(build.block, () -> new Seq<>(false)).remove(build);
|
||||
{
|
||||
int buildIndex = build.indexerBuildIndex & 0xffff;
|
||||
|
||||
//remove from building list based on cached index
|
||||
if(buildIndex < data.buildings.size && data.buildings.get(buildIndex) == build){
|
||||
data.buildings.remove(buildIndex);
|
||||
//update index of the building placed in the new position
|
||||
if(buildIndex < data.buildings.size) data.buildings.get(buildIndex).indexerBuildIndex = (short)buildIndex;
|
||||
}else{
|
||||
int index = data.buildings.indexOf(build);
|
||||
if(index != -1){
|
||||
data.buildings.remove(index);
|
||||
//update index of the building placed in the new position
|
||||
if(index < data.buildings.size) data.buildings.get(index).indexerBuildIndex = (short)index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var targetTypes = data.buildingTypes.get(build.block, () -> new Seq<>(false));
|
||||
int buildTypeIndex = build.indexerBuildTypeIndex & 0xffff;
|
||||
|
||||
//remove from building list based on cached index
|
||||
if(buildTypeIndex < targetTypes.size && targetTypes.get(buildTypeIndex) == build){
|
||||
targetTypes.remove(buildTypeIndex);
|
||||
//update index of the building placed in the new position
|
||||
if(buildTypeIndex < targetTypes.size) targetTypes.get(buildTypeIndex).indexerBuildTypeIndex = (short)buildTypeIndex;
|
||||
}else{
|
||||
int index = targetTypes.indexOf(build);
|
||||
if(index != -1){
|
||||
targetTypes.remove(index);
|
||||
//update index of the building placed in the new position
|
||||
if(index < targetTypes.size) targetTypes.get(index).indexerBuildTypeIndex = (short)index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//update the unit cap when building is removed
|
||||
data.unitCap -= tile.block().unitCapModifier;
|
||||
|
||||
//unregister building from building quadtree
|
||||
if(data.buildingTree != null){
|
||||
data.buildingTree.remove(build);
|
||||
}
|
||||
|
||||
//remove indexed turret
|
||||
if(data.turretTree != null && build.block.attacks){
|
||||
data.turretTree.remove(build);
|
||||
}
|
||||
|
||||
//unregister damaged buildings
|
||||
//unregister damaged buildings if applicable
|
||||
if(build.wasDamaged && damagedTiles[team.id] != null){
|
||||
damagedTiles[team.id].remove(build);
|
||||
}
|
||||
|
||||
//is no longer registered
|
||||
build.wasDamaged = false;
|
||||
}
|
||||
}
|
||||
@@ -563,9 +592,15 @@ public class BlockIndexer{
|
||||
}
|
||||
}
|
||||
|
||||
var targetTypes = data.buildingTypes.get(tile.block(), () -> new Seq<>(false));
|
||||
|
||||
//record in list of buildings
|
||||
data.buildings.add(tile.build);
|
||||
data.buildingTypes.get(tile.block(), () -> new Seq<>(false)).add(tile.build);
|
||||
targetTypes.add(tile.build);
|
||||
|
||||
//save indices for fast lookup
|
||||
tile.build.indexerBuildIndex = (short)(data.buildings.size - 1);
|
||||
tile.build.indexerBuildTypeIndex = (short)(targetTypes.size - 1);
|
||||
|
||||
//update the unit cap when new tile is registered
|
||||
data.unitCap += tile.block().unitCapModifier;
|
||||
|
||||
@@ -66,9 +66,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
transient Seq<Building> proximity = new Seq<>(true, 6, Building.class);
|
||||
transient int cdump;
|
||||
transient int rotation;
|
||||
transient float payloadRotation;
|
||||
transient String lastAccessed;
|
||||
transient boolean wasDamaged; //used only by the indexer
|
||||
transient float visualLiquid;
|
||||
|
||||
/** TODO Each bit corresponds to a team ID. Only 64 are supported. Does not work on servers. */
|
||||
@@ -103,6 +101,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
private transient float sleepTime;
|
||||
private transient boolean initialized;
|
||||
|
||||
//used only by the indexer
|
||||
transient boolean wasDamaged;
|
||||
transient short indexerBuildIndex, indexerBuildTypeIndex;
|
||||
|
||||
/** Sets this tile entity data to this and adds it if necessary. */
|
||||
public Building init(Tile tile, Team team, boolean shouldAdd, int rotation){
|
||||
if(!initialized){
|
||||
@@ -1755,6 +1757,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
/** Changes this building's team in a safe manner. */
|
||||
public void changeTeam(Team next){
|
||||
changeTeam(next, true);
|
||||
}
|
||||
|
||||
/** Changes this building's team in a safe manner. */
|
||||
public void changeTeam(Team next, boolean updatePower){
|
||||
if(this.team == next) return;
|
||||
if(block.forceTeam != null) team = block.forceTeam;
|
||||
|
||||
@@ -1768,11 +1775,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
|
||||
this.team = next;
|
||||
|
||||
if(power != null){
|
||||
if(power != null && updatePower){
|
||||
var oldGraph = power.graph;
|
||||
for(int i = 0; i < power.links.size; i++){
|
||||
var other = world.build(power.links.items[i]);
|
||||
|
||||
if(other != null && other.team != team && other.power != null){
|
||||
//only reflow links that were connected to the old power graph; ones that have a new one were already covered.
|
||||
if(other != null && other.team != team && other.power != null && other.power.graph == oldGraph){
|
||||
power.links.removeIndex(i);
|
||||
other.power.links.removeValue(pos());
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.blocks.environment.*;
|
||||
import mindustry.world.blocks.power.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@@ -26,7 +27,9 @@ public class Tile implements Position, QuadTreeObject, Displayable{
|
||||
private static final TilePreChangeEvent preChange = new TilePreChangeEvent();
|
||||
private static final TileFloorChangeEvent floorChange = new TileFloorChangeEvent();
|
||||
private static final TileOverlayChangeEvent overlayChange = new TileOverlayChangeEvent();;
|
||||
|
||||
private static final ObjectSet<Building> tileSet = new ObjectSet<>();
|
||||
private static final IntSet staleGraphs = new IntSet();
|
||||
|
||||
/**
|
||||
* Extra data for specific blocks. Only saved if Block#saveData is true.
|
||||
@@ -801,10 +804,39 @@ public class Tile implements Position, QuadTreeObject, Displayable{
|
||||
@Remote(called = Loc.server)
|
||||
public static void setTeams(int[] positions, Team team){
|
||||
if(positions == null) return;
|
||||
|
||||
staleGraphs.clear();
|
||||
|
||||
for(int pos : positions){
|
||||
Tile tile = world.tile(pos);
|
||||
if(tile != null && tile.build != null){
|
||||
tile.build.changeTeam(team);
|
||||
var build = world.build(pos);
|
||||
if(build != null){
|
||||
if(build.power != null){
|
||||
staleGraphs.add(build.power.graph.getID());
|
||||
}
|
||||
build.changeTeam(team, false);
|
||||
}
|
||||
}
|
||||
|
||||
//update power graphs in a second pass
|
||||
for(int pos : positions){
|
||||
var build = world.build(pos);
|
||||
if(build != null && build.power != null && staleGraphs.contains(build.power.graph.getID())){
|
||||
for(int i = 0; i < build.power.links.size; i++){
|
||||
var other = world.build(build.power.links.items[i]);
|
||||
|
||||
//only reflow links that were connected to the old power graph; ones that have a new one were already covered.
|
||||
if(other != null && other.team != team && other.power != null && staleGraphs.contains(other.power.graph.getID())){
|
||||
build.power.links.removeIndex(i);
|
||||
other.power.links.removeValue(build.pos());
|
||||
|
||||
new PowerGraph().reflow(other);
|
||||
|
||||
i --;
|
||||
}
|
||||
}
|
||||
new PowerGraph().reflow(build);
|
||||
|
||||
build.updatePowerGraph();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,6 @@ public class BuildPayload implements Payload{
|
||||
@Override
|
||||
public void set(float x, float y, float rotation){
|
||||
build.set(x, y);
|
||||
build.payloadRotation = rotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user