From e481de9d28ce442ea8628e91027dc99c31c3895f Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 16 Dec 2021 10:31:16 -0500 Subject: [PATCH] Payload router sorter mode --- core/assets/bundles/bundle.properties | 2 +- core/src/mindustry/ai/BaseAI.java | 1 - core/src/mindustry/content/Blocks.java | 3 + .../mindustry/entities/comp/BuildingComp.java | 8 + core/src/mindustry/graphics/Drawf.java | 4 +- .../maps/generators/BaseGenerator.java | 1 - core/src/mindustry/mod/ClassMap.java | 10 +- core/src/mindustry/type/BlockSeq.java | 24 +- core/src/mindustry/world/Block.java | 2 + .../blocks/defense/turrets/PayloadTurret.java | 169 +++++++++ .../distribution/DirectionalUnloader.java | 12 +- .../world/blocks/distribution/DuctRouter.java | 12 +- .../blocks/distribution/PayloadConveyor.java | 355 +---------------- .../blocks/distribution/PayloadRouter.java | 98 +---- .../world/blocks/distribution/Sorter.java | 12 +- .../world/blocks/payloads/Constructor.java | 13 +- .../blocks/payloads/PayloadConveyor.java | 358 ++++++++++++++++++ .../world/blocks/payloads/PayloadRouter.java | 208 ++++++++++ .../world/blocks/payloads/PayloadSource.java | 12 +- .../world/blocks/sandbox/ItemSource.java | 12 +- .../world/blocks/sandbox/LiquidSource.java | 12 +- .../world/blocks/storage/Unloader.java | 12 +- .../world/blocks/units/UnitAssembler.java | 1 - .../blocks/units/UnitCargoUnloadPoint.java | 12 +- .../world/blocks/units/UnitFactory.java | 12 +- .../world/consumers/ConsumePayloadFilter.java | 66 ++++ .../world/consumers/ConsumePayloads.java | 3 +- 27 files changed, 866 insertions(+), 568 deletions(-) create mode 100644 core/src/mindustry/world/blocks/defense/turrets/PayloadTurret.java create mode 100644 core/src/mindustry/world/blocks/payloads/PayloadConveyor.java create mode 100644 core/src/mindustry/world/blocks/payloads/PayloadRouter.java create mode 100644 core/src/mindustry/world/consumers/ConsumePayloadFilter.java diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index abfecb82bc..9291b82ecd 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1469,7 +1469,7 @@ liquid.oil.description = Used in advanced material production and as incendiary liquid.cryofluid.description = Used as coolant in reactors, turrets and factories. block.derelict =  [lightgray]Derelict -block.armored-conveyor.description = Moves items forward. Does not accept inputs from the sides. +block.armored-conveyor.description = Moves items forward. Does not accept non-conveyor inputs from the sides. block.illuminator.description = Emits light. block.message.description = Stores a message for communication between allies. block.graphite-press.description = Compresses coal into graphite. diff --git a/core/src/mindustry/ai/BaseAI.java b/core/src/mindustry/ai/BaseAI.java index 7643d0e804..7b3d0a54ef 100644 --- a/core/src/mindustry/ai/BaseAI.java +++ b/core/src/mindustry/ai/BaseAI.java @@ -16,7 +16,6 @@ import mindustry.maps.generators.*; import mindustry.type.*; import mindustry.world.*; import mindustry.world.blocks.defense.*; -import mindustry.world.blocks.distribution.*; import mindustry.world.blocks.payloads.*; import mindustry.world.blocks.production.*; import mindustry.world.blocks.storage.*; diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 03dcddd5e5..7546eaa6cc 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -23,6 +23,8 @@ import mindustry.world.blocks.legacy.*; import mindustry.world.blocks.liquid.*; import mindustry.world.blocks.logic.*; import mindustry.world.blocks.payloads.*; +import mindustry.world.blocks.payloads.PayloadConveyor; +import mindustry.world.blocks.payloads.PayloadRouter; import mindustry.world.blocks.power.*; import mindustry.world.blocks.production.*; import mindustry.world.blocks.sandbox.*; @@ -3321,6 +3323,7 @@ public class Blocks{ droneType = UnitTypes.manifold; requirements = BlockStack.list(Blocks.thoriumWallLarge, 4, Blocks.duct, 2); consumes.power(1f); + areaSize = 13; droneType = UnitTypes.assemblyDrone; }}; diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 81d901e53b..7d7cf7d157 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1365,6 +1365,14 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, * @return whether or not this block should be deselected. */ public boolean onConfigureTileTapped(Building other){ + if(block.clearOnDoubleTap){ + if(self() == other){ + deselect(); + configure(null); + return false; + } + return true; + } return self() != other; } diff --git a/core/src/mindustry/graphics/Drawf.java b/core/src/mindustry/graphics/Drawf.java index 3698e3f32d..9e3af3ce37 100644 --- a/core/src/mindustry/graphics/Drawf.java +++ b/core/src/mindustry/graphics/Drawf.java @@ -25,6 +25,7 @@ public class Drawf{ flame(x, y, divisions, rotation, length, width, pan, 0f); } + //TODO offset unused public static void flame(float x, float y, int divisions, float rotation, float length, float width, float pan, float offset){ float len1 = length * pan, len2 = length * (1f - pan); @@ -107,7 +108,8 @@ public class Drawf{ public static void dashLine(Color color, float x, float y, float x2, float y2){ int segments = (int)(Math.max(Math.abs(x - x2), Math.abs(y - y2)) / tilesize * 2); - Lines.stroke(3f, Pal.gray); + Lines.stroke(3f); + Draw.color(Pal.gray, color.a); Lines.dashLine(x, y, x2, y2, segments); Lines.stroke(1f, color); Lines.dashLine(x, y, x2, y2, segments); diff --git a/core/src/mindustry/maps/generators/BaseGenerator.java b/core/src/mindustry/maps/generators/BaseGenerator.java index 7cbe7b8487..d6e698e886 100644 --- a/core/src/mindustry/maps/generators/BaseGenerator.java +++ b/core/src/mindustry/maps/generators/BaseGenerator.java @@ -14,7 +14,6 @@ import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; import mindustry.world.blocks.defense.*; -import mindustry.world.blocks.distribution.*; import mindustry.world.blocks.payloads.*; import mindustry.world.blocks.power.*; import mindustry.world.blocks.production.*; diff --git a/core/src/mindustry/mod/ClassMap.java b/core/src/mindustry/mod/ClassMap.java index 839410441d..7a9cee4aed 100644 --- a/core/src/mindustry/mod/ClassMap.java +++ b/core/src/mindustry/mod/ClassMap.java @@ -1,6 +1,8 @@ package mindustry.mod; import arc.struct.*; +import mindustry.world.blocks.payloads.*; + /** Generated class. Maps simple class names to concrete classes. For use in JSON mods. */ @SuppressWarnings("deprecation") public class ClassMap{ @@ -152,10 +154,10 @@ public class ClassMap{ classes.put("MassDriverBuild", mindustry.world.blocks.distribution.MassDriver.MassDriverBuild.class); classes.put("OverflowGate", mindustry.world.blocks.distribution.OverflowGate.class); classes.put("OverflowGateBuild", mindustry.world.blocks.distribution.OverflowGate.OverflowGateBuild.class); - classes.put("PayloadConveyor", mindustry.world.blocks.distribution.PayloadConveyor.class); - classes.put("PayloadConveyorBuild", mindustry.world.blocks.distribution.PayloadConveyor.PayloadConveyorBuild.class); - classes.put("PayloadRouter", mindustry.world.blocks.distribution.PayloadRouter.class); - classes.put("PayloadRouterBuild", mindustry.world.blocks.distribution.PayloadRouter.PayloadRouterBuild.class); + classes.put("PayloadConveyor", PayloadConveyor.class); + classes.put("PayloadConveyorBuild", PayloadConveyor.PayloadConveyorBuild.class); + classes.put("PayloadRouter", PayloadRouter.class); + classes.put("PayloadRouterBuild", PayloadRouter.PayloadRouterBuild.class); classes.put("Router", mindustry.world.blocks.distribution.Router.class); classes.put("RouterBuild", mindustry.world.blocks.distribution.Router.RouterBuild.class); classes.put("Sorter", mindustry.world.blocks.distribution.Sorter.class); diff --git a/core/src/mindustry/type/BlockSeq.java b/core/src/mindustry/type/BlockSeq.java index e5fc203b6e..542387cc14 100644 --- a/core/src/mindustry/type/BlockSeq.java +++ b/core/src/mindustry/type/BlockSeq.java @@ -7,13 +7,27 @@ import mindustry.world.*; public class BlockSeq{ private ObjectIntMap blocks = new ObjectIntMap<>(); + private int total; + + public boolean isEmpty(){ + return total == 0; + } + + public boolean any(){ + return total > 0; + } + + public int total(){ + return total; + } public void add(Block block){ - blocks.increment(block); + add(block, 1); } public void add(Block block, int amount){ blocks.increment(block, amount); + total += amount; } public void remove(Block block){ @@ -30,6 +44,7 @@ public class BlockSeq{ public void clear(){ blocks.clear(); + total = 0; } public int get(Block block){ @@ -44,6 +59,10 @@ public class BlockSeq{ return get(block) >= amount; } + public boolean contains(Block block){ + return get(block) >= 1; + } + public boolean contains(BlockStack stack){ return get(stack.block) >= stack.amount; } @@ -57,9 +76,10 @@ public class BlockSeq{ } public void read(Reads read){ + total = 0; short amount = read.s(); for(int i = 0; i < amount; i++){ - blocks.put(Vars.content.block(read.s()), read.i()); + add(Vars.content.block(read.s()), read.i()); } } } diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index 9a1e18e1d5..ed29bb73b5 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -76,6 +76,8 @@ public class Block extends UnlockableContent{ public boolean saveConfig = false; /** whether to allow copying the config through middle click */ public boolean copyConfig = true; + /** if true, double-tapping this configurable block clears configuration. */ + public boolean clearOnDoubleTap = false; /** whether this block has a tile entity that updates */ public boolean update; /** whether this block has health and can be destroyed */ diff --git a/core/src/mindustry/world/blocks/defense/turrets/PayloadTurret.java b/core/src/mindustry/world/blocks/defense/turrets/PayloadTurret.java new file mode 100644 index 0000000000..fe3ab4fffd --- /dev/null +++ b/core/src/mindustry/world/blocks/defense/turrets/PayloadTurret.java @@ -0,0 +1,169 @@ +package mindustry.world.blocks.defense.turrets; + +import arc.scene.ui.layout.*; +import arc.struct.*; +import arc.util.io.*; +import mindustry.entities.bullet.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.type.*; +import mindustry.ui.*; +import mindustry.world.*; +import mindustry.world.blocks.payloads.*; +import mindustry.world.consumers.*; +import mindustry.world.meta.*; + +import static mindustry.Vars.*; + +//TODO visuals! +public class PayloadTurret extends Turret{ + public ObjectMap ammoTypes = new ObjectMap<>(); + + protected Block[] ammoKeys; + + public PayloadTurret(String name){ + super(name); + + maxAmmo = 3; + } + + /** Initializes accepted ammo map. Format: [block1, bullet1, block2, bullet2...] */ + public void ammo(Object... objects){ + ammoTypes = ObjectMap.of(objects); + } + + /** Makes copies of all bullets and limits their range. */ + public void limitRange(){ + limitRange(1f); + } + + /** Makes copies of all bullets and limits their range. */ + public void limitRange(float margin){ + for(var entry : ammoTypes.copy().entries()){ + var copy = entry.value.copy(); + copy.lifetime = (range + margin) / copy.speed; + ammoTypes.put(entry.key, copy); + } + } + + @Override + public void setStats(){ + super.setStats(); + + stats.remove(Stat.itemCapacity); + stats.add(Stat.ammo, StatValues.ammo(ammoTypes)); + } + + @Override + public void init(){ + consumes.add(new ConsumePayloadFilter(i -> ammoTypes.containsKey(i)){ + @Override + public void build(Building build, Table table){ + MultiReqImage image = new MultiReqImage(); + content.blocks().each(i -> filter.get(i) && i.unlockedNow(), block -> image.add(new ReqImage(new ItemImage(block.uiIcon), + () -> build instanceof PayloadTurretBuild it && !it.blocks.isEmpty() && it.currentBlock() == block))); + + table.add(image).size(8 * 4); + } + + @Override + public boolean valid(Building build){ + //valid when there's any ammo in the turret + return build instanceof PayloadTurretBuild it && it.blocks.any(); + } + + @Override + public void display(Stats stats){ + //don't display + } + }); + + ammoKeys = ammoTypes.keys().toSeq().toArray(Block.class); + + super.init(); + } + + public class PayloadTurretBuild extends TurretBuild{ + public BlockSeq blocks = new BlockSeq(); + + public Block currentBlock(){ + for(Block block : ammoKeys){ + if(blocks.contains(block)){ + return block; + } + } + return null; + } + + @Override + public boolean acceptPayload(Building source, Payload payload){ + return payload instanceof BuildPayload build && blocks.total() < maxAmmo && ammoTypes.containsKey(build.block()); + } + + @Override + public void handlePayload(Building source, Payload payload){ + blocks.add(((BuildPayload)payload).block()); + } + + @Override + public boolean hasAmmo(){ + return blocks.total() > 0; + } + + @Override + public BulletType useAmmo(){ + ejectEffects(); + for(Block block : ammoKeys){ + if(blocks.contains(block)){ + blocks.remove(block); + return ammoTypes.get(block); + } + } + return null; + } + + @Override + public BulletType peekAmmo(){ + for(Block block : ammoKeys){ + if(blocks.contains(block)){ + return ammoTypes.get(block); + } + } + return null; + } + + @Override + public BlockSeq getBlockPayloads(){ + return blocks; + } + + @Override + public void updateTile(){ + totalAmmo = blocks.total(); + unit.ammo((float)unit.type().ammoCapacity * totalAmmo / maxAmmo); + + super.updateTile(); + } + + @Override + public void displayBars(Table bars){ + super.displayBars(bars); + + bars.add(new Bar("stat.ammo", Pal.ammo, () -> (float)totalAmmo / maxAmmo)).growX(); + bars.row(); + } + + @Override + public void write(Writes write){ + super.write(write); + blocks.write(write); + } + + @Override + public void read(Reads read, byte revision){ + super.read(read, revision); + blocks.read(read); + //TODO remove invalid ammo + } + } +} diff --git a/core/src/mindustry/world/blocks/distribution/DirectionalUnloader.java b/core/src/mindustry/world/blocks/distribution/DirectionalUnloader.java index 7a780dd8df..092edeb421 100644 --- a/core/src/mindustry/world/blocks/distribution/DirectionalUnloader.java +++ b/core/src/mindustry/world/blocks/distribution/DirectionalUnloader.java @@ -34,6 +34,7 @@ public class DirectionalUnloader extends Block{ noUpdateDisabled = true; unloadable = false; envDisabled = Env.none; + clearOnDoubleTap = true; config(Item.class, (DirectionalUnloaderBuild tile, Item item) -> tile.unloadItem = item); configClear((DirectionalUnloaderBuild tile) -> tile.unloadItem = null); @@ -125,17 +126,6 @@ public class DirectionalUnloader extends Block{ ItemSelection.buildTable(DirectionalUnloader.this, table, content.items(), () -> unloadItem, this::configure); } - @Override - public boolean onConfigureTileTapped(Building other){ - if(this == other){ - deselect(); - configure(null); - return false; - } - - return true; - } - @Override public Item config(){ return unloadItem; diff --git a/core/src/mindustry/world/blocks/distribution/DuctRouter.java b/core/src/mindustry/world/blocks/distribution/DuctRouter.java index 0e2b7be04f..4b6cd8a7c2 100644 --- a/core/src/mindustry/world/blocks/distribution/DuctRouter.java +++ b/core/src/mindustry/world/blocks/distribution/DuctRouter.java @@ -33,6 +33,7 @@ public class DuctRouter extends Block{ configurable = true; saveConfig = true; rotate = true; + clearOnDoubleTap = true; envEnabled = Env.space | Env.terrestrial | Env.underwater; config(Item.class, (DuctRouterBuild tile, Item item) -> tile.sortItem = item); @@ -110,17 +111,6 @@ public class DuctRouter extends Block{ ItemSelection.buildTable(DuctRouter.this, table, content.items(), () -> sortItem, this::configure); } - @Override - public boolean onConfigureTileTapped(Building other){ - if(this == other){ - deselect(); - configure(null); - return false; - } - - return true; - } - @Nullable public Building target(){ if(current == null) return null; diff --git a/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java b/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java index 4ec5827820..5dcfb64e26 100644 --- a/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java +++ b/core/src/mindustry/world/blocks/distribution/PayloadConveyor.java @@ -1,359 +1,14 @@ package mindustry.world.blocks.distribution; -import arc.*; -import arc.graphics.g2d.*; -import arc.math.*; -import arc.math.geom.*; -import arc.util.*; -import arc.util.io.*; -import mindustry.annotations.Annotations.*; -import mindustry.gen.*; -import mindustry.graphics.*; -import mindustry.world.*; -import mindustry.world.blocks.payloads.*; -import mindustry.world.meta.*; - -import static mindustry.Vars.*; - -public class PayloadConveyor extends Block{ - public float moveTime = 40f, moveForce = 201f; - public @Load("@-top") TextureRegion topRegion; - public @Load("@-edge") TextureRegion edgeRegion; - public Interp interp = Interp.pow5; - public float payloadLimit = 3f; +/** @deprecated use the class in the payload package instead */ +@Deprecated +public class PayloadConveyor extends mindustry.world.blocks.payloads.PayloadConveyor{ public PayloadConveyor(String name){ super(name); - group = BlockGroup.transportation; - size = 3; - rotate = true; - update = true; - outputsPayload = true; - noUpdateDisabled = true; - envEnabled |= Env.space; - sync = true; } - @Override - protected TextureRegion[] icons(){ - return new TextureRegion[]{Core.atlas.find(name + "-icon")}; + public class PayloadConveyorBuild extends mindustry.world.blocks.payloads.PayloadConveyor.PayloadConveyorBuild{ + } - - @Override - public void drawPlace(int x, int y, int rotation, boolean valid){ - super.drawPlace(x, y, rotation, valid); - - for(int i = 0; i < 4; i++){ - Building other = world.build(x + Geometry.d4x[i] * size, y + Geometry.d4y[i] * size); - if(other != null && other.block.outputsPayload && other.block.size == size){ - Drawf.selected(other.tileX(), other.tileY(), other.block, other.team.color); - } - } - } - - @Override - public void setStats(){ - super.setStats(); - - stats.add(Stat.payloadCapacity, (payloadLimit), StatUnit.blocksSquared); - } - - @Override - public void init(){ - super.init(); - - //increase clip size for oversize loads - clipSize = Math.max(clipSize, size * tilesize * 2.1f); - } - - public class PayloadConveyorBuild extends Building{ - public @Nullable Payload item; - public float progress, itemRotation, animation; - public float curInterp, lastInterp; - public @Nullable Building next; - public boolean blocked; - public int step = -1, stepAccepted = -1; - - @Override - public boolean canControlSelect(Unit unit){ - return this.item == null && unit.type.allowedInPayloads && !unit.spawnedByCore && unit.hitSize / tilesize <= payloadLimit && unit.tileOn() != null && unit.tileOn().build == this; - } - - @Override - public void onControlSelect(Unit player){ - handleUnitPayload(player, p -> item = p); - } - - @Override - public Payload takePayload(){ - Payload t = item; - item = null; - return t; - } - - @Override - public void onProximityUpdate(){ - super.onProximityUpdate(); - - Building accept = nearby(Geometry.d4(rotation).x * (size/2+1), Geometry.d4(rotation).y * (size/2+1)); - //next block must be aligned and of the same size - if(accept != null && ( - //same size - (accept.block.size == size && tileX() + Geometry.d4(rotation).x * size == accept.tileX() && tileY() + Geometry.d4(rotation).y * size == accept.tileY()) || - - //differing sizes - (accept.block.size > size && - (rotation % 2 == 0 ? //check orientation - Math.abs(accept.y - y) <= (accept.block.size * tilesize - size * tilesize)/2f : //check Y alignment - Math.abs(accept.x - x) <= (accept.block.size * tilesize - size * tilesize)/2f //check X alignment - )))){ - next = accept; - }else{ - next = null; - } - - int ntrns = 1 + size/2; - Tile next = tile.nearby(Geometry.d4(rotation).x * ntrns, Geometry.d4(rotation).y * ntrns); - blocked = (next != null && next.solid() && !(next.block().outputsPayload || next.block().acceptsPayload)) || (this.next != null && this.next.payloadCheck(rotation)); - } - - @Override - public Payload getPayload(){ - return item; - } - - @Override - public void updateTile(){ - if(!enabled) return; - - if(item != null){ - item.update(false); - } - - lastInterp = curInterp; - curInterp = fract(); - //rollover skip - if(lastInterp > curInterp) lastInterp = 0f; - progress = time() % moveTime; - - updatePayload(); - if(item != null && next == null){ - PayloadBlock.pushOutput(item, progress / moveTime); - } - - //TODO nondeterministic input priority - int curStep = curStep(); - if(curStep > step){ - boolean valid = step != -1; - step = curStep; - boolean had = item != null; - - if(valid && stepAccepted != curStep && item != null){ - if(next != null){ - //trigger update forward - next.updateTile(); - - //TODO add self to queue of next conveyor, then check if this conveyor was selected next frame - selection happens deterministically - if(next.acceptPayload(this, item)){ - //move forward. - next.handlePayload(this, item); - item = null; - moved(); - } - }else if(!blocked){ - //dump item forward - if(item.dump()){ - item = null; - moved(); - } - } - } - - if(had && item != null){ - moveFailed(); - } - } - } - - public void moveFailed(){ - - } - - public void moved(){ - - } - - public void drawBottom(){ - super.draw(); - } - - @Override - public void draw(){ - super.draw(); - - float dst = 0.8f; - - float glow = Math.max((dst - (Math.abs(fract() - 0.5f) * 2)) / dst, 0); - Draw.mixcol(team.color, glow); - - float trnext = fract() * size * tilesize, trprev = size * tilesize * (fract() - 1), rot = rotdeg(); - - TextureRegion clipped = clipRegion(tile.getHitbox(Tmp.r1), tile.getHitbox(Tmp.r2).move(trnext, 0), topRegion); - float s = tilesize * size; - - //next - Tmp.v1.set((s- clipped.width *Draw.scl) + clipped.width /2f*Draw.scl - s/2f, s- clipped.height *Draw.scl + clipped.height /2f*Draw.scl - s/2f).rotate(rot); - Draw.rect(clipped, x + Tmp.v1.x, y + Tmp.v1.y, rot); - - clipped = clipRegion(tile.getHitbox(Tmp.r1), tile.getHitbox(Tmp.r2).move(trprev, 0), topRegion); - - //prev - Tmp.v1.set(- s/2f + clipped.width /2f*Draw.scl, - s/2f + clipped.height /2f*Draw.scl).rotate(rot); - Draw.rect(clipped, x + Tmp.v1.x, y + Tmp.v1.y, rot); - - for(int i = 0; i < 4; i++){ - if(blends(i) && i != rotation){ - Draw.alpha(1f - Interp.pow5In.apply(fract())); - //prev from back - Tmp.v1.set(- s/2f + clipped.width /2f*Draw.scl, - s/2f + clipped.height /2f*Draw.scl).rotate(i * 90 + 180); - Draw.rect(clipped, x + Tmp.v1.x, y + Tmp.v1.y, i * 90 + 180); - } - } - - Draw.reset(); - - for(int i = 0; i < 4; i++){ - if(!blends(i)){ - Draw.rect(edgeRegion, x, y, i * 90); - } - } - - Draw.z(Layer.blockOver); - - if(item != null){ - item.draw(); - } - } - - @Override - public void payloadDraw(){ - Draw.rect(block.fullIcon,x, y); - } - - public float time(){ - return Time.time; - } - - @Override - public void unitOn(Unit unit){ - //calculate derivative of units moved last frame - float delta = (curInterp - lastInterp) * size * tilesize; - Tmp.v1.trns(rotdeg(), delta * moveForce).scl(1f / Math.max(unit.mass(), 201f)); - unit.move(Tmp.v1.x, Tmp.v1.y); - } - - @Override - public boolean acceptPayload(Building source, Payload payload){ - return this.item == null - && payload.fits(payloadLimit) - && (source == this || this.enabled && progress <= 5f); - } - - @Override - public void handlePayload(Building source, Payload payload){ - this.item = payload; - this.stepAccepted = curStep(); - this.itemRotation = source == this ? rotdeg() : source.angleTo(this); - this.animation = 0; - - updatePayload(); - } - - @Override - public void onRemoved(){ - super.onRemoved(); - if(item != null) item.dump(); - } - - @Override - public void write(Writes write){ - super.write(write); - - write.f(progress); - write.f(itemRotation); - Payload.write(item, write); - } - - @Override - public void read(Reads read, byte revision){ - super.read(read, revision); - - read.f(); //why is progress written? - itemRotation = read.f(); - item = Payload.read(read); - } - - public void updatePayload(){ - if(item != null){ - if(animation > fract()){ - animation = Mathf.lerp(animation, 0.8f, 0.15f); - } - - animation = Math.max(animation, fract()); - - float fract = animation; - float rot = Mathf.slerp(itemRotation, rotdeg(), fract); - - if(fract < 0.5f){ - Tmp.v1.trns(itemRotation + 180, (0.5f - fract) * tilesize * size); - }else{ - Tmp.v1.trns(rotdeg(), (fract - 0.5f) * tilesize * size); - } - - float vx = Tmp.v1.x, vy = Tmp.v1.y; - - item.set(x + vx, y + vy, rot); - } - } - - protected boolean blends(int direction){ - if(direction == rotation){ - return !blocked || next != null; - } - return PayloadBlock.blends(this, direction); - } - - protected TextureRegion clipRegion(Rect bounds, Rect sprite, TextureRegion region){ - Rect over = Tmp.r3; - - boolean overlaps = Intersector.intersectRectangles(bounds, sprite, over); - - TextureRegion out = Tmp.tr1; - out.set(region.texture); - - if(overlaps){ - float w = region.u2 - region.u; - float h = region.v2 - region.v; - float x = region.u, y = region.v; - float newX = (over.x - sprite.x) / sprite.width * w + x; - float newY = (over.y - sprite.y) / sprite.height * h + y; - float newW = (over.width / sprite.width) * w, newH = (over.height / sprite.height) * h; - - out.set(newX, newY, newX + newW, newY + newH); - }else{ - out.set(0f, 0f, 0f, 0f); - } - - return out; - } - - public int curStep(){ - return (int)((time()) / moveTime); - } - - public float fract(){ - return interp.apply(progress / moveTime); - } - } - } diff --git a/core/src/mindustry/world/blocks/distribution/PayloadRouter.java b/core/src/mindustry/world/blocks/distribution/PayloadRouter.java index 2a42ba8ac0..50db237fd0 100644 --- a/core/src/mindustry/world/blocks/distribution/PayloadRouter.java +++ b/core/src/mindustry/world/blocks/distribution/PayloadRouter.java @@ -1,104 +1,14 @@ package mindustry.world.blocks.distribution; -import arc.graphics.g2d.*; -import arc.math.*; -import arc.util.*; -import mindustry.annotations.Annotations.*; -import mindustry.entities.units.*; -import mindustry.gen.*; -import mindustry.graphics.*; -import mindustry.logic.*; -import mindustry.world.blocks.payloads.*; - -public class PayloadRouter extends PayloadConveyor{ - public @Load("@-over") TextureRegion overRegion; +/** @deprecated use the class in the payload package instead */ +@Deprecated +public class PayloadRouter extends mindustry.world.blocks.payloads.PayloadRouter{ public PayloadRouter(String name){ super(name); - - outputsPayload = true; - outputFacing = false; } - @Override - public void drawRequestRegion(BuildPlan plan, Eachable list){ - super.drawRequestRegion(plan, list); + public class PayloadRouterBuild extends mindustry.world.blocks.payloads.PayloadRouter.PayloadRouterBuild{ - Draw.rect(overRegion, plan.drawx(), plan.drawy()); - } - - public class PayloadRouterBuild extends PayloadConveyorBuild{ - public float smoothRot; - public float controlTime = -1f; - - @Override - public void add(){ - super.add(); - smoothRot = rotdeg(); - } - - public void pickNext(){ - if(item != null && controlTime <= 0f){ - int rotations = 0; - do{ - rotation = (rotation + 1) % 4; - onProximityUpdate(); - //force update to transfer if necessary - if(next instanceof PayloadConveyorBuild && !(next instanceof PayloadRouterBuild)){ - next.updateTile(); - } - //this condition intentionally uses "accept from itself" conditions, because payload conveyors only accept during the start - //"accept from self" conditions are for dropped payloads and are less restrictive - }while((blocked || next == null || !next.acceptPayload(next, item)) && ++rotations < 4); - } - } - - @Override - public void control(LAccess type, double p1, double p2, double p3, double p4){ - super.control(type, p1, p2, p3, p4); - if(type == LAccess.config){ - rotation = (int)p1; - //when manually controlled, routers do not turn automatically for a while, same as turrets - controlTime = Building.timeToUncontrol; - } - } - - @Override - public void handlePayload(Building source, Payload payload){ - super.handlePayload(source, payload); - pickNext(); - } - - @Override - public void moveFailed(){ - pickNext(); - } - - @Override - public void updateTile(){ - super.updateTile(); - - controlTime -= Time.delta; - smoothRot = Mathf.slerpDelta(smoothRot, rotdeg(), 0.2f); - } - - @Override - public void draw(){ - Draw.rect(region, x, y); - - float dst = 0.8f; - - Draw.mixcol(team.color, Math.max((dst - (Math.abs(fract() - 0.5f) * 2)) / dst, 0)); - Draw.rect(topRegion, x, y, smoothRot); - Draw.reset(); - - Draw.rect(overRegion, x, y); - - Draw.z(Layer.blockOver); - - if(item != null){ - item.draw(); - } - } } } diff --git a/core/src/mindustry/world/blocks/distribution/Sorter.java b/core/src/mindustry/world/blocks/distribution/Sorter.java index e14131dc27..9acc5f0a20 100644 --- a/core/src/mindustry/world/blocks/distribution/Sorter.java +++ b/core/src/mindustry/world/blocks/distribution/Sorter.java @@ -26,6 +26,7 @@ public class Sorter extends Block{ configurable = true; unloadable = false; saveConfig = true; + clearOnDoubleTap = true; config(Item.class, (SorterBuild tile, Item item) -> tile.sortItem = item); configClear((SorterBuild tile) -> tile.sortItem = null); @@ -127,17 +128,6 @@ public class Sorter extends Block{ ItemSelection.buildTable(Sorter.this, table, content.items(), () -> sortItem, this::configure); } - @Override - public boolean onConfigureTileTapped(Building other){ - if(this == other){ - deselect(); - configure(null); - return false; - } - - return true; - } - @Override public Item config(){ return sortItem; diff --git a/core/src/mindustry/world/blocks/payloads/Constructor.java b/core/src/mindustry/world/blocks/payloads/Constructor.java index 96016ad03a..1479cc090e 100644 --- a/core/src/mindustry/world/blocks/payloads/Constructor.java +++ b/core/src/mindustry/world/blocks/payloads/Constructor.java @@ -6,7 +6,6 @@ import arc.scene.ui.layout.*; import arc.util.*; import arc.util.io.*; import mindustry.*; -import mindustry.gen.*; import mindustry.world.*; import mindustry.world.blocks.*; import mindustry.world.blocks.storage.*; @@ -24,6 +23,7 @@ public class Constructor extends BlockProducer{ size = 3; configurable = true; + clearOnDoubleTap = true; configClear((ConstructorBuild tile) -> tile.recipe = null); config(Block.class, (ConstructorBuild tile, Block block) -> { @@ -59,17 +59,6 @@ public class Constructor extends BlockProducer{ ItemSelection.buildTable(Constructor.this, table, content.blocks().select(Constructor.this::canProduce), () -> recipe, this::configure); } - @Override - public boolean onConfigureTileTapped(Building other){ - if(this == other){ - deselect(); - configure(null); - return false; - } - - return true; - } - @Override public Object config(){ return recipe; diff --git a/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java b/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java new file mode 100644 index 0000000000..99df295cca --- /dev/null +++ b/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java @@ -0,0 +1,358 @@ +package mindustry.world.blocks.payloads; + +import arc.*; +import arc.graphics.g2d.*; +import arc.math.*; +import arc.math.geom.*; +import arc.util.*; +import arc.util.io.*; +import mindustry.annotations.Annotations.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.world.*; +import mindustry.world.meta.*; + +import static mindustry.Vars.*; + +public class PayloadConveyor extends Block{ + public float moveTime = 40f, moveForce = 201f; + public @Load("@-top") TextureRegion topRegion; + public @Load("@-edge") TextureRegion edgeRegion; + public Interp interp = Interp.pow5; + public float payloadLimit = 3f; + + public PayloadConveyor(String name){ + super(name); + group = BlockGroup.transportation; + size = 3; + rotate = true; + update = true; + outputsPayload = true; + noUpdateDisabled = true; + envEnabled |= Env.space; + sync = true; + } + + @Override + protected TextureRegion[] icons(){ + return new TextureRegion[]{Core.atlas.find(name + "-icon")}; + } + + @Override + public void drawPlace(int x, int y, int rotation, boolean valid){ + super.drawPlace(x, y, rotation, valid); + + for(int i = 0; i < 4; i++){ + Building other = world.build(x + Geometry.d4x[i] * size, y + Geometry.d4y[i] * size); + if(other != null && other.block.outputsPayload && other.block.size == size){ + Drawf.selected(other.tileX(), other.tileY(), other.block, other.team.color); + } + } + } + + @Override + public void setStats(){ + super.setStats(); + + stats.add(Stat.payloadCapacity, (payloadLimit), StatUnit.blocksSquared); + } + + @Override + public void init(){ + super.init(); + + //increase clip size for oversize loads + clipSize = Math.max(clipSize, size * tilesize * 2.1f); + } + + public class PayloadConveyorBuild extends Building{ + public @Nullable Payload item; + public float progress, itemRotation, animation; + public float curInterp, lastInterp; + public @Nullable Building next; + public boolean blocked; + public int step = -1, stepAccepted = -1; + + @Override + public boolean canControlSelect(Unit unit){ + return this.item == null && unit.type.allowedInPayloads && !unit.spawnedByCore && unit.hitSize / tilesize <= payloadLimit && unit.tileOn() != null && unit.tileOn().build == this; + } + + @Override + public void onControlSelect(Unit player){ + handleUnitPayload(player, p -> item = p); + } + + @Override + public Payload takePayload(){ + Payload t = item; + item = null; + return t; + } + + @Override + public void onProximityUpdate(){ + super.onProximityUpdate(); + + Building accept = nearby(Geometry.d4(rotation).x * (size/2+1), Geometry.d4(rotation).y * (size/2+1)); + //next block must be aligned and of the same size + if(accept != null && ( + //same size + (accept.block.size == size && tileX() + Geometry.d4(rotation).x * size == accept.tileX() && tileY() + Geometry.d4(rotation).y * size == accept.tileY()) || + + //differing sizes + (accept.block.size > size && + (rotation % 2 == 0 ? //check orientation + Math.abs(accept.y - y) <= (accept.block.size * tilesize - size * tilesize)/2f : //check Y alignment + Math.abs(accept.x - x) <= (accept.block.size * tilesize - size * tilesize)/2f //check X alignment + )))){ + next = accept; + }else{ + next = null; + } + + int ntrns = 1 + size/2; + Tile next = tile.nearby(Geometry.d4(rotation).x * ntrns, Geometry.d4(rotation).y * ntrns); + blocked = (next != null && next.solid() && !(next.block().outputsPayload || next.block().acceptsPayload)) || (this.next != null && this.next.payloadCheck(rotation)); + } + + @Override + public Payload getPayload(){ + return item; + } + + @Override + public void updateTile(){ + if(!enabled) return; + + if(item != null){ + item.update(false); + } + + lastInterp = curInterp; + curInterp = fract(); + //rollover skip + if(lastInterp > curInterp) lastInterp = 0f; + progress = time() % moveTime; + + updatePayload(); + if(item != null && next == null){ + PayloadBlock.pushOutput(item, progress / moveTime); + } + + //TODO nondeterministic input priority + int curStep = curStep(); + if(curStep > step){ + boolean valid = step != -1; + step = curStep; + boolean had = item != null; + + if(valid && stepAccepted != curStep && item != null){ + if(next != null){ + //trigger update forward + next.updateTile(); + + //TODO add self to queue of next conveyor, then check if this conveyor was selected next frame - selection happens deterministically + if(next.acceptPayload(this, item)){ + //move forward. + next.handlePayload(this, item); + item = null; + moved(); + } + }else if(!blocked){ + //dump item forward + if(item.dump()){ + item = null; + moved(); + } + } + } + + if(had && item != null){ + moveFailed(); + } + } + } + + public void moveFailed(){ + + } + + public void moved(){ + + } + + public void drawBottom(){ + super.draw(); + } + + @Override + public void draw(){ + super.draw(); + + float dst = 0.8f; + + float glow = Math.max((dst - (Math.abs(fract() - 0.5f) * 2)) / dst, 0); + Draw.mixcol(team.color, glow); + + float trnext = fract() * size * tilesize, trprev = size * tilesize * (fract() - 1), rot = rotdeg(); + + TextureRegion clipped = clipRegion(tile.getHitbox(Tmp.r1), tile.getHitbox(Tmp.r2).move(trnext, 0), topRegion); + float s = tilesize * size; + + //next + Tmp.v1.set((s- clipped.width *Draw.scl) + clipped.width /2f*Draw.scl - s/2f, s- clipped.height *Draw.scl + clipped.height /2f*Draw.scl - s/2f).rotate(rot); + Draw.rect(clipped, x + Tmp.v1.x, y + Tmp.v1.y, rot); + + clipped = clipRegion(tile.getHitbox(Tmp.r1), tile.getHitbox(Tmp.r2).move(trprev, 0), topRegion); + + //prev + Tmp.v1.set(- s/2f + clipped.width /2f*Draw.scl, - s/2f + clipped.height /2f*Draw.scl).rotate(rot); + Draw.rect(clipped, x + Tmp.v1.x, y + Tmp.v1.y, rot); + + for(int i = 0; i < 4; i++){ + if(blends(i) && i != rotation){ + Draw.alpha(1f - Interp.pow5In.apply(fract())); + //prev from back + Tmp.v1.set(- s/2f + clipped.width /2f*Draw.scl, - s/2f + clipped.height /2f*Draw.scl).rotate(i * 90 + 180); + Draw.rect(clipped, x + Tmp.v1.x, y + Tmp.v1.y, i * 90 + 180); + } + } + + Draw.reset(); + + for(int i = 0; i < 4; i++){ + if(!blends(i)){ + Draw.rect(edgeRegion, x, y, i * 90); + } + } + + Draw.z(Layer.blockOver); + + if(item != null){ + item.draw(); + } + } + + @Override + public void payloadDraw(){ + Draw.rect(block.fullIcon,x, y); + } + + public float time(){ + return Time.time; + } + + @Override + public void unitOn(Unit unit){ + //calculate derivative of units moved last frame + float delta = (curInterp - lastInterp) * size * tilesize; + Tmp.v1.trns(rotdeg(), delta * moveForce).scl(1f / Math.max(unit.mass(), 201f)); + unit.move(Tmp.v1.x, Tmp.v1.y); + } + + @Override + public boolean acceptPayload(Building source, Payload payload){ + return this.item == null + && payload.fits(payloadLimit) + && (source == this || this.enabled && progress <= 5f); + } + + @Override + public void handlePayload(Building source, Payload payload){ + this.item = payload; + this.stepAccepted = curStep(); + this.itemRotation = source == this ? rotdeg() : source.angleTo(this); + this.animation = 0; + + updatePayload(); + } + + @Override + public void onRemoved(){ + super.onRemoved(); + if(item != null) item.dump(); + } + + @Override + public void write(Writes write){ + super.write(write); + + write.f(progress); + write.f(itemRotation); + Payload.write(item, write); + } + + @Override + public void read(Reads read, byte revision){ + super.read(read, revision); + + read.f(); //why is progress written? + itemRotation = read.f(); + item = Payload.read(read); + } + + public void updatePayload(){ + if(item != null){ + if(animation > fract()){ + animation = Mathf.lerp(animation, 0.8f, 0.15f); + } + + animation = Math.max(animation, fract()); + + float fract = animation; + float rot = Mathf.slerp(itemRotation, rotdeg(), fract); + + if(fract < 0.5f){ + Tmp.v1.trns(itemRotation + 180, (0.5f - fract) * tilesize * size); + }else{ + Tmp.v1.trns(rotdeg(), (fract - 0.5f) * tilesize * size); + } + + float vx = Tmp.v1.x, vy = Tmp.v1.y; + + item.set(x + vx, y + vy, rot); + } + } + + protected boolean blends(int direction){ + if(direction == rotation){ + return !blocked || next != null; + } + return PayloadBlock.blends(this, direction); + } + + protected TextureRegion clipRegion(Rect bounds, Rect sprite, TextureRegion region){ + Rect over = Tmp.r3; + + boolean overlaps = Intersector.intersectRectangles(bounds, sprite, over); + + TextureRegion out = Tmp.tr1; + out.set(region.texture); + + if(overlaps){ + float w = region.u2 - region.u; + float h = region.v2 - region.v; + float x = region.u, y = region.v; + float newX = (over.x - sprite.x) / sprite.width * w + x; + float newY = (over.y - sprite.y) / sprite.height * h + y; + float newW = (over.width / sprite.width) * w, newH = (over.height / sprite.height) * h; + + out.set(newX, newY, newX + newW, newY + newH); + }else{ + out.set(0f, 0f, 0f, 0f); + } + + return out; + } + + public int curStep(){ + return (int)((time()) / moveTime); + } + + public float fract(){ + return interp.apply(progress / moveTime); + } + } + +} diff --git a/core/src/mindustry/world/blocks/payloads/PayloadRouter.java b/core/src/mindustry/world/blocks/payloads/PayloadRouter.java new file mode 100644 index 0000000000..be5a0144fc --- /dev/null +++ b/core/src/mindustry/world/blocks/payloads/PayloadRouter.java @@ -0,0 +1,208 @@ +package mindustry.world.blocks.payloads; + +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import arc.scene.ui.layout.*; +import arc.util.*; +import arc.util.io.*; +import mindustry.*; +import mindustry.annotations.Annotations.*; +import mindustry.ctype.*; +import mindustry.entities.units.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.logic.*; +import mindustry.type.*; +import mindustry.world.*; +import mindustry.world.blocks.*; +import mindustry.world.blocks.storage.*; + +import static mindustry.Vars.*; + +public class PayloadRouter extends PayloadConveyor{ + public @Load("@-over") TextureRegion overRegion; + + public PayloadRouter(String name){ + super(name); + + outputsPayload = true; + outputFacing = false; + configurable = true; + + config(Block.class, (PayloadRouterBuild tile, Block item) -> tile.sorted = item); + config(UnitType.class, (PayloadRouterBuild tile, UnitType item) -> tile.sorted = item); + configClear((PayloadRouterBuild tile) -> tile.sorted = null); + } + + @Override + public void drawRequestRegion(BuildPlan plan, Eachable list){ + super.drawRequestRegion(plan, list); + + Draw.rect(overRegion, plan.drawx(), plan.drawy()); + } + + public boolean canSort(Block b){ + return b.isVisible() && b.size <= size && !(b instanceof CoreBlock) && !state.rules.bannedBlocks.contains(b) && b.environmentBuildable(); + } + + public boolean canSort(UnitType t){ + return !t.isHidden() && !t.isBanned() && t.supportsEnv(state.rules.environment); + } + + public class PayloadRouterBuild extends PayloadConveyorBuild{ + public @Nullable UnlockableContent sorted; + public int recDir; + public boolean matches; + + public float smoothRot; + public float controlTime = -1f; + + @Override + public void add(){ + super.add(); + smoothRot = rotdeg(); + } + + public void pickNext(){ + if(item != null && controlTime <= 0f){ + if(matches){ + //when the item matches, always move forward. + rotation = recDir; + onProximityUpdate(); + }else{ + int rotations = 0; + do{ + rotation = (rotation + 1) % 4; + //if it doesn't match the sort item and this router is facing forward, skip this rotation + if(!matches && sorted != null && rotation == recDir){ + rotation ++; + } + onProximityUpdate(); + + //force update to transfer if necessary + if(next instanceof PayloadConveyorBuild && !(next instanceof PayloadRouterBuild)){ + next.updateTile(); + } + //this condition intentionally uses "accept from itself" conditions, because payload conveyors only accept during the start + //"accept from self" conditions are for dropped payloads and are less restrictive + }while((blocked || next == null || !next.acceptPayload(next, item)) && ++rotations < 4); + } + } + } + + @Override + public void control(LAccess type, double p1, double p2, double p3, double p4){ + super.control(type, p1, p2, p3, p4); + if(type == LAccess.config){ + rotation = (int)p1; + //when manually controlled, routers do not turn automatically for a while, same as turrets + controlTime = Building.timeToUncontrol; + } + } + + @Override + public void onControlSelect(Unit player){ + super.onControlSelect(player); + recDir = rotation; + checkMatch(); + } + + @Override + public void handlePayload(Building source, Payload payload){ + super.handlePayload(source, payload); + recDir = source == null ? rotation : source.relativeTo(this); + checkMatch(); + pickNext(); + } + + public void checkMatch(){ + matches = sorted != null && + (item instanceof BuildPayload build && build.block() == sorted) || + (item instanceof UnitPayload unit && unit.unit.type == sorted); + } + + @Override + public void moveFailed(){ + pickNext(); + } + + @Override + public void updateTile(){ + super.updateTile(); + + controlTime -= Time.delta; + smoothRot = Mathf.slerpDelta(smoothRot, rotdeg(), 0.2f); + } + + @Override + public void drawSelect(){ + if(sorted != null){ + float dx = x - size * tilesize/2f, dy = y + size * tilesize/2f, s = iconSmall / 4f; + Draw.mixcol(Color.darkGray, 1f); + Draw.rect(sorted.fullIcon, dx, dy - 1, s, s); + Draw.reset(); + Draw.rect(sorted.fullIcon, dx, dy, s, s); + } + } + + @Override + public void draw(){ + Draw.rect(region, x, y); + + float dst = 0.8f; + + Draw.mixcol(team.color, Math.max((dst - (Math.abs(fract() - 0.5f) * 2)) / dst, 0)); + Draw.rect(topRegion, x, y, smoothRot); + Draw.reset(); + + Draw.rect(overRegion, x, y); + + Draw.z(Layer.blockOver); + + if(item != null){ + item.draw(); + } + + //TODO draw sort item + } + + @Override + public void buildConfiguration(Table table){ + ItemSelection.buildTable(PayloadRouter.this, table, + content.blocks().select(PayloadRouter.this::canSort).as() + .and(content.units().select(PayloadRouter.this::canSort).as()), + () -> (UnlockableContent)config(), this::configure); + } + + @Override + public Object config(){ + return sorted; + } + + @Override + public byte version(){ + return 1; + } + + @Override + public void write(Writes write){ + super.write(write); + write.b(sorted == null ? -1 : sorted.getContentType().ordinal()); + write.s(sorted == null ? -1 : sorted.id); + write.b(recDir); + } + + @Override + public void read(Reads read, byte revision){ + super.read(read, revision); + if(revision >= 1){ + byte ctype = read.b(); + short sort = read.s(); + sorted = ctype == -1 ? null : Vars.content.getByID(ContentType.all[ctype], sort); + recDir = read.b(); + checkMatch(); + } + } + } +} diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java index a02e3bd29a..3175c06eff 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java @@ -31,6 +31,7 @@ public class PayloadSource extends PayloadBlock{ //make sure to display large units. clipSize = 120; noUpdateDisabled = true; + clearOnDoubleTap = true; config(Block.class, (PayloadSourceBuild build, Block block) -> { if(canProduce(block) && build.block != block){ @@ -91,17 +92,6 @@ public class PayloadSource extends PayloadBlock{ () -> (UnlockableContent)config(), this::configure); } - @Override - public boolean onConfigureTileTapped(Building other){ - if(this == other){ - deselect(); - configure(null); - return false; - } - - return true; - } - @Override public Object config(){ return unit == null ? block : unit; diff --git a/core/src/mindustry/world/blocks/sandbox/ItemSource.java b/core/src/mindustry/world/blocks/sandbox/ItemSource.java index c203b359b6..dc2cfbf2a3 100644 --- a/core/src/mindustry/world/blocks/sandbox/ItemSource.java +++ b/core/src/mindustry/world/blocks/sandbox/ItemSource.java @@ -26,6 +26,7 @@ public class ItemSource extends Block{ saveConfig = true; noUpdateDisabled = true; envEnabled = Env.any; + clearOnDoubleTap = true; config(Item.class, (ItemSourceBuild tile, Item item) -> tile.outputItem = item); configClear((ItemSourceBuild tile) -> tile.outputItem = null); @@ -91,17 +92,6 @@ public class ItemSource extends Block{ ItemSelection.buildTable(ItemSource.this, table, content.items(), () -> outputItem, this::configure); } - @Override - public boolean onConfigureTileTapped(Building other){ - if(this == other){ - deselect(); - configure(null); - return false; - } - - return true; - } - @Override public boolean acceptItem(Building source, Item item){ return false; diff --git a/core/src/mindustry/world/blocks/sandbox/LiquidSource.java b/core/src/mindustry/world/blocks/sandbox/LiquidSource.java index f47dd82c68..31cc98cbbb 100644 --- a/core/src/mindustry/world/blocks/sandbox/LiquidSource.java +++ b/core/src/mindustry/world/blocks/sandbox/LiquidSource.java @@ -32,6 +32,7 @@ public class LiquidSource extends Block{ displayFlow = false; group = BlockGroup.liquids; envEnabled = Env.any; + clearOnDoubleTap = true; config(Liquid.class, (LiquidSourceBuild tile, Liquid l) -> tile.source = l); configClear((LiquidSourceBuild tile) -> tile.source = null); @@ -87,17 +88,6 @@ public class LiquidSource extends Block{ ItemSelection.buildTable(LiquidSource.this, table, content.liquids(), () -> source, this::configure); } - @Override - public boolean onConfigureTileTapped(Building other){ - if(this == other){ - deselect(); - configure(null); - return false; - } - - return true; - } - @Override public Liquid config(){ return source; diff --git a/core/src/mindustry/world/blocks/storage/Unloader.java b/core/src/mindustry/world/blocks/storage/Unloader.java index d5c4d08897..6e696a7ec8 100644 --- a/core/src/mindustry/world/blocks/storage/Unloader.java +++ b/core/src/mindustry/world/blocks/storage/Unloader.java @@ -31,6 +31,7 @@ public class Unloader extends Block{ saveConfig = true; itemCapacity = 0; noUpdateDisabled = true; + clearOnDoubleTap = true; unloadable = false; config(Item.class, (UnloaderBuild tile, Item item) -> tile.sortItem = item); @@ -220,17 +221,6 @@ public class Unloader extends Block{ ItemSelection.buildTable(Unloader.this, table, content.items(), () -> sortItem, this::configure); } - @Override - public boolean onConfigureTileTapped(Building other){ - if(this == other){ - deselect(); - configure(null); - return false; - } - - return true; - } - @Override public Item config(){ return sortItem; diff --git a/core/src/mindustry/world/blocks/units/UnitAssembler.java b/core/src/mindustry/world/blocks/units/UnitAssembler.java index 666cd91795..40954fe446 100644 --- a/core/src/mindustry/world/blocks/units/UnitAssembler.java +++ b/core/src/mindustry/world/blocks/units/UnitAssembler.java @@ -68,7 +68,6 @@ public class UnitAssembler extends PayloadBlock{ public void setBars(){ super.setBars(); - //TODO progress bar bars.add("progress", (UnitAssemblerBuild e) -> new Bar("bar.progress", Pal.ammo, () -> e.progress)); bars.add("units", (UnitAssemblerBuild e) -> diff --git a/core/src/mindustry/world/blocks/units/UnitCargoUnloadPoint.java b/core/src/mindustry/world/blocks/units/UnitCargoUnloadPoint.java index 7e9e4ba917..d7a2e02c0d 100644 --- a/core/src/mindustry/world/blocks/units/UnitCargoUnloadPoint.java +++ b/core/src/mindustry/world/blocks/units/UnitCargoUnloadPoint.java @@ -27,6 +27,7 @@ public class UnitCargoUnloadPoint extends Block{ hasItems = true; configurable = true; saveConfig = true; + clearOnDoubleTap = true; flags = EnumSet.of(BlockFlag.unitCargoUnloadPoint); config(Item.class, (UnitCargoUnloadPointBuild build, Item item) -> build.item = item); @@ -76,17 +77,6 @@ public class UnitCargoUnloadPoint extends Block{ ItemSelection.buildTable(UnitCargoUnloadPoint.this, table, content.items(), () -> item, this::configure); } - @Override - public boolean onConfigureTileTapped(Building other){ - if(this == other){ - deselect(); - configure(null); - return false; - } - - return true; - } - @Override public Object config(){ return item; diff --git a/core/src/mindustry/world/blocks/units/UnitFactory.java b/core/src/mindustry/world/blocks/units/UnitFactory.java index de257a693b..fd8cd1c4ec 100644 --- a/core/src/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/mindustry/world/blocks/units/UnitFactory.java @@ -35,6 +35,7 @@ public class UnitFactory extends UnitBlock{ hasItems = true; solid = true; configurable = true; + clearOnDoubleTap = true; outputsPayload = true; rotate = true; @@ -166,17 +167,6 @@ public class UnitFactory extends UnitBlock{ } } - @Override - public boolean onConfigureTileTapped(Building other){ - if(this == other){ - deselect(); - configure(null); - return false; - } - - return true; - } - @Override public boolean acceptPayload(Building source, Payload payload){ return false; diff --git a/core/src/mindustry/world/consumers/ConsumePayloadFilter.java b/core/src/mindustry/world/consumers/ConsumePayloadFilter.java new file mode 100644 index 0000000000..5138532d97 --- /dev/null +++ b/core/src/mindustry/world/consumers/ConsumePayloadFilter.java @@ -0,0 +1,66 @@ +package mindustry.world.consumers; + +import arc.func.*; +import arc.scene.ui.layout.*; +import mindustry.*; +import mindustry.gen.*; +import mindustry.ui.*; +import mindustry.world.*; +import mindustry.world.meta.*; + +import static mindustry.Vars.*; + +public class ConsumePayloadFilter extends Consume{ + //cache fitting blocks to prevent search over all blocks later + protected final Block[] fitting; + + public Boolf filter; + + public ConsumePayloadFilter(Boolf filter){ + this.filter = filter; + this.fitting = Vars.content.blocks().select(filter).toArray(Block.class); + } + + @Override + public boolean valid(Building build){ + var payloads = build.getBlockPayloads(); + for(var block : fitting){ + if(payloads.contains(block, 1)){ + return true; + } + } + return false; + } + + @Override + public void trigger(Building build){ + var payloads = build.getBlockPayloads(); + for(var block : fitting){ + if(payloads.contains(block, 1)){ + payloads.remove(block); + return; + } + } + } + + @Override + public void display(Stats stats){ + stats.add(booster ? Stat.booster : Stat.input, StatValues.blocks(filter)); + } + + @Override + public void build(Building build, Table table){ + var inv = build.getBlockPayloads(); + + MultiReqImage image = new MultiReqImage(); + content.blocks().each(i -> filter.get(i) && i.unlockedNow(), block -> image.add(new ReqImage(new ItemImage(block.uiIcon, 1), + () -> inv.contains(block, 1)))); + + table.add(image).size(8 * 4); + } + + @Override + public ConsumeType type(){ + return ConsumeType.payload; + } +} diff --git a/core/src/mindustry/world/consumers/ConsumePayloads.java b/core/src/mindustry/world/consumers/ConsumePayloads.java index 67606cbea8..8296536f4e 100644 --- a/core/src/mindustry/world/consumers/ConsumePayloads.java +++ b/core/src/mindustry/world/consumers/ConsumePayloads.java @@ -1,6 +1,5 @@ package mindustry.world.consumers; -import arc.func.*; import arc.scene.ui.layout.*; import arc.struct.*; import mindustry.gen.*; @@ -11,7 +10,7 @@ import mindustry.world.meta.*; public class ConsumePayloads extends Consume{ public Seq payloads; - public ConsumePayloads(Seq payloads){ + public ConsumePayloads(Seq payloads){ this.payloads = payloads; }