diff --git a/annotations/src/main/resources/classids.properties b/annotations/src/main/resources/classids.properties index 555d72975c..6dd36e7b71 100644 --- a/annotations/src/main/resources/classids.properties +++ b/annotations/src/main/resources/classids.properties @@ -20,6 +20,8 @@ mindustry.entities.comp.LaunchCoreComp=11 mindustry.entities.comp.PlayerComp=12 mindustry.entities.comp.PosTeam=27 mindustry.entities.comp.PosTeamDef=28 +mindustry.entities.comp.PowerGraphComp=41 +mindustry.entities.comp.PowerGraphUpdaterComp=42 mindustry.entities.comp.PuddleComp=13 mindustry.entities.comp.WorldLabelComp=35 mindustry.type.Weather.WeatherStateComp=14 diff --git a/annotations/src/main/resources/revisions/PowerGraphUpdaterComp/0.json b/annotations/src/main/resources/revisions/PowerGraphUpdaterComp/0.json new file mode 100644 index 0000000000..eaaaeead96 --- /dev/null +++ b/annotations/src/main/resources/revisions/PowerGraphUpdaterComp/0.json @@ -0,0 +1 @@ +{fields:[]} \ No newline at end of file diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index 76205dac2f..5a56472ba6 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -308,6 +308,7 @@ public class World{ } state.rules.cloudColor = sector.planet.landCloudColor; + state.rules.environment = sector.planet.defaultEnv; state.rules.hiddenBuildItems.clear(); state.rules.hiddenBuildItems.addAll(sector.planet.hiddenItems); sector.info.resources = content.toSeq(); diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 288650c9ef..96115c6711 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -109,7 +109,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, set(tile.drawx(), tile.drawy()); - if(shouldAdd){ + if(shouldAdd && shouldUpdate()){ add(); } @@ -524,7 +524,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, /** Call when this entity is updating. This wakes it up. */ public void noSleep(){ sleepTime = 0f; - if(sleeping){ + if(sleeping && shouldUpdate()){ add(); sleeping = false; sleepingEntities--; @@ -1508,6 +1508,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, this.team = next; indexer.addIndex(tile); Events.fire(teamChangeEvent.set(last, self())); + + if(!shouldUpdate()){ + remove(); + } } public boolean canPickup(){ @@ -1522,6 +1526,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, /** Called right after this building is picked up. */ public void afterPickedUp(){ if(power != null){ + //TODO can lead to ghost graphs? power.graph = new PowerGraph(); power.links.clear(); if(block.consumes.hasPower() && !block.consumes.getPower().buffered){ @@ -1773,9 +1778,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, //TODO should just avoid updating buildings instead if(state.isEditor()) return; - //TODO refactor to timestamp-based system - timeScaleDuration -= Time.delta; - if(timeScaleDuration <= 0f || !block.canOverdrive){ + //TODO refactor to timestamp-based system? + if((timeScaleDuration -= Time.delta) <= 0f || !block.canOverdrive){ timeScale = 1f; } @@ -1789,11 +1793,6 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } } - //TODO this check should not be here, just remove unsupported buildings instead - if(team == Team.derelict || !block.supportsEnv(state.rules.environment)){ - enabled = false; - } - //TODO separate system for sound? AudioSource, etc if(!headless){ if(sound != null){ @@ -1805,18 +1804,13 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, } } - //TODO consume module is not necessary for every building, e.g. conveyors should not have it - perhaps it should be nullable? + //TODO updating consumption is not necessary for every building, e.g. conveyors should not have it updateConsumption(); //TODO just handle per-block instead if(enabled || !block.noUpdateDisabled){ updateTile(); } - - //TODO power graph should be separate entity - if(power != null){ - power.graph.update(); - } } @Override diff --git a/core/src/mindustry/entities/comp/PowerGraphUpdaterComp.java b/core/src/mindustry/entities/comp/PowerGraphUpdaterComp.java new file mode 100644 index 0000000000..66b1464eae --- /dev/null +++ b/core/src/mindustry/entities/comp/PowerGraphUpdaterComp.java @@ -0,0 +1,16 @@ +package mindustry.entities.comp; + +import mindustry.annotations.Annotations.*; +import mindustry.gen.*; +import mindustry.world.blocks.power.*; + +@EntityDef(value = PowerGraphUpdaterc.class, serialize = false, genio = false) +@Component +abstract class PowerGraphUpdaterComp implements Entityc{ + public transient PowerGraph graph; + + @Override + public void update(){ + graph.update(); + } +} diff --git a/core/src/mindustry/graphics/OverlayRenderer.java b/core/src/mindustry/graphics/OverlayRenderer.java index 6589f8d6e9..ff6c35da30 100644 --- a/core/src/mindustry/graphics/OverlayRenderer.java +++ b/core/src/mindustry/graphics/OverlayRenderer.java @@ -206,7 +206,7 @@ public class OverlayRenderer{ if(build != null && build.team == player.team()){ build.drawSelect(); - if(!build.enabled && build.block.drawDisabled){ + if((!build.enabled && build.block.drawDisabled) || !build.shouldUpdate()){ build.drawDisabled(); } diff --git a/core/src/mindustry/world/blocks/power/PowerGraph.java b/core/src/mindustry/world/blocks/power/PowerGraph.java index f046ffbf39..f4e4b408c2 100644 --- a/core/src/mindustry/world/blocks/power/PowerGraph.java +++ b/core/src/mindustry/world/blocks/power/PowerGraph.java @@ -6,8 +6,6 @@ import arc.util.*; import mindustry.gen.*; import mindustry.world.consumers.*; -import static mindustry.Vars.*; - public class PowerGraph{ private static final Queue queue = new Queue<>(); private static final Seq outArray1 = new Seq<>(); @@ -20,17 +18,19 @@ public class PowerGraph{ public final Seq batteries = new Seq<>(false); public final Seq all = new Seq<>(false); + private final PowerGraphUpdater entity; private final WindowedMean powerBalance = new WindowedMean(60); private float lastPowerProduced, lastPowerNeeded, lastPowerStored; private float lastScaledPowerIn, lastScaledPowerOut, lastCapacity; //diodes workaround for correct energy production info private float energyDelta = 0f; - private long lastFrameUpdated = -1; private final int graphID; private static int lastGraphID; - { + public PowerGraph(){ + entity = PowerGraphUpdater.create(); + entity.graph = this; graphID = lastGraphID++; } @@ -207,9 +207,7 @@ public class PowerGraph{ } public void update(){ - if(state.updateId == lastFrameUpdated){ - return; - }else if(!consumers.isEmpty() && consumers.first().cheating()){ + if(!consumers.isEmpty() && consumers.first().cheating()){ //when cheating, just set status to 1 for(Building tile : consumers){ tile.power.status = 1f; @@ -219,8 +217,6 @@ public class PowerGraph{ return; } - lastFrameUpdated = state.updateId; - float powerNeeded = getPowerNeeded(); float powerProduced = getPowerProduced(); @@ -255,6 +251,8 @@ public class PowerGraph{ public void addGraph(PowerGraph graph){ if(graph == this) return; + //other entity should be removed as the graph was merged + graph.entity.remove(); for(Building tile : graph.all){ add(tile); @@ -265,9 +263,16 @@ public class PowerGraph{ if(build == null || build.power == null) return; if(build.power.graph != this || !build.power.init){ + //any old graph that is added here MUST be invalid, remove it + if(build.power.graph != null && build.power.graph != this){ + build.power.graph.entity.remove(); + } + build.power.graph = this; build.power.init = true; all.add(build); + //there's something to update, add the entity + entity.add(); if(build.block.outputsPower && build.block.consumesPower && !build.block.consumes.getPower().buffered){ producers.add(build); @@ -287,6 +292,8 @@ public class PowerGraph{ producers.clear(); consumers.clear(); batteries.clear(); + //nothing left + entity.remove(); } public void reflow(Building tile){ @@ -313,7 +320,7 @@ public class PowerGraph{ } /** Note that this does not actually remove the building from the graph; - * it creates *new* graphs that contain the correct buildings. */ + * it creates *new* graphs that contain the correct buildings. Doing this invalidates the graph. */ public void remove(Building tile){ //go through all the connections of this tile @@ -345,6 +352,9 @@ public class PowerGraph{ //update the graph once so direct consumers without any connected producer lose their power graph.update(); } + + //implied empty graph here + entity.remove(); } private boolean otherConsumersAreValid(Building build, Consume consumePower){ @@ -363,7 +373,6 @@ public class PowerGraph{ ", consumers=" + consumers + ", batteries=" + batteries + ", all=" + all + - ", lastFrameUpdated=" + lastFrameUpdated + ", graphID=" + graphID + '}'; } diff --git a/core/src/mindustry/world/blocks/power/PowerNode.java b/core/src/mindustry/world/blocks/power/PowerNode.java index 2f61d24d96..259b204c0d 100644 --- a/core/src/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/mindustry/world/blocks/power/PowerNode.java @@ -379,11 +379,6 @@ public class PowerNode extends PowerBlock{ updatePowerGraph(); } - @Override - public void updateTile(){ - power.graph.update(); - } - @Override public boolean onConfigureTileTapped(Building other){ if(linkValid(this, other)){ diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index f987875576..ce32717bfa 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -913,7 +913,7 @@ public class ApplicationTests{ if(state.rules.attackMode){ bossWave = 100; }else{ - //assertNotEquals(0, bossWave, "Sector " + zone.name + " doesn't have a boss/end wave."); + assertNotEquals(0, bossWave, "Sector " + zone.name + " doesn't have a boss/end wave."); } if(state.rules.winWave > 0) bossWave = state.rules.winWave - 1; diff --git a/tests/src/test/java/power/FakeGraphics.java b/tests/src/test/java/power/FakeGraphics.java deleted file mode 100644 index 4bbd0bb24c..0000000000 --- a/tests/src/test/java/power/FakeGraphics.java +++ /dev/null @@ -1,215 +0,0 @@ -package power; - -import arc.Graphics; -import arc.Graphics.Cursor.SystemCursor; -import arc.graphics.*; -import arc.graphics.gl.GLVersion; - -public class FakeGraphics extends Graphics{ - static int frame; - - @Override - public boolean isGL30Available(){ - return false; - } - - @Override - public GL20 getGL20(){ - return null; - } - - @Override - public void setGL20(GL20 gl20){ - - } - - @Override - public GL30 getGL30(){ - return null; - } - - @Override - public void setGL30(GL30 gl30){ - - } - - @Override - public int getWidth(){ - return 0; - } - - @Override - public int getHeight(){ - return 0; - } - - @Override - public int getBackBufferWidth(){ - return 0; - } - - @Override - public int getBackBufferHeight(){ - return 0; - } - - @Override - public long getFrameId(){ - return frame++; - } - - @Override - public float getDeltaTime(){ - return 0; - } - - @Override - public int getFramesPerSecond(){ - return 0; - } - - @Override - public GLVersion getGLVersion(){ - return null; - } - - @Override - public float getPpiX(){ - return 0; - } - - @Override - public float getPpiY(){ - return 0; - } - - @Override - public float getPpcX(){ - return 0; - } - - @Override - public float getPpcY(){ - return 0; - } - - @Override - public float getDensity(){ - return 0; - } - - @Override - public boolean supportsDisplayModeChange(){ - return false; - } - - @Override - public Monitor getPrimaryMonitor(){ - return null; - } - - @Override - public Monitor getMonitor(){ - return null; - } - - @Override - public Monitor[] getMonitors(){ - return new Monitor[0]; - } - - @Override - public DisplayMode[] getDisplayModes(){ - return new DisplayMode[0]; - } - - @Override - public DisplayMode[] getDisplayModes(Monitor monitor){ - return new DisplayMode[0]; - } - - @Override - public DisplayMode getDisplayMode(){ - return null; - } - - @Override - public DisplayMode getDisplayMode(Monitor monitor){ - return null; - } - - @Override - public boolean setFullscreenMode(DisplayMode displayMode){ - return false; - } - - @Override - public boolean setWindowedMode(int width, int height){ - return false; - } - - @Override - public void setTitle(String title){ - - } - - @Override - public void setBorderless(boolean undecorated){ - - } - - @Override - public void setResizable(boolean resizable){ - - } - - @Override - public void setVSync(boolean vsync){ - - } - - @Override - public BufferFormat getBufferFormat(){ - return null; - } - - @Override - public boolean supportsExtension(String extension){ - return false; - } - - @Override - public boolean isContinuousRendering(){ - return false; - } - - @Override - public void setContinuousRendering(boolean isContinuous){ - - } - - @Override - public void requestRendering(){ - - } - - @Override - public boolean isFullscreen(){ - return false; - } - - @Override - public Cursor newCursor(Pixmap pixmap, int xHotspot, int yHotspot){ - return null; - } - - @Override - protected void setCursor(Cursor cursor){ - - } - - @Override - protected void setSystemCursor(SystemCursor systemCursor){ - - } -} diff --git a/tests/src/test/java/power/PowerTestFixture.java b/tests/src/test/java/power/PowerTestFixture.java index a27f2cee31..e25c2e50cf 100644 --- a/tests/src/test/java/power/PowerTestFixture.java +++ b/tests/src/test/java/power/PowerTestFixture.java @@ -26,8 +26,8 @@ public class PowerTestFixture{ @BeforeAll static void initializeDependencies(){ headless = true; - Core.graphics = new FakeGraphics(); Core.files = new MockFiles(); + Groups.init(); boolean make = content == null; diff --git a/tests/src/test/java/power/PowerTests.java b/tests/src/test/java/power/PowerTests.java index 39e4b9b588..18a47a9492 100644 --- a/tests/src/test/java/power/PowerTests.java +++ b/tests/src/test/java/power/PowerTests.java @@ -1,18 +1,17 @@ package power; -import arc.*; import arc.math.*; import arc.util.*; import mindustry.*; import mindustry.core.*; import mindustry.world.*; -import mindustry.world.blocks.power.*; import mindustry.world.blocks.power.PowerGenerator.*; +import mindustry.world.blocks.power.*; import mindustry.world.consumers.*; import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.*; -import static org.junit.jupiter.api.DynamicTest.dynamicTest; +import static org.junit.jupiter.api.DynamicTest.*; /** * Tests code related to the power system in general, but not specific blocks. @@ -25,7 +24,6 @@ public class PowerTests extends PowerTestFixture{ @BeforeAll static void init(){ - Core.graphics = new FakeGraphics(); Vars.state = new GameState(); }