Compare commits

...

6 Commits

Author SHA1 Message Date
Anuken
5c89d7d273 arc 2023-05-09 16:42:17 -04:00
Anuken
3ea742b06d debugGraphs off 2023-05-09 15:39:53 -04:00
Anuken
9bedadac79 Better conduit merge 2023-05-09 15:34:13 -04:00
Anuken
5ccadcf38f Semi-functioning implementation 2023-05-09 15:00:26 -04:00
Anuken
a32462971b checklist 2023-05-09 12:23:49 -04:00
Anuken
3faf8ca07f WIP conduit graph 2023-05-09 12:19:26 -04:00
10 changed files with 394 additions and 25 deletions

View File

@@ -15,6 +15,7 @@ manifold=36
mega=5 mega=5
mindustry.entities.comp.BuildingComp=6 mindustry.entities.comp.BuildingComp=6
mindustry.entities.comp.BulletComp=7 mindustry.entities.comp.BulletComp=7
mindustry.entities.comp.ConduitGraphUpdaterComp=48
mindustry.entities.comp.DecalComp=8 mindustry.entities.comp.DecalComp=8
mindustry.entities.comp.EffectStateComp=9 mindustry.entities.comp.EffectStateComp=9
mindustry.entities.comp.FireComp=10 mindustry.entities.comp.FireComp=10

View File

@@ -0,0 +1 @@
{fields:[]}

View File

@@ -99,7 +99,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
private transient boolean sleeping; private transient boolean sleeping;
private transient float sleepTime; private transient float sleepTime;
private transient boolean initialized; private transient boolean initialized, wasAdded;
/** Sets this tile entity data to this and adds it if necessary. */ /** Sets this tile entity data to this and adds it if necessary. */
public Building init(Tile tile, Team team, boolean shouldAdd, int rotation){ public Building init(Tile tile, Team team, boolean shouldAdd, int rotation){
@@ -174,6 +174,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
//endregion //endregion
//region io //region io
/** certain blocks merge liquid graphs, so it is necessary to provide a fake one at write-time */
public LiquidModule writeLiquids(){
return liquids;
}
public final void writeBase(Writes write){ public final void writeBase(Writes write){
boolean writeVisibility = state.rules.fog && visibleFlags != 0; boolean writeVisibility = state.rules.fog && visibleFlags != 0;
@@ -186,7 +191,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
write.b(moduleBitmask()); write.b(moduleBitmask());
if(items != null) items.write(write); if(items != null) items.write(write);
if(power != null) power.write(write); if(power != null) power.write(write);
if(liquids != null) liquids.write(write); if(liquids != null) writeLiquids().write(write);
//efficiency is written as two bytes to save space //efficiency is written as two bytes to save space
write.b((byte)(Mathf.clamp(efficiency) * 255f)); write.b((byte)(Mathf.clamp(efficiency) * 255f));
@@ -820,6 +825,8 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
if(!net.client() && state.isCampaign() && team == state.rules.defaultTeam) liquid.unlock(); if(!net.client() && state.isCampaign() && team == state.rules.defaultTeam) liquid.unlock();
float selfCapacity = liquidCapacity();
for(int i = 0; i < proximity.size; i++){ for(int i = 0; i < proximity.size; i++){
incrementDump(proximity.size); incrementDump(proximity.size);
@@ -829,10 +836,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
other = other.getLiquidDestination(self(), liquid); other = other.getLiquidDestination(self(), liquid);
if(other != null && other.team == team && other.block.hasLiquids && canDumpLiquid(other, liquid) && other.liquids != null){ if(other != null && other.team == team && other.block.hasLiquids && canDumpLiquid(other, liquid) && other.liquids != null){
float ofract = other.liquids.get(liquid) / other.block.liquidCapacity; float ofract = other.liquids.get(liquid) / other.liquidCapacity();
float fract = liquids.get(liquid) / block.liquidCapacity; float fract = liquids.get(liquid) / selfCapacity;
if(ofract < fract) transferLiquid(other, (fract - ofract) * block.liquidCapacity / scaling, liquid); if(ofract < fract) transferLiquid(other, (fract - ofract) * selfCapacity / scaling, liquid);
} }
} }
} }
@@ -842,7 +849,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
} }
public void transferLiquid(Building next, float amount, Liquid liquid){ public void transferLiquid(Building next, float amount, Liquid liquid){
float flow = Math.min(next.block.liquidCapacity - next.liquids.get(liquid), amount); float flow = Math.min(next.liquidCapacity() - next.liquids.get(liquid), amount);
if(next.acceptLiquid(self(), liquid)){ if(next.acceptLiquid(self(), liquid)){
next.handleLiquid(self(), liquid, flow); next.handleLiquid(self(), liquid, flow);
@@ -869,19 +876,20 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
if(next == null) return 0; if(next == null) return 0;
next = next.getLiquidDestination(self(), liquid); next = next.getLiquidDestination(self(), liquid);
float selfCapacity = liquidCapacity(), nextCapacity = next.liquidCapacity();
if(next.team == team && next.block.hasLiquids && liquids.get(liquid) > 0f){ if(next.team == team && next.block.hasLiquids && liquids.get(liquid) > 0f){
float ofract = next.liquids.get(liquid) / next.block.liquidCapacity; float ofract = next.liquids.get(liquid) / nextCapacity;
float fract = liquids.get(liquid) / block.liquidCapacity * block.liquidPressure; float fract = liquids.get(liquid) / selfCapacity * block.liquidPressure;
float flow = Math.min(Mathf.clamp((fract - ofract)) * (block.liquidCapacity), liquids.get(liquid)); float flow = Math.min(Mathf.clamp((fract - ofract)) * selfCapacity, liquids.get(liquid));
flow = Math.min(flow, next.block.liquidCapacity - next.liquids.get(liquid)); flow = Math.min(flow, nextCapacity - next.liquids.get(liquid));
if(flow > 0f && ofract <= fract && next.acceptLiquid(self(), liquid)){ if(flow > 0f && ofract <= fract && next.acceptLiquid(self(), liquid)){
next.handleLiquid(self(), liquid, flow); next.handleLiquid(self(), liquid, flow);
liquids.remove(liquid, flow); liquids.remove(liquid, flow);
return flow; return flow;
//handle reactions between different liquid types ▼ //handle reactions between different liquid types ▼
}else if(!next.block.consumesLiquid(liquid) && next.liquids.currentAmount() / next.block.liquidCapacity > 0.1f && fract > 0.1f){ }else if(!next.block.consumesLiquid(liquid) && next.liquids.currentAmount() / nextCapacity > 0.1f && fract > 0.1f){
//TODO !IMPORTANT! uses current(), which is 1) wrong for multi-liquid blocks and 2) causes unwanted reactions, e.g. hydrogen + slag in pump //TODO !IMPORTANT! uses current(), which is 1) wrong for multi-liquid blocks and 2) causes unwanted reactions, e.g. hydrogen + slag in pump
//TODO these are incorrect effect positions //TODO these are incorrect effect positions
float fx = (x + next.x) / 2f, fy = (y + next.y) / 2f; float fx = (x + next.x) / 2f, fy = (y + next.y) / 2f;
@@ -907,6 +915,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
return 0; return 0;
} }
/** Override to set a custom liquid capacity, e.g. for blocks with shared inventories. */
public float liquidCapacity(){
return block.liquidCapacity;
}
public Building getLiquidDestination(Building from, Liquid liquid){ public Building getLiquidDestination(Building from, Liquid liquid){
return self(); return self();
} }
@@ -1074,6 +1087,9 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
noSleep(); noSleep();
} }
/** Like onProximityAdded, but only called once. Essentially does what onProximityAdded was supposed to. */
public void onAdded(){}
public void updatePowerGraph(){ public void updatePowerGraph(){
for(Building other : getPowerConnections(tempBuilds)){ for(Building other : getPowerConnections(tempBuilds)){
if(other.power != null){ if(other.power != null){
@@ -1679,6 +1695,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
other.onProximityUpdate(); other.onProximityUpdate();
} }
proximity.clear(); proximity.clear();
wasAdded = false;
}
public void rotated(int prevRotation, int newRotation){
} }
public void updateProximity(){ public void updateProximity(){
@@ -1701,6 +1722,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
proximity.add(tile); proximity.add(tile);
} }
if(!wasAdded){
onAdded();
wasAdded = true;
}
onProximityAdded(); onProximityAdded();
onProximityUpdate(); onProximityUpdate();

View File

@@ -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();
}
}

View File

@@ -464,8 +464,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
} }
if(player != null) build.lastAccessed = player.name; 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.updateProximity();
build.rotated(prev, newRotation);
build.noSleep(); build.noSleep();
Fx.rotateBlock.at(build.x, build.y, build.block.size); Fx.rotateBlock.at(build.x, build.y, build.block.size);
} }

View File

@@ -558,7 +558,7 @@ public class Block extends UnlockableContent implements Senseable{
addBar("liquid-" + liq.name, entity -> !liq.unlockedNow() ? null : new Bar( addBar("liquid-" + liq.name, entity -> !liq.unlockedNow() ? null : new Bar(
() -> liq.localizedName, () -> liq.localizedName,
liq::barColor, liq::barColor,
() -> entity.liquids.get(liq) / liquidCapacity () -> entity.liquids.get(liq) / entity.liquidCapacity()
)); ));
} }
@@ -567,7 +567,7 @@ public class Block extends UnlockableContent implements Senseable{
addBar("liquid", entity -> new Bar( addBar("liquid", entity -> new Bar(
() -> current.get((T)entity) == null || entity.liquids.get(current.get((T)entity)) <= 0.001f ? Core.bundle.get("bar.liquid") : current.get((T)entity).localizedName, () -> current.get((T)entity) == null || entity.liquids.get(current.get((T)entity)) <= 0.001f ? Core.bundle.get("bar.liquid") : current.get((T)entity).localizedName,
() -> current.get((T)entity) == null ? Color.clear : current.get((T)entity).barColor(), () -> current.get((T)entity) == null ? Color.clear : current.get((T)entity).barColor(),
() -> current.get((T)entity) == null ? 0f : entity.liquids.get(current.get((T)entity)) / liquidCapacity) () -> current.get((T)entity) == null ? 0f : entity.liquids.get(current.get((T)entity)) / entity.liquidCapacity())
); );
} }

View File

@@ -8,6 +8,7 @@ import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
import arc.util.io.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.entities.*; import mindustry.entities.*;
@@ -15,17 +16,22 @@ import mindustry.entities.units.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.input.*; import mindustry.input.*;
import mindustry.logic.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.*; import mindustry.world.blocks.*;
import mindustry.world.blocks.distribution.*; import mindustry.world.blocks.distribution.*;
import mindustry.world.modules.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
import static mindustry.type.Liquid.*; import static mindustry.type.Liquid.*;
public class Conduit extends LiquidBlock implements Autotiler{ public class Conduit extends LiquidBlock implements Autotiler{
static final boolean debugGraphs = false;
static final float mergeThreshold = 0.2f;
static final float rotatePad = 6, hpad = rotatePad / 2f / 4f; static final float rotatePad = 6, hpad = rotatePad / 2f / 4f;
static final float[][] rotateOffsets = {{hpad, hpad}, {-hpad, hpad}, {-hpad, -hpad}, {hpad, -hpad}}; static final float[][] rotateOffsets = {{hpad, hpad}, {-hpad, hpad}, {-hpad, -hpad}, {hpad, -hpad}};
static final LiquidModule tempLiquids = new LiquidModule();
public final int timerFlow = timers++; public final int timerFlow = timers++;
@@ -51,6 +57,10 @@ public class Conduit extends LiquidBlock implements Autotiler{
noUpdateDisabled = true; noUpdateDisabled = true;
canOverdrive = false; canOverdrive = false;
priority = TargetPriority.transport; priority = TargetPriority.transport;
//conduits don't need to update
update = false;
destructible = true;
} }
@Override @Override
@@ -148,10 +158,78 @@ public class Conduit extends LiquidBlock implements Autotiler{
} }
public class ConduitBuild extends LiquidBuild implements ChainedBuilding{ public class ConduitBuild extends LiquidBuild implements ChainedBuilding{
public @Nullable ConduitGraph graph;
public float smoothLiquid; public float smoothLiquid;
public int blendbits, xscl = 1, yscl = 1, blending; public int blendbits, xscl = 1, yscl = 1, blending;
public boolean capped, backCapped = false; public boolean capped, backCapped = false;
protected void addGraphs(){
//connect self to every nearby graph
getConnections(other -> {
if(other.graph != null){
other.graph.merge(this);
}
});
//nothing to connect to
if(graph == null){
new ConduitGraph().merge(this);
}
}
protected void removeGraphs(){
//graph is getting recalculated, no longer valid
if(graph != null){
graph.checkRemove();
graph.remove(this);
graph = null; //TODO ?????
}
getConnections(other -> new ConduitGraph().reflow(this, other));
}
@Override
public void control(LAccess type, double p1, double p2, double p3, double p4){
if(type == LAccess.enabled){
boolean shouldEnable = !Mathf.zero((float)p1);
if(enabled != shouldEnable){
if(graph != null){
//keep track of how many conduits are disabled, so the graph can stop working
if(shouldEnable){
graph.disabledConduits --;
}else{
graph.disabledConduits ++;
}
}
enabled = shouldEnable;
}
}
}
@Override
public void onAdded(){
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 @Override
public void draw(){ public void draw(){
int r = this.rotation; int r = this.rotation;
@@ -173,6 +251,21 @@ public class Conduit extends LiquidBlock implements Autotiler{
if(capped && capRegion.found()) Draw.rect(capRegion, x, y, rotdeg()); if(capped && capRegion.found()) Draw.rect(capRegion, x, y, rotdeg());
if(backCapped && capRegion.found()) Draw.rect(capRegion, x, y, rotdeg() + 180); if(backCapped && capRegion.found()) Draw.rect(capRegion, x, y, rotdeg() + 180);
if(debugGraphs){
//simple visualization that assigns random color to each graph
Mathf.rand.setSeed(graph == null ? -1 : graph.id);
Draw.color(Tmp.c1.rand());
Drawf.selected(tileX(), tileY(), block, Tmp.c1);
Draw.color(Pal.accent);
if(this == graph.head){
Fill.poly(x, y, 3, 2f, rotdeg());
}
Draw.color();
}
} }
protected void drawAt(float x, float y, int bits, int rotation, SliceMode slice){ protected void drawAt(float x, float y, int bits, int rotation, SliceMode slice){
@@ -196,7 +289,7 @@ public class Conduit extends LiquidBlock implements Autotiler{
//the drawing state machine sure was a great design choice with no downsides or hidden behavior!!! //the drawing state machine sure was a great design choice with no downsides or hidden behavior!!!
float xscl = Draw.xscl, yscl = Draw.yscl; float xscl = Draw.xscl, yscl = Draw.yscl;
Draw.scl(1f, 1f); Draw.scl(1f, 1f);
Drawf.liquid(sliced(liquidr, slice), x + ox, y + oy, smoothLiquid, liquids.current().color.write(Tmp.c1).a(1f)); Drawf.liquid(sliced(liquidr, slice), x + ox, y + oy, graph == null ? smoothLiquid : graph.smoothLiquid, liquids.current().color.write(Tmp.c1).a(1f));
Draw.scl(xscl, yscl); Draw.scl(xscl, yscl);
Draw.rect(sliced(topRegions[bits], slice), x, y, angle); Draw.rect(sliced(topRegions[bits], slice), x, y, angle);
@@ -225,15 +318,15 @@ public class Conduit extends LiquidBlock implements Autotiler{
} }
@Override @Override
public void updateTile(){ public LiquidModule writeLiquids(){
smoothLiquid = Mathf.lerpDelta(smoothLiquid, liquids.currentAmount() / liquidCapacity, 0.05f); //"saved" liquids are based on a fraction, essentially splitting apart and re-joining
tempLiquids.set(liquids, graph == null ? 1f : block.liquidCapacity / graph.totalCapacity);
if(liquids.currentAmount() > 0.0001f && timer(timerFlow, 1)){ return tempLiquids;
moveLiquidForward(leaks, liquids.current());
noSleep();
}else{
sleep();
} }
@Override
public float liquidCapacity(){
return graph == null ? block.liquidCapacity : graph.totalCapacity;
} }
@Nullable @Nullable
@@ -245,5 +338,195 @@ public class Conduit extends LiquidBlock implements Autotiler{
} }
return null; return null;
} }
@Override
public void writeAll(Writes write){
super.writeAll(write);
}
/** Calls callback with every conduit that transfers fluids to this one. */
public void getConnections(Cons<ConduitBuild> cons){
for(var other : proximity){
if(canMerge(other)){
cons.get((ConduitBuild)other);
}
}
}
public boolean canMerge(Building other){
return
other instanceof ConduitBuild conduit && other.team == team &&
(front() == conduit || other.front() == this) &&
(other.liquids.current() == liquids.current() || other.liquids.currentAmount() <= mergeThreshold || liquids.currentAmount() <= mergeThreshold);
}
}
/*
TODO:
- [X] liquids shared as one inventory
- [X] liquids merged when placing
- [X] liquids split when breaking
- [X] liquids saved
- [X] liquids accept input
- [X] liquids transfer forward
- [X] liquids leak
- [X] liquids display properly (including flow rate)
- [X] liquids merge different types correctly
- [X] conduits can (or can't) be disabled
*/
public static class ConduitGraph{
private static final IntSet closedSet = new IntSet(), headSet = new IntSet();
private static final Queue<ConduitBuild> queue = new Queue<>();
static int lastId = 0;
public final int id = lastId ++;
public float smoothLiquid;
/** if any are disabled, does not update */
private int disabledConduits;
private Seq<ConduitBuild> conduits = new Seq<>();
private final @Nullable ConduitGraphUpdater entity;
private LiquidModule liquids = new LiquidModule();
private float totalCapacity;
public @Nullable ConduitBuild head;
public ConduitGraph(){
entity = ConduitGraphUpdater.create();
entity.graph = this;
}
public void update(){
smoothLiquid = Mathf.lerpDelta(smoothLiquid, liquids.currentAmount() / totalCapacity, 0.05f);
if(disabledConduits > 0) return;
if(head != null){
//move forward as the head
if(liquids.currentAmount() > 0.0001f && head.timer(((Conduit)head.block).timerFlow, 1)){
head.moveLiquidForward(((Conduit)head.block).leaks, liquids.current());
}
//merge with front if one of the conduits becomes empty
if(head.front() instanceof ConduitBuild build && build.graph != this && head.canMerge(build)){
merge(build);
}
}
}
public void checkAdd(){
if(entity != null) entity.add();
}
public void checkRemove(){
if(entity != null) entity.remove();
}
public void remove(ConduitBuild build){
float fraction = build.block.liquidCapacity / totalCapacity;
//remove fraction of liquids based on what part this conduit constituted
//e.g. 70% of capacity was made up by this conduit = multiply liquids by 0.3 (remove 70%)
liquids.mul(1f - fraction);
totalCapacity -= build.block.liquidCapacity;
}
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, ignore);
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, like power graphs?
for(var cond : other.graph.conduits){
assign(cond);
}
}else{
assign(other);
}
}
protected void assign(ConduitBuild build){
assign(build, null);
}
protected void assign(ConduitBuild build, @Nullable Building ignore){
if(build.graph != this){
//merge graph liquids - TODO - how does this react to different types
if(build.graph != null){
build.graph.checkRemove();
//add liquids based on what fraction it made up
liquids.add(build.liquids, build.block.liquidCapacity / build.graph.totalCapacity);
}else{
//simple direct liquid merge
liquids.add(build.liquids);
}
totalCapacity += build.block.liquidCapacity;
build.graph = this;
build.liquids = liquids;
conduits.add(build);
checkAdd();
//re-validate head
if(head == null){
head = build;
}
//find the best head block
headSet.clear();
headSet.add(head.id);
while(true){
var next = head.front();
if(next instanceof ConduitBuild cond && cond.team == head.team && next != ignore && cond.graph == this){
if(!headSet.add(next.id)){
//there's a loop, which means a head does not exist
head = null;
break;
}else{
head = cond;
}
}else{
//found the end
break;
}
}
//snap smoothLiquid so it doesn't start at 0
smoothLiquid = liquids.currentAmount() / totalCapacity;
}
}
} }
} }

View File

@@ -24,7 +24,7 @@ public class DrawLiquidRegion extends DrawBlock{
public void draw(Building build){ public void draw(Building build){
Liquid drawn = drawLiquid != null ? drawLiquid : build.liquids.current(); Liquid drawn = drawLiquid != null ? drawLiquid : build.liquids.current();
Drawf.liquid(liquid, build.x, build.y, Drawf.liquid(liquid, build.x, build.y,
build.liquids.get(drawn) / build.block.liquidCapacity * alpha, build.liquids.get(drawn) / build.liquidCapacity() * alpha,
drawn.color drawn.color
); );
} }

View File

@@ -64,6 +64,12 @@ public class LiquidModule extends BlockModule{
} }
} }
public void mul(float amount){
for(int i = 0; i < liquids.length; i ++){
liquids[i] *= amount;
}
}
public void stopFlow(){ public void stopFlow(){
flow = null; flow = null;
} }
@@ -107,6 +113,27 @@ public class LiquidModule extends BlockModule{
Arrays.fill(liquids, 0); Arrays.fill(liquids, 0);
} }
public void add(LiquidModule other){
add(other, 1f);
}
public void add(LiquidModule other, float mul){
for(int i = 0; i < liquids.length; i ++){
liquids[i] += other.liquids[i] * mul;
if(liquids[i] > liquids[current.id]){
current = content.liquid(i);
}
}
}
public void set(LiquidModule other, float mul){
current = other.current;
for(int i = 0; i < liquids.length; i ++){
liquids[i] = other.liquids[i] * mul;
}
}
public void add(Liquid liquid, float amount){ public void add(Liquid liquid, float amount){
liquids[liquid.id] += amount; liquids[liquid.id] += amount;
current = liquid; current = liquid;
@@ -180,6 +207,20 @@ public class LiquidModule extends BlockModule{
} }
} }
@Override
public String toString(){
var res = new StringBuilder();
res.append("LiquidModule{ current=").append(current).append(", ");
for(int i = 0; i < liquids.length; i++){
if(liquids[i] > 0){
res.append(content.liquid(i).name).append(":").append(liquids[i]).append(", ");
}
}
res.setLength(res.length() - 2);
res.append("}");
return res.toString();
}
public interface LiquidConsumer{ public interface LiquidConsumer{
void accept(Liquid liquid, float amount); void accept(Liquid liquid, float amount);
} }

View File

@@ -25,4 +25,4 @@ org.gradle.caching=true
#used for slow jitpack builds; TODO see if this actually works #used for slow jitpack builds; TODO see if this actually works
org.gradle.internal.http.socketTimeout=100000 org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000 org.gradle.internal.http.connectionTimeout=100000
archash=77461f1c82 archash=eb3b8bdd10