diff --git a/annotations/src/main/resources/classids.properties b/annotations/src/main/resources/classids.properties index 0c04c4de0b..f1b91cae3b 100644 --- a/annotations/src/main/resources/classids.properties +++ b/annotations/src/main/resources/classids.properties @@ -15,6 +15,7 @@ manifold=36 mega=5 mindustry.entities.comp.BuildingComp=6 mindustry.entities.comp.BulletComp=7 +mindustry.entities.comp.ConduitGraphUpdaterComp=48 mindustry.entities.comp.DecalComp=8 mindustry.entities.comp.EffectStateComp=9 mindustry.entities.comp.FireComp=10 diff --git a/annotations/src/main/resources/revisions/ConduitGraphUpdaterComp/0.json b/annotations/src/main/resources/revisions/ConduitGraphUpdaterComp/0.json new file mode 100644 index 0000000000..eaaaeead96 --- /dev/null +++ b/annotations/src/main/resources/revisions/ConduitGraphUpdaterComp/0.json @@ -0,0 +1 @@ +{fields:[]} \ No newline at end of file diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index a1c5f7b766..848cb37e67 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1681,6 +1681,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, proximity.clear(); } + public void rotated(int prevRotation, int newRotation){ + + } + public void updateProximity(){ tmpTiles.clear(); proximity.clear(); diff --git a/core/src/mindustry/entities/comp/ConduitGraphUpdaterComp.java b/core/src/mindustry/entities/comp/ConduitGraphUpdaterComp.java new file mode 100644 index 0000000000..1190dceb4b --- /dev/null +++ b/core/src/mindustry/entities/comp/ConduitGraphUpdaterComp.java @@ -0,0 +1,16 @@ +package mindustry.entities.comp; + +import mindustry.annotations.Annotations.*; +import mindustry.gen.*; +import mindustry.world.blocks.liquid.Conduit.*; + +@EntityDef(value = ConduitGraphUpdaterc.class, serialize = false, genio = false) +@Component +abstract class ConduitGraphUpdaterComp implements Entityc{ + public transient ConduitGraph graph; + + @Override + public void update(){ + graph.update(); + } +} diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 11877512e5..d57a58b26f 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -464,8 +464,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } if(player != null) build.lastAccessed = player.name; - build.rotation = Mathf.mod(build.rotation + Mathf.sign(direction), 4); + int newRotation = Mathf.mod(build.rotation + Mathf.sign(direction), 4), prev = build.rotation; + build.rotation = newRotation; build.updateProximity(); + build.rotated(prev, newRotation); build.noSleep(); Fx.rotateBlock.at(build.x, build.y, build.block.size); } diff --git a/core/src/mindustry/world/blocks/liquid/Conduit.java b/core/src/mindustry/world/blocks/liquid/Conduit.java index d73b6c9331..c3bc4e1741 100644 --- a/core/src/mindustry/world/blocks/liquid/Conduit.java +++ b/core/src/mindustry/world/blocks/liquid/Conduit.java @@ -148,10 +148,58 @@ public class Conduit extends LiquidBlock implements Autotiler{ } public class ConduitBuild extends LiquidBuild implements ChainedBuilding{ + public @Nullable ConduitGraph graph; + public float smoothLiquid; public int blendbits, xscl = 1, yscl = 1, blending; public boolean capped, backCapped = false; + protected void addGraphs(){ + graph = null; + //connect self to every nearby graph + getConnections(other -> { + if(other.graph != null){ + other.graph.merge(this); + } + }); + + if(graph == null){ + new ConduitGraph().merge(this); + } + } + + protected void removeGraphs(){ + //graph is getting recalculated, no longer valid + if(graph != null){ + graph.checkRemove(); + } + + getConnections(other -> new ConduitGraph().reflow(this, other)); + } + + @Override + public void onProximityAdded(){ + super.onProximityAdded(); + + addGraphs(); + } + + @Override + public void onProximityRemoved(){ + super.onProximityRemoved(); + + removeGraphs(); + } + + @Override + public void rotated(int prevRot, int newRot){ + //essentially simulates the conduit being removed and re-placed - hacky, but it works + rotation = prevRot; + removeGraphs(); + rotation = newRot; + addGraphs(); + } + @Override public void draw(){ int r = this.rotation; @@ -173,6 +221,15 @@ public class Conduit extends LiquidBlock implements Autotiler{ if(capped && capRegion.found()) Draw.rect(capRegion, x, y, rotdeg()); if(backCapped && capRegion.found()) Draw.rect(capRegion, x, y, rotdeg() + 180); + + //TODO this is for debuggig only + Mathf.rand.setSeed(graph == null ? -1 : graph.id); + Draw.color(Tmp.c1.rand()); + Draw.alpha(0.4f); + + Fill.square(x, y, 4f); + + Draw.color(); } protected void drawAt(float x, float y, int bits, int rotation, SliceMode slice){ @@ -245,5 +302,102 @@ public class Conduit extends LiquidBlock implements Autotiler{ } return null; } + + /** Calls callback with every conduit that transfers fluids to this one. */ + public void getConnections(Cons cons){ + for(var other : proximity){ + if(other instanceof ConduitBuild conduit){ + if( + front() == conduit || + other.front() == this + ){ + cons.get(conduit); + } + } + } + } + } + + public static class ConduitGraph{ + private static final IntSet closedSet = new IntSet(); + private static final Queue queue = new Queue<>(); + + static int lastId = -1; + + public final int id = lastId ++; + + private Seq conduits = new Seq<>(); + private final @Nullable ConduitGraphUpdater entity; + + public ConduitGraph(){ + entity = ConduitGraphUpdater.create(); + entity.graph = this; + } + + public void update(){ + //TODO + } + + public void checkAdd(){ + if(entity != null) entity.add(); + } + + public void checkRemove(){ + if(entity != null) entity.remove(); + } + + public void reflow(@Nullable ConduitBuild ignore, ConduitBuild conduit){ + closedSet.clear(); + queue.clear(); + + //ignore the starting point and don't add it, as it is being removed + if(ignore != null) closedSet.add(ignore.id); + + closedSet.add(conduit.id); + queue.add(conduit); + + while(queue.size > 0){ + var parent = queue.removeFirst(); + assign(parent); + + parent.getConnections(child -> { + if(closedSet.add(child.id)){ + queue.addLast(child); + } + }); + } + + closedSet.clear(); + queue.clear(); + } + + public void merge(ConduitBuild other){ + if(other.graph == this) return; + + if(other.graph != null){ + + //merge graphs - TODO - flip if it is larger + for(var cond : other.graph.conduits){ + assign(cond); + } + }else{ + assign(other); + } + } + + protected void assign(ConduitBuild build){ + if(build.graph != this){ + + //invalidate older graph + if(build.graph != null){ + build.graph.checkRemove(); + } + + build.graph = this; + conduits.add(build); + checkAdd(); + } + } + } } diff --git a/gradle.properties b/gradle.properties index 893b0f869e..ce4c75a351 100644 --- a/gradle.properties +++ b/gradle.properties @@ -25,4 +25,4 @@ org.gradle.caching=true #used for slow jitpack builds; TODO see if this actually works org.gradle.internal.http.socketTimeout=100000 org.gradle.internal.http.connectionTimeout=100000 -archash=77461f1c82 +archash=eb3b8bdd10