From 80f5b4c3b7d702b048282069413dd0f5d9fec161 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 21 Oct 2018 17:02:37 -0400 Subject: [PATCH 1/4] Crashy storage graph implementation --- .../anuke/mindustry/content/fx/BlockFx.java | 4 +- .../anuke/mindustry/graphics/FogRenderer.java | 6 -- .../world/blocks/defense/ForceProjector.java | 15 +++- .../world/blocks/production/PhaseWeaver.java | 2 + .../world/blocks/storage/CoreBlock.java | 2 +- .../world/blocks/storage/StorageBlock.java | 41 ++++++++++ .../world/blocks/storage/StorageGraph.java | 79 +++++++++++++++++++ 7 files changed, 139 insertions(+), 10 deletions(-) create mode 100644 core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java diff --git a/core/src/io/anuke/mindustry/content/fx/BlockFx.java b/core/src/io/anuke/mindustry/content/fx/BlockFx.java index ff390d4558..2319d71586 100644 --- a/core/src/io/anuke/mindustry/content/fx/BlockFx.java +++ b/core/src/io/anuke/mindustry/content/fx/BlockFx.java @@ -322,9 +322,9 @@ public class BlockFx extends FxList implements ContentList{ }); shieldBreak = new Effect(40, e -> { - Draw.color(Color.WHITE); + Draw.color(Palette.accent); Lines.stroke(3f * e.fout()); - Lines.poly(e.x, e.y, 6, e.rotation, 90); + Lines.poly(e.x, e.y, 6, e.rotation + e.fin(), 90); Draw.reset(); }); } diff --git a/core/src/io/anuke/mindustry/graphics/FogRenderer.java b/core/src/io/anuke/mindustry/graphics/FogRenderer.java index 031abfe8c1..e974414838 100644 --- a/core/src/io/anuke/mindustry/graphics/FogRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/FogRenderer.java @@ -96,12 +96,6 @@ public class FogRenderer implements Disposable{ })); } - public void setLoadingOffset(int x, int y){ - isOffseted = true; - offsettedX = x; - offsettedY = y; - } - public void writeFog(){ if(buffer == null) return; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java index ad6aa4d585..41ddb64976 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/ForceProjector.java @@ -7,9 +7,11 @@ import io.anuke.mindustry.content.fx.BulletFx; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.traits.AbsorbTrait; import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.world.BarType; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; +import io.anuke.mindustry.world.meta.BlockBar; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; import io.anuke.ucore.core.Effects; @@ -68,6 +70,13 @@ public class ForceProjector extends Block { stats.add(BlockStat.powerDamage, powerDamage, StatUnit.powerUnits); } + @Override + public void setBars(){ + super.setBars(); + + bars.add(new BlockBar(BarType.heat, true, tile -> tile.entity().buildup / breakage)); + } + @Override public void update(Tile tile){ ForceEntity entity = tile.entity(); @@ -91,7 +100,7 @@ public class ForceProjector extends Block { } if(!entity.cons.valid() && !cheat){ - entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.1f); + entity.warmup = Mathf.lerpDelta(entity.warmup, 0f, 0.15f); if(entity.warmup <= 0.09f){ entity.broken = true; } @@ -136,6 +145,10 @@ public class ForceProjector extends Block { float hit = trait.getShieldDamage()*powerDamage; entity.hit = 1f; entity.power.amount -= Math.min(hit, entity.power.amount); + + if(entity.power.amount <= 0.0001f){ + entity.buildup += trait.getShieldDamage() * entity.warmup*2f; + } entity.buildup += trait.getShieldDamage() * entity.warmup; } }); diff --git a/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java b/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java index 2808b2c9bc..c14533d27f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/PhaseWeaver.java @@ -45,6 +45,7 @@ public class PhaseWeaver extends PowerSmelter{ Shaders.build.region = weaveRegion; Shaders.build.progress = progress; Shaders.build.color.set(Palette.accent); + Shaders.build.color.a = entity.heat; Shaders.build.time = -entity.time / 10f; Graphics.shader(Shaders.build, false); @@ -53,6 +54,7 @@ public class PhaseWeaver extends PowerSmelter{ Graphics.shader(); Draw.color(Palette.accent); + Draw.alpha(entity.heat); Lines.lineAngleCenter( tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 3f * size), diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java index 4e5f9875f9..2fa3d52cf8 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -242,7 +242,7 @@ public class CoreBlock extends StorageBlock{ return new CoreEntity(); } - public class CoreEntity extends TileEntity implements SpawnerTrait{ + public class CoreEntity extends StorageEntity implements SpawnerTrait{ public Unit currentUnit; int droneID = -1; boolean solid = true; diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java index 25f3d4a220..acb586fabb 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.world.blocks.storage; +import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; @@ -17,6 +18,42 @@ public abstract class StorageBlock extends Block{ return false; } + @Override + public void onProximityUpdate(Tile tile){ + super.onProximityUpdate(tile); + StorageEntity entity = tile.entity(); + entity.graph.add(tile); + + for(Tile prox : tile.entity.proximity()){ + if(prox.block() instanceof StorageBlock){ + StorageEntity other = prox.entity(); + entity.graph.merge(other.graph); + } + } + } + + @Override + public void removed(Tile tile){ + super.removed(tile); + StorageEntity entity = tile.entity(); + entity.graph.remove(tile); + } + + @Override + public TileEntity newEntity(){ + return new StorageEntity(); + } + + @Override + public Array getDebugInfo(Tile tile){ + Array arr = super.getDebugInfo(tile); + + StorageEntity entity = tile.entity(); + arr.addAll("storage graph", entity.graph.getID()); + + return arr; + } + /** * Removes an item and returns it. If item is not null, it should return the item. * Returns null if no items are there. @@ -48,4 +85,8 @@ public abstract class StorageBlock extends Block{ return entity.items.has(item); } } + + public class StorageEntity extends TileEntity{ + public StorageGraph graph = new StorageGraph(); + } } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java b/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java new file mode 100644 index 0000000000..6fbb31ec39 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java @@ -0,0 +1,79 @@ +package io.anuke.mindustry.world.blocks.storage; + +import com.badlogic.gdx.utils.IntSet; +import com.badlogic.gdx.utils.ObjectSet; +import com.badlogic.gdx.utils.Queue; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.storage.StorageBlock.StorageEntity; + +public class StorageGraph{ + private static IntSet closedSet = new IntSet(); + private static Queue queue = new Queue<>(); + private static int lastID; + + private ObjectSet tiles = new ObjectSet<>(); + private int cores; + private int id = lastID++; + + public void add(Tile tile){ + if(tiles.add(tile) && tile.block() instanceof CoreBlock){ + cores ++; + } + } + + public void remove(Tile tile){ + for(Tile other : tiles){ + other.entity().graph = null; + } + + if(tiles.remove(tile) && tile.block() instanceof CoreBlock){ + cores --; + } + + cores = 0; + + for(Tile other : tile.entity.proximity()){ + if(other.block() instanceof StorageBlock){ + reflow(tile, other); + } + } + } + + public void reflow(Tile base, Tile tile){ + queue.clear(); + queue.addLast(tile); + closedSet.clear(); + while(queue.size > 0){ + Tile child = queue.removeFirst(); + StorageEntity entity = child.entity(); + entity.graph = this; + add(child); + for(Tile next : child.entity.proximity()){ + if(next != base && next.block() instanceof StorageBlock && next.entity().graph == null && !closedSet.contains(next.packedPosition())){ + queue.addLast(next); + closedSet.add(next.packedPosition()); + } + } + } + } + + public void merge(StorageGraph other){ + if(this == other) return; + + for(Tile tile : other.tiles){ + StorageEntity e = tile.entity(); + e.graph = this; + } + + tiles.addAll(other.tiles); + cores += other.cores; + } + + public boolean hasCores(){ + return cores > 0; + } + + public int getID(){ + return id; + } +} From f9b70a37aa9a8aadc6ff53c7ccbab1b7d456a696 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 21 Oct 2018 17:20:08 -0400 Subject: [PATCH 2/4] Correct storage graphs --- .../io/anuke/mindustry/entities/TileEntity.java | 6 ++---- core/src/io/anuke/mindustry/world/Block.java | 14 ++++++++++++-- .../world/blocks/storage/StorageBlock.java | 6 ++---- .../world/blocks/storage/StorageGraph.java | 12 +++++------- .../io/anuke/mindustry/server/ServerControl.java | 2 +- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/core/src/io/anuke/mindustry/entities/TileEntity.java b/core/src/io/anuke/mindustry/entities/TileEntity.java index 98c7a767bb..426da9fb6c 100644 --- a/core/src/io/anuke/mindustry/entities/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/TileEntity.java @@ -157,9 +157,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ } public void removeFromProximity(){ - if(power != null){ - tile.block().powerGraphRemoved(tile); - } + tile.block().onProximityRemoved(tile); GridPoint2[] nearby = Edges.getEdges(tile.block().size); for(GridPoint2 point : nearby){ @@ -202,7 +200,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ proximity.add(tile); } - if(tile.block().hasPower) tile.block().updatePowerGraph(tile); + tile.block().onProximityAdded(tile); tile.block().onProximityUpdate(tile); } diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 85d38301d9..90e513763b 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -139,7 +139,17 @@ public class Block extends BaseBlock { return drops != null && drops.item == item; } - public void updatePowerGraph(Tile tile){ + public void onProximityRemoved(Tile tile){ + if(tile.entity.power != null){ + tile.block().powerGraphRemoved(tile); + } + } + + public void onProximityAdded(Tile tile){ + if(tile.block().hasPower) tile.block().updatePowerGraph(tile); + } + + protected void updatePowerGraph(Tile tile){ TileEntity entity = tile.entity(); for(Tile other : getPowerConnections(tile, tempTiles)){ @@ -149,7 +159,7 @@ public class Block extends BaseBlock { } } - public void powerGraphRemoved(Tile tile){ + protected void powerGraphRemoved(Tile tile){ tile.entity.power.graph.remove(tile); for(int i = 0; i < tile.entity.power.links.size; i++){ Tile other = world.tile(tile.entity.power.links.get(i)); diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java index acb586fabb..32c085756e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java @@ -19,8 +19,7 @@ public abstract class StorageBlock extends Block{ } @Override - public void onProximityUpdate(Tile tile){ - super.onProximityUpdate(tile); + public void onProximityAdded(Tile tile){ StorageEntity entity = tile.entity(); entity.graph.add(tile); @@ -33,8 +32,7 @@ public abstract class StorageBlock extends Block{ } @Override - public void removed(Tile tile){ - super.removed(tile); + public void onProximityRemoved(Tile tile){ StorageEntity entity = tile.entity(); entity.graph.remove(tile); } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java b/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java index 6fbb31ec39..a7f8c1feb9 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java @@ -26,15 +26,13 @@ public class StorageGraph{ other.entity().graph = null; } - if(tiles.remove(tile) && tile.block() instanceof CoreBlock){ - cores --; - } - cores = 0; for(Tile other : tile.entity.proximity()){ - if(other.block() instanceof StorageBlock){ - reflow(tile, other); + if(other.block() instanceof StorageBlock && other.entity().graph == null){ + StorageGraph graph = new StorageGraph(); + other.entity().graph = graph; + graph.reflow(tile, other); } } } @@ -58,7 +56,7 @@ public class StorageGraph{ } public void merge(StorageGraph other){ - if(this == other) return; + if(this == other || other == null) return; for(Tile tile : other.tiles){ StorageEntity e = tile.entity(); diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index b8a88fb15c..e9601b65dc 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -97,7 +97,7 @@ public class ServerControl extends Module{ world.sectors.save(); gameOvers = 0; inExtraRound = true; - Settings.putInt("sector_x", world.getSector().x + world.getSector().width); + Settings.putInt("sector_x", world.getSector().x + 1); Settings.save(); Call.onInfoMessage("[accent]Sector conquered![]\n" + roundExtraTime + " seconds until deployment in next sector."); From 67f574b5d8083b33cb3f848cfcb844d63ba19558 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 21 Oct 2018 19:49:32 -0400 Subject: [PATCH 3/4] Storage graph inventory sharing --- .../io/anuke/mindustry/core/NetClient.java | 4 +- .../anuke/mindustry/entities/TileEntity.java | 4 +- core/src/io/anuke/mindustry/world/Tile.java | 4 +- .../mindustry/world/blocks/BuildBlock.java | 4 +- .../world/blocks/storage/CoreBlock.java | 20 ----- .../world/blocks/storage/StorageBlock.java | 47 +++++++++++- .../world/blocks/storage/StorageGraph.java | 44 +++++++++-- .../mindustry/world/blocks/storage/Vault.java | 76 +------------------ .../world/blocks/units/UnitFactory.java | 4 +- .../{InventoryModule.java => ItemModule.java} | 10 ++- 10 files changed, 106 insertions(+), 111 deletions(-) rename core/src/io/anuke/mindustry/world/modules/{InventoryModule.java => ItemModule.java} (93%) diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index d934d62e61..57600cca6f 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -24,7 +24,7 @@ import io.anuke.mindustry.net.Packets.*; import io.anuke.mindustry.net.TraceInfo; import io.anuke.mindustry.net.ValidateException; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.modules.InventoryModule; +import io.anuke.mindustry.world.modules.ItemModule; import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Settings; import io.anuke.ucore.core.Timers; @@ -296,7 +296,7 @@ public class NetClient extends Module{ if(tile != null && tile.entity != null){ tile.entity.items.read(input); }else{ - new InventoryModule().read(input); + new ItemModule().read(input); } } diff --git a/core/src/io/anuke/mindustry/entities/TileEntity.java b/core/src/io/anuke/mindustry/entities/TileEntity.java index 426da9fb6c..ea3af6d622 100644 --- a/core/src/io/anuke/mindustry/entities/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/TileEntity.java @@ -17,7 +17,7 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.defense.Wall; import io.anuke.mindustry.world.consumers.Consume; import io.anuke.mindustry.world.modules.ConsumeModule; -import io.anuke.mindustry.world.modules.InventoryModule; +import io.anuke.mindustry.world.modules.ItemModule; import io.anuke.mindustry.world.modules.LiquidModule; import io.anuke.mindustry.world.modules.PowerModule; import io.anuke.ucore.core.Effects; @@ -47,7 +47,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ public float timeScale = 1f, timeScaleDuration; public PowerModule power; - public InventoryModule items; + public ItemModule items; public LiquidModule liquids; public ConsumeModule cons; diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index d3394c4b4b..dff94535ac 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -10,7 +10,7 @@ import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.blocks.BlockPart; import io.anuke.mindustry.world.blocks.Floor; import io.anuke.mindustry.world.modules.ConsumeModule; -import io.anuke.mindustry.world.modules.InventoryModule; +import io.anuke.mindustry.world.modules.ItemModule; import io.anuke.mindustry.world.modules.LiquidModule; import io.anuke.mindustry.world.modules.PowerModule; import io.anuke.ucore.entities.trait.PosTrait; @@ -423,7 +423,7 @@ public class Tile implements PosTrait, TargetTrait{ if(block.hasEntity()){ entity = block.newEntity().init(this, block.update); entity.cons = new ConsumeModule(); - if(block.hasItems) entity.items = new InventoryModule(); + if(block.hasItems) entity.items = new ItemModule(); if(block.hasLiquids) entity.liquids = new LiquidModule(); if(block.hasPower){ entity.power = new PowerModule(); diff --git a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java index 296a8f87a1..be34438d0c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java @@ -22,7 +22,7 @@ import io.anuke.mindustry.world.BarType; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockBar; -import io.anuke.mindustry.world.modules.InventoryModule; +import io.anuke.mindustry.world.modules.ItemModule; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Graphics; import io.anuke.ucore.graphics.Draw; @@ -246,7 +246,7 @@ public class BuildBlock extends Block{ } } - private float checkRequired(InventoryModule inventory, float amount, boolean remove){ + private float checkRequired(ItemModule inventory, float amount, boolean remove){ float maxProgress = amount; for(int i = 0; i < recipe.requirements.length; i++){ diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java index 2fa3d52cf8..3df2db69d3 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -19,7 +19,6 @@ import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.maps.TutorialSector; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.world.BarType; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.meta.BlockFlag; @@ -163,25 +162,6 @@ public class CoreBlock extends StorageBlock{ return entity.solid; } - @Override - public int acceptStack(Item item, int amount, Tile tile, Unit source){ - if(acceptItem(item, tile, tile) && hasItems && (source == null || source.getTeam() == tile.getTeam())){ - return Math.min(itemCapacity - tile.entity.items.get(item), amount); - }else{ - return 0; - } - } - - @Override - public int getMaximumAccepted(Tile tile, Item item){ - return itemCapacity; - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - return tile.entity.items.get(item) < itemCapacity && item.type == ItemType.material; - } - @Override public void handleItem(Item item, Tile tile, Tile source){ if(Net.server() || !Net.active()) super.handleItem(item, tile, source); diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java index 32c085756e..38800c5762 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java @@ -1,10 +1,19 @@ package io.anuke.mindustry.world.blocks.storage; +import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.entities.Unit; +import io.anuke.mindustry.graphics.Palette; +import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; +import io.anuke.ucore.core.Graphics; +import io.anuke.ucore.graphics.Draw; +import io.anuke.ucore.graphics.Fill; + +import static io.anuke.mindustry.Vars.tilesize; public abstract class StorageBlock extends Block{ @@ -37,6 +46,42 @@ public abstract class StorageBlock extends Block{ entity.graph.remove(tile); } + @Override + public void drawSelect(Tile tile){ + + StorageEntity entity = tile.entity(); + + if(entity.graph.getTiles().size > 1){ + + Shaders.outline.color.set(Palette.accent); + Graphics.beginShaders(Shaders.outline); + + for(Tile other : entity.graph.getTiles()){ + Fill.square(other.drawx(), other.drawy(), other.block().size * tilesize); + } + + Draw.color(Color.CLEAR); + Graphics.endShaders(); + Draw.color(); + } + } + + @Override + public boolean acceptItem(Item item, Tile tile, Tile source){ + StorageEntity entity = tile.entity(); + return entity.graph.accept(item); + } + + @Override + public int acceptStack(Item item, int amount, Tile tile, Unit source){ + StorageEntity entity = tile.entity(); + if(acceptItem(item, tile, tile) && hasItems && (source == null || source.getTeam() == tile.getTeam())){ + return Math.min(entity.graph.accept(item, amount), amount); + }else{ + return 0; + } + } + @Override public TileEntity newEntity(){ return new StorageEntity(); @@ -47,7 +92,7 @@ public abstract class StorageBlock extends Block{ Array arr = super.getDebugInfo(tile); StorageEntity entity = tile.entity(); - arr.addAll("storage graph", entity.graph.getID()); + arr.addAll("storage graph", entity.graph.getID(), "graph capacity", entity.graph.getCapacity(), "graph tiles", entity.graph.getTiles().size); return arr; } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java b/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java index a7f8c1feb9..f8ff6c7e4b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java @@ -3,21 +3,32 @@ package io.anuke.mindustry.world.blocks.storage; import com.badlogic.gdx.utils.IntSet; import com.badlogic.gdx.utils.ObjectSet; import com.badlogic.gdx.utils.Queue; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.storage.StorageBlock.StorageEntity; +import io.anuke.mindustry.world.modules.ItemModule; public class StorageGraph{ private static IntSet closedSet = new IntSet(); private static Queue queue = new Queue<>(); private static int lastID; + private final int id = lastID++; private ObjectSet tiles = new ObjectSet<>(); + private ItemModule items = new ItemModule(); + private int capacity; private int cores; - private int id = lastID++; public void add(Tile tile){ - if(tiles.add(tile) && tile.block() instanceof CoreBlock){ - cores ++; + if(tiles.add(tile)){ + if(tile.block() instanceof CoreBlock) cores ++; + capacity += tile.block().itemCapacity; + + if(tile.entity.items != items){ + items.addAll(tile.entity.items); + } + + tile.entity.items = items; } } @@ -27,6 +38,7 @@ public class StorageGraph{ } cores = 0; + capacity = 0; for(Tile other : tile.entity.proximity()){ if(other.block() instanceof StorageBlock && other.entity().graph == null){ @@ -61,10 +73,24 @@ public class StorageGraph{ for(Tile tile : other.tiles){ StorageEntity e = tile.entity(); e.graph = this; + add(tile); } + } - tiles.addAll(other.tiles); - cores += other.cores; + public boolean accept(Item item){ + return accept(item, 1) == 1; + } + + public int accept(Item item, int amount){ + if(hasCores()){ + return Math.min(capacity - items.get(item), amount); + }else{ + return Math.min(capacity - items.total(), amount); + } + } + + public ObjectSet getTiles(){ + return tiles; } public boolean hasCores(){ @@ -74,4 +100,12 @@ public class StorageGraph{ public int getID(){ return id; } + + public int getCapacity(){ + return capacity; + } + + public ItemModule items(){ + return items; + } } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/Vault.java b/core/src/io/anuke/mindustry/world/blocks/storage/Vault.java index d7f3d60eb2..28beaad8f2 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/Vault.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/Vault.java @@ -1,85 +1,13 @@ package io.anuke.mindustry.world.blocks.storage; -import com.badlogic.gdx.utils.Array; -import io.anuke.mindustry.entities.TileEntity; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Edges; -import io.anuke.mindustry.world.Tile; -import io.anuke.ucore.core.Timers; -import static io.anuke.mindustry.Vars.*; - public class Vault extends StorageBlock{ public Vault(String name){ super(name); solid = true; - update = true; + update = false; + destructible = true; itemCapacity = 1000; } - @Override - public void update(Tile tile){ - int iterations = Math.max(1, (int) (Timers.delta() + 0.4f)); - - for(int i = 0; i < iterations; i++){ - if(tile.entity.items.total() > 0){ - tryDump(tile); - } - } - } - - @Override - public boolean acceptItem(Item item, Tile tile, Tile source){ - return tile.entity.items.total() < itemCapacity; - } - - @Override - public boolean tryDump(Tile tile, Item todump){ - TileEntity entity = tile.entity; - if(entity == null || !hasItems || tile.entity.items.total() == 0 || (todump != null && !entity.items.has(todump))) - return false; - - Array proximity = entity.proximity(); - int dump = tile.getDump(); - - if(proximity.size == 0) return false; - - for(int i = 0; i < proximity.size; i++){ - Tile other = proximity.get((i + dump) % proximity.size); - Tile in = Edges.getFacingEdge(tile, other); - - if(other == null || !(other.block() instanceof StorageBlock)) continue; - - if(!(other.block() instanceof Vault)){ - - for(int ii = 0; ii < content.items().size; ii++){ - Item item = content.item(ii); - - if(entity.items.has(item) && other.block().acceptItem(item, other, in) && canDump(tile, other, item)){ - other.block().handleItem(item, other, in); - tile.entity.items.remove(item, 1); - incrementDump(tile, proximity.size); - return true; - } - } - }else{ - todump = content.item(0); - - if(other.block().acceptItem(todump, other, in) && canDump(tile, other, todump)){ - other.block().handleItem(removeItem(tile, null), other, in); - incrementDump(tile, proximity.size); - return true; - } - } - - incrementDump(tile, proximity.size); - } - - return false; - } - - @Override - public boolean canDump(Tile tile, Tile to, Item item){ - return !(to.block() instanceof Vault) || (float) to.entity.items.total() / to.block().itemCapacity < (float) tile.entity.items.total() / itemCapacity; - } } diff --git a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java index fb7fed9e4e..ae28270215 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java @@ -22,7 +22,7 @@ import io.anuke.mindustry.world.meta.BlockBar; import io.anuke.mindustry.world.meta.BlockFlag; import io.anuke.mindustry.world.meta.BlockStat; import io.anuke.mindustry.world.meta.StatUnit; -import io.anuke.mindustry.world.modules.InventoryModule; +import io.anuke.mindustry.world.modules.ItemModule; import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Graphics; import io.anuke.ucore.graphics.Draw; @@ -211,7 +211,7 @@ public class UnitFactory extends Block{ return new UnitFactoryEntity(); } - protected boolean hasRequirements(InventoryModule inv, float fraction){ + protected boolean hasRequirements(ItemModule inv, float fraction){ for(ItemStack stack : consumes.items()){ if(!inv.has(stack.item, (int) (fraction * stack.amount))){ return false; diff --git a/core/src/io/anuke/mindustry/world/modules/InventoryModule.java b/core/src/io/anuke/mindustry/world/modules/ItemModule.java similarity index 93% rename from core/src/io/anuke/mindustry/world/modules/InventoryModule.java rename to core/src/io/anuke/mindustry/world/modules/ItemModule.java index b8f175fa51..980d462aa2 100644 --- a/core/src/io/anuke/mindustry/world/modules/InventoryModule.java +++ b/core/src/io/anuke/mindustry/world/modules/ItemModule.java @@ -7,9 +7,10 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.util.Arrays; + import static io.anuke.mindustry.Vars.content; -public class InventoryModule extends BlockModule{ +public class ItemModule extends BlockModule{ private int[] items = new int[content.items().size]; private int total; @@ -85,6 +86,13 @@ public class InventoryModule extends BlockModule{ total += amount; } + public void addAll(ItemModule items){ + for(int i = 0; i < items.items.length; i++){ + this.items[i] += items.items[i]; + total += items.items[i]; + } + } + public void remove(Item item, int amount){ amount = Math.min(amount, items[item.id]); From 3bd73961d79df3d9c6925f1fd98c0759d065b821 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sun, 21 Oct 2018 21:46:12 -0400 Subject: [PATCH 4/4] Merged inventory saving/loading, item-based capacity --- .../content/blocks/StorageBlocks.java | 4 +- .../world/blocks/storage/StorageBlock.java | 14 +++- .../world/blocks/storage/StorageGraph.java | 82 ++++++++++++++----- .../mindustry/world/modules/ItemModule.java | 14 ++++ 4 files changed, 89 insertions(+), 25 deletions(-) diff --git a/core/src/io/anuke/mindustry/content/blocks/StorageBlocks.java b/core/src/io/anuke/mindustry/content/blocks/StorageBlocks.java index 0a808e7ecc..d00275a05f 100644 --- a/core/src/io/anuke/mindustry/content/blocks/StorageBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/StorageBlocks.java @@ -17,12 +17,12 @@ public class StorageBlocks extends BlockList implements ContentList{ vault = new Vault("vault"){{ size = 3; - itemCapacity = 2000; + itemCapacity = 1000; }}; container = new Vault("container"){{ size = 2; - itemCapacity = 500; + itemCapacity = 250; }}; unloader = new SortedUnloader("unloader"){{ diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java index 38800c5762..417a7dd4a0 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/StorageBlock.java @@ -7,6 +7,7 @@ import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.world.BarType; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.ucore.core.Graphics; @@ -22,6 +23,12 @@ public abstract class StorageBlock extends Block{ hasItems = true; } + @Override + public void setBars(){ + super.setBars(); + bars.remove(BarType.inventory); + } + @Override public boolean outputsItems(){ return false; @@ -30,7 +37,7 @@ public abstract class StorageBlock extends Block{ @Override public void onProximityAdded(Tile tile){ StorageEntity entity = tile.entity(); - entity.graph.add(tile); + entity.graph.set(tile); for(Tile prox : tile.entity.proximity()){ if(prox.block() instanceof StorageBlock){ @@ -92,7 +99,10 @@ public abstract class StorageBlock extends Block{ Array arr = super.getDebugInfo(tile); StorageEntity entity = tile.entity(); - arr.addAll("storage graph", entity.graph.getID(), "graph capacity", entity.graph.getCapacity(), "graph tiles", entity.graph.getTiles().size); + arr.addAll("storage graph", entity.graph.getID(), + "graph capacity", entity.graph.getCapacity(), + "graph tiles", entity.graph.getTiles().size, + "graph item ID", entity.graph.items().getID()); return arr; } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java b/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java index f8ff6c7e4b..d139f84693 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/StorageGraph.java @@ -11,33 +11,70 @@ import io.anuke.mindustry.world.modules.ItemModule; public class StorageGraph{ private static IntSet closedSet = new IntSet(); private static Queue queue = new Queue<>(); + private static ObjectSet itemSet = new ObjectSet<>(); private static int lastID; private final int id = lastID++; private ObjectSet tiles = new ObjectSet<>(); private ItemModule items = new ItemModule(); private int capacity; - private int cores; + + public void set(Tile tile){ + items.addAll(tile.entity.items); + items.setID(tile.entity.items.getID()); + + add(tile); + } public void add(Tile tile){ - if(tiles.add(tile)){ - if(tile.block() instanceof CoreBlock) cores ++; - capacity += tile.block().itemCapacity; - if(tile.entity.items != items){ - items.addAll(tile.entity.items); - } + if(!tiles.add(tile)) return; - tile.entity.items = items; + StorageEntity e = tile.entity(); + e.graph = this; + + capacity += tile.block().itemCapacity; + + if(tile.entity.items != null && tile.entity.items.getID() != items.getID()){ + items.addAll(tile.entity.items); } + + tile.entity.items = items; } public void remove(Tile tile){ + if(!tiles.contains(tile)) return; + for(Tile other : tiles){ - other.entity().graph = null; + if(other == tile) continue; + + StorageEntity entity = other.entity(); + entity.graph = null; + entity.items = new ItemModule(); + + float fraction = (float)other.block().itemCapacity / capacity; + items.forEach((item, amount) -> { + int added = (int)(fraction * amount); + entity.items.add(item, added); + items.remove(item, added); + }); } - cores = 0; + //handle remaining items that didn't get added + Item taken; + while((taken = items.take()) != null){ + for(Tile other : tiles){ + if(other == tile) continue; + + //insert item into first found block + if(other.entity.items.get(taken) < other.block().itemCapacity){ + other.entity.items.add(taken, 1); + break; + } + } + } + + items.clear(); capacity = 0; for(Tile other : tile.entity.proximity()){ @@ -53,11 +90,16 @@ public class StorageGraph{ queue.clear(); queue.addLast(tile); closedSet.clear(); + itemSet.clear(); + while(queue.size > 0){ Tile child = queue.removeFirst(); StorageEntity entity = child.entity(); entity.graph = this; + + if(!itemSet.add(child.entity.items)) child.entity.items = null; add(child); + for(Tile next : child.entity.proximity()){ if(next != base && next.block() instanceof StorageBlock && next.entity().graph == null && !closedSet.contains(next.packedPosition())){ queue.addLast(next); @@ -70,9 +112,14 @@ public class StorageGraph{ public void merge(StorageGraph other){ if(this == other || other == null) return; + itemSet.clear(); + for(Tile tile : other.tiles){ + if(!itemSet.add(tile.entity.items)){ + tile.entity.items = null; + } + } + for(Tile tile : other.tiles){ - StorageEntity e = tile.entity(); - e.graph = this; add(tile); } } @@ -82,21 +129,13 @@ public class StorageGraph{ } public int accept(Item item, int amount){ - if(hasCores()){ - return Math.min(capacity - items.get(item), amount); - }else{ - return Math.min(capacity - items.total(), amount); - } + return Math.min(capacity - items.get(item), amount); } public ObjectSet getTiles(){ return tiles; } - public boolean hasCores(){ - return cores > 0; - } - public int getID(){ return id; } @@ -108,4 +147,5 @@ public class StorageGraph{ public ItemModule items(){ return items; } + } diff --git a/core/src/io/anuke/mindustry/world/modules/ItemModule.java b/core/src/io/anuke/mindustry/world/modules/ItemModule.java index 980d462aa2..ece14fbe82 100644 --- a/core/src/io/anuke/mindustry/world/modules/ItemModule.java +++ b/core/src/io/anuke/mindustry/world/modules/ItemModule.java @@ -11,8 +11,11 @@ import java.util.Arrays; import static io.anuke.mindustry.Vars.content; public class ItemModule extends BlockModule{ + private static int lastID; + private int[] items = new int[content.items().size]; private int total; + private int id = lastID ++; public void forEach(ItemConsumer cons){ for(int i = 0; i < items.length; i++){ @@ -111,6 +114,8 @@ public class ItemModule extends BlockModule{ @Override public void write(DataOutput stream) throws IOException{ + stream.writeInt(id); //unique ID + byte amount = 0; for(int item : items){ if(item > 0) amount++; @@ -128,6 +133,7 @@ public class ItemModule extends BlockModule{ @Override public void read(DataInput stream) throws IOException{ + id = stream.readInt(); byte count = stream.readByte(); total = 0; @@ -139,6 +145,14 @@ public class ItemModule extends BlockModule{ } } + public int getID(){ + return id; + } + + public void setID(int id){ + this.id = id; + } + public interface ItemConsumer{ void accept(Item item, float amount); }