diff --git a/src/meld/content/MeldBlocks.java b/src/meld/content/MeldBlocks.java index 3f8f0e9..04b07f5 100644 --- a/src/meld/content/MeldBlocks.java +++ b/src/meld/content/MeldBlocks.java @@ -1,5 +1,6 @@ package meld.content; +import arc.*; import arc.graphics.Blending; import arc.graphics.Color; import arc.math.Angles; @@ -16,6 +17,7 @@ import meld.world.blocks.*; import meld.world.blocks.crafting.ModularCrafter; import meld.world.blocks.crafting.RecipeCrafter; +import meld.world.blocks.crafting.modules.rework.*; import meld.world.blocks.crafting.recipe.ItemRecipe; import meld.world.blocks.crafting.recipe.SpoolRecipe; import meld.world.blocks.crafting.modules.*; @@ -27,8 +29,7 @@ import meld.world.blocks.production.SingleBeamDrill; import meld.world.meta.*; import mindustry.Vars; -import mindustry.content.Fx; -import mindustry.content.StatusEffects; +import mindustry.content.*; import mindustry.entities.bullet.*; import mindustry.entities.effect.MultiEffect; import mindustry.entities.effect.ParticleEffect; @@ -998,7 +999,7 @@ public static void load(){ dumpedLiquids.addAll(MeldLiquids.pollutantMixture, MeldLiquids.fumes); //Should make all the modules trigger in order - hookAll(BlockEvent.Defaults.proximityUpdate, + /*hookAll(BlockEvent.Defaults.proximityUpdate, new AttributeModule(){{ attribute = MeldAttributes.aetherAttr; baseEfficiency = 0; @@ -1015,12 +1016,12 @@ public static void load(){ efficiencyPin = 1; }} - ); + );*/ - modules.addAll( + /*modules.addAll( new ProduceLiquidModule(new LiquidStack(MeldLiquids.pollutantMixture, 1), 0), new ProduceLiquidModule(new LiquidStack(MeldLiquids.fumes, 1), 1) - ); + );*/ }}; elementalBlaster = new BeamDrill("elemental-blaster"){{ @@ -1072,6 +1073,97 @@ public static void load(){ consume(new ConsumeAspects(outletRate/2, MeldLiquids.outletEfficiencies, MeldLiquids.outletDensities)); }}; + new ModularCrafter("stupid-crafter"){{ + requirements(Category.crafting, with(MeldItems.debris, 40)); + size = 3; + + modules.addAll( + new ProduceHeatModule(0){{ + heatOutput = 10; + }}, + new AttributeModule(0){{ + attribute = Attribute.heat; + baseEfficiency = 0f; + maxBoost = 2f; + storagePin = 1; + }}, + //This is assigned to the same pin as the attribute, and updates after, + //which means it will only "top off" the efficiency that the attributes don't reach. + new ConsumeItemModule(0){{ + items = ItemStack.with(Items.pyratite, 1); + efficiencyIncrease = 4f; + time = 20f; + progressPin = 2; + }}, + //Same as above, but will also cover for the pyratite consumer. + new ConsumeItemModule(0){{ + items = ItemStack.with(Items.coal, 1); + time = 40f; + progressPin = 3; + }} + ); + }}; + + new ModularCrafter("stupid-silicon-smelter"){ + //I refuse to add sprites to the files. + @Override + public void load(){ + super.load(); + region = Core.atlas.find("silicon-smelter"); + fullIcon = Core.atlas.find("silicon-smelter"); + uiIcon = Core.atlas.find("silicon-smelter"); + if(drawer instanceof DrawMulti m && m.drawers[1] instanceof DrawHeatInput f) f.heat = Core.atlas.find("phase-heater-heat"); + if(drawer instanceof DrawMulti m && m.drawers[2] instanceof DrawRegion r) r.region = Core.atlas.find("pneumatic-drill-rotator"); + if(drawer instanceof DrawMulti m && m.drawers[3] instanceof DrawFlame f) f.top = Core.atlas.find("silicon-smelter-top"); + } + + { + requirements(Category.crafting, with(MeldItems.debris, 40)); + size = 2; + + drawer = new DrawMulti( + new DrawDefault(), + new DrawHeatInput(), + new DrawRegion("", 3f, true), + new DrawFlame(Color.valueOf("ffef99")) + ); + + modules.addAll( + new ProduceItemModule( 1, 2){{ + items = ItemStack.with(Items.silicon, 1); + time = 60f; + progressPin = 0; + }}, + new ConsumeItemModule(1){{ + items = ItemStack.with(Items.sand, 1); + time = 20f; + progressPin = -1; + }}, + new ConsumeHeatModule(2), + new AttributeModule(2){{ + attribute = Attribute.heat; + baseEfficiency = 0f; + maxBoost = 2f; + storagePin = -2; + }}, + //This is assigned to the same pin as the attribute, and updates after, + //which means it will only "top off" the efficiency that the attributes don't reach. + new ConsumeItemModule(2){{ + items = ItemStack.with(Items.pyratite, 1); + efficiencyIncrease = 2.5f; + time = 20f; + progressPin = -3; + }}, + //Same as above, but will also cover for the pyratite consumer. + new ConsumeItemModule(2){{ + items = ItemStack.with(Items.coal, 1); + time = 40f; + progressPin = -4; + }} + ); + } + }; + earthboundInfuser = new ModularCrafter("earthbound-infuser"){{ requirements(Category.crafting, with( MeldItems.debris, 40, @@ -1088,7 +1180,7 @@ public static void load(){ dumpedItems.add(MeldItems.carbolith); - //Should make all the modules trigger in order + /*//Should make all the modules trigger in order hookAll(BlockEvent.Defaults.proximityUpdate, new AttributeModule(){{ attribute = Attribute.steam; @@ -1098,11 +1190,11 @@ public static void load(){ efficiencyPin = 0; }} - ); + );*/ ItemRecipe carbolith = new ItemRecipe(with(MeldItems.debris, 1), with(MeldItems.carbolith, 1)); - modules.addAll( + /*modules.addAll( new ProduceLiquidModule(new LiquidStack(MeldLiquids.fumes, 2f), 0), new GateModule(1, new GateModule.RecipeCondition(carbolith)), new ConsumeLiquidModule(LiquidStack.with(MeldLiquids.fumes, 1, MeldLiquids.aspect, outletRate * 2), 1, 2), @@ -1112,7 +1204,7 @@ public static void load(){ craftTime = 12; recipe = carbolith; }} - ); + );*/ /* @@ -1330,7 +1422,7 @@ public static void load(){ float produceTime = 30; - modules.addAll( + /*modules.addAll( new GateModule( ModOUT.ZERO, new GateModule.RecipeCondition(aspectPipe1) ), @@ -1361,7 +1453,7 @@ public static void load(){ progressPin = ModOUT.FIVE; craftTime = produceTime; }} - ); + );*/ }}; sharkFactory = new UnitFactory("shark-factory"){{ diff --git a/src/meld/world/blocks/crafting/ModularCrafter.java b/src/meld/world/blocks/crafting/ModularCrafter.java index a56528b..cb7e48b 100644 --- a/src/meld/world/blocks/crafting/ModularCrafter.java +++ b/src/meld/world/blocks/crafting/ModularCrafter.java @@ -1,44 +1,55 @@ package meld.world.blocks.crafting; +import arc.scene.ui.layout.*; import arc.struct.*; -import arc.util.Log; -import arc.util.Time; +import arc.util.*; import arc.util.io.Reads; import arc.util.io.Writes; +import mindustry.ctype.*; import mindustry.game.Team; import mindustry.gen.Building; -import mindustry.type.Item; -import mindustry.type.ItemStack; -import mindustry.type.Liquid; +import mindustry.type.*; import mindustry.world.Block; -import mindustry.world.blocks.production.GenericCrafter; -import mindustry.world.meta.Attribute; - -import java.util.HashMap; - -public class ModularCrafter extends Block { +import mindustry.world.blocks.heat.*; +import mindustry.world.blocks.payloads.*; +import mindustry.world.draw.*; +import mindustry.world.meta.*; +public class ModularCrafter extends PayloadBlock{ //Modules updates every update, listeners are for modules with specific events - public Seq modules = new Seq(); - public ObjectMap> listeners = new ObjectMap>(); + public Seq modules = new Seq<>(); + public ObjectMap> listeners = new ObjectMap<>(); - //list of items/liquids which this block accepts + //Lists of stuff which this block accepts + //note: could be a single HashSet. public Seq acceptedLiquids = new Seq<>(); public Seq acceptedItems = new Seq<>(); + public Seq acceptedPayloads = new Seq<>(); - //List of items/liquids which get dumped + //Lists of stuff which gets dumped public Seq dumpedLiquids = new Seq<>(); public Seq dumpedItems = new Seq<>(); + public Seq dumpedPayloads = new Seq<>(); public boolean replaceBars = true; + public int payloadCapacity = 3; + + /// Used to show heat as a percentage. Does not affect function. + public float fullHeat = 10f; - //Default float data array + /// Default float data array public IntFloatMap defaultData = new IntFloatMap(); + /// When true, shows a table with the data map in the block's display. + public boolean debugTable = true; + + public DrawBlock drawer = new DrawDefault(); + public ModularCrafter(String name) { super(name); update = true; solid = true; + sync = true; } @Override @@ -57,9 +68,21 @@ public void setBars() { } } + @Override + public void init(){ + super.init(); + modules.each(m -> m.setup(this)); + } + + @Override + public void load(){ + super.load(); + drawer.load(this); + } + public static void trigger(ModularCrafter block, ModularCrafterBuild build, Object event){ Seq events = block.listeners.get(event); - if(events != null) events.each(c -> c.update(build)); + if(events != null) events.each(c -> c.on_event(build)); } public void hook(Object event, CrafterModule module){ @@ -71,15 +94,6 @@ public void hook(Object event, CrafterModule module){ events.add(module); } - public void hookAll(Object event, CrafterModule... module){ - Seq events = listeners.get(event); - if(events == null) { - listeners.put(event, Seq.with(module)); - return; - } - events.add(module); - } - public static class BlockEvent{ public enum Defaults{ update, @@ -87,10 +101,25 @@ public enum Defaults{ } } + @Override + public boolean outputsItems(){ + return !dumpedItems.isEmpty(); + } + public static abstract class CrafterModule{ public void update(ModularCrafterBuild build){ } + + public void setup(ModularCrafter block){ + + } + + public void on_event(ModularCrafterBuild build){ + + } + + } public static abstract class CraftingModule extends CrafterModule{ @@ -166,31 +195,61 @@ public static class ModIN{ public static final float ON = 1, OFF = 0; - public class ModularCrafterBuild extends Building { - + public class ModularCrafterBuild extends PayloadBlockBuild implements HeatConsumer, HeatBlock{ public ModularCrafter modular; public IntFloatMap data = new IntFloatMap(); + public PayloadSeq payloads = new PayloadSeq(); + + public float[] sideHeat = new float[4]; + public float heat = 0f; + + public float totalProgress = 0f; + public float visualEfficiency = 0f; + @Override - public void created() { - super.created(); - data.putAll(defaultData); + public void draw(){ + drawer.draw(this); + + drawPayload(); } @Override - public void updateTile() { - super.updateTile(); - this.dumpOutputs(); + public void display(Table table){ + super.display(table); + + if(debugTable){ + table.row(); + table.table(d -> { + Runnable rebuild = () -> { + d.clearChildren(); + d.table(debug -> { + data.iterator().forEachRemaining(entry -> { + debug.add(entry.key + ": " + StatValues.fixValue(entry.value)).left(); + debug.row(); + }); + }).left(); + d.table().growX(); //ugh + }; + d.update(rebuild); + rebuild.run(); + }).growX(); //It doesn't actually grow for some fucking reason. See ugh above. + } } - public void dumpOutputs(){ - dumpedLiquids.each(this::dumpLiquid); - dumpedItems.each(this::dump); + @Override + public void created() { + super.created(); + data.putAll(defaultData); } public void setPin(int pin, float value){ data.put(pin, value); - }; + } + + public void setPins(int[] pins, float value){ + for(int i : pins) setPin(i, value); + } public float getPin(int pin){ return data.get(pin); @@ -206,6 +265,11 @@ public boolean acceptItem(Building source, Item item) { return (this.block.consumesItem(item) || acceptedItems.contains(item)) && this.items.get(item) < this.getMaximumAccepted(item); } + @Override + public boolean acceptPayload(Building source, Payload payload){ + return this.payload == null && acceptedPayloads.contains(payload.content()) && payloads.get(payload.content()) < payloadCapacity; + } + @Override public Building create(Block block, Team team) { modular = (ModularCrafter) block; @@ -221,12 +285,51 @@ public void onProximityUpdate() { @Override public void update() { super.update(); + visualEfficiency = 0f; + modules.each(c -> c.update(this)); + + totalProgress += visualEfficiency * Time.delta; + } + + //the useful one + @Override + public float heat(){ + return heat; + } + + //only used by DrawHeatOutput + @Override + public float heatFrac(){ + return heat / fullHeat; + } + + //only used by DrawHeatInput + @Override + public float[] sideHeat(){ + return sideHeat; + } + + //only used by DrawHeatInput and DrawHeatRegion + @Override + public float heatRequirement(){ + return fullHeat; + } + + @Override + public float warmup(){ + return visualEfficiency; + } + + @Override + public float totalProgress(){ + return totalProgress; } @Override public void write(Writes write) { super.write(write); + write.i(data.size); int[] keys = data.keys().toArray().toArray(); @@ -234,16 +337,26 @@ public void write(Writes write) { write.i(i); write.f(data.get(i)); } + + write.f(heat); } @Override public void read(Reads read, byte revision) { super.read(read, revision); + data = new IntFloatMap(); int len = read.i(); for (int i = 0; i < len; i++){ data.put(read.i(), read.f()); } + + if(revision >= 1) heat = read.f(); + } + + @Override + public byte version(){ + return 1; } } } diff --git a/src/meld/world/blocks/crafting/modules/AttributeModule.java b/src/meld/world/blocks/crafting/modules/AttributeModule.java deleted file mode 100644 index 600085e..0000000 --- a/src/meld/world/blocks/crafting/modules/AttributeModule.java +++ /dev/null @@ -1,27 +0,0 @@ -package meld.world.blocks.crafting.modules; - -import arc.util.Log; -import meld.world.blocks.crafting.ModularCrafter; -import mindustry.world.meta.Attribute; - -public class AttributeModule extends ModularCrafter.CrafterModule { - public int efficiencyPin; - - public Attribute attribute; - public float baseEfficiency = 1; - public float boostScale = 1; - public float maxBoost = 1; - public float minEfficiency = -1; - - @Override - public void update(ModularCrafter.ModularCrafterBuild build) { - float efficiency = baseEfficiency + Math.min(maxBoost, boostScale * build.block.sumAttribute(attribute, build.tileX(), build.tileY()) + attribute.env()); - - if(minEfficiency != -1 && efficiency < minEfficiency) { - build.setPin(efficiencyPin, 0); - return; - } - - build.data.put(efficiencyPin, efficiency); - } -} \ No newline at end of file diff --git a/src/meld/world/blocks/crafting/modules/ConsumeLiquidModule.java b/src/meld/world/blocks/crafting/modules/ConsumeLiquidModule.java deleted file mode 100644 index cc4df34..0000000 --- a/src/meld/world/blocks/crafting/modules/ConsumeLiquidModule.java +++ /dev/null @@ -1,41 +0,0 @@ -package meld.world.blocks.crafting.modules; - -import meld.world.blocks.crafting.ModularCrafter; -import mindustry.type.LiquidStack; - -public class ConsumeLiquidModule extends ModularCrafter.CrafterModule { - - public ConsumeLiquidModule(LiquidStack[] consumed, int efficiencyPin, int outputEfficiencyPin){ - this.consumed = consumed; - this.efficiencyPin = efficiencyPin; - this.outputEfficiencyPin = outputEfficiencyPin; - } - - public int efficiencyPin; - public int outputEfficiencyPin; - public LiquidStack[] consumed; - - @Override - public void update(ModularCrafter.ModularCrafterBuild build) { - float efficiency = build.getPin(efficiencyPin); - if(efficiency == 0) return; - - float maxEfficiency = 1; - - for(LiquidStack stack: consumed){ - float target = build.liquids.get(stack.liquid); - float consumeAmount = stack.amount * efficiency; - - maxEfficiency = Math.min(maxEfficiency, target/consumeAmount); - } - - efficiency *= maxEfficiency; - - for (LiquidStack stack: consumed){ - float removed = efficiency * stack.amount; - build.liquids.remove(stack.liquid, removed); - } - - build.setPin(outputEfficiencyPin, efficiency); - } -} diff --git a/src/meld/world/blocks/crafting/modules/ProduceLiquidModule.java b/src/meld/world/blocks/crafting/modules/ProduceLiquidModule.java deleted file mode 100644 index 590998e..0000000 --- a/src/meld/world/blocks/crafting/modules/ProduceLiquidModule.java +++ /dev/null @@ -1,22 +0,0 @@ -package meld.world.blocks.crafting.modules; - -import arc.math.Mathf; -import meld.world.blocks.crafting.ModularCrafter; -import mindustry.type.LiquidStack; - -public class ProduceLiquidModule extends ModularCrafter.CrafterModule { - public LiquidStack liquid; - public int efficiencyPin; - - public ProduceLiquidModule(LiquidStack liquid, int efficiencyPin){ - this.liquid = liquid; - this.efficiencyPin = efficiencyPin; - } - - @Override - public void update(ModularCrafter.ModularCrafterBuild build) { - float efficiency = build.getPin(efficiencyPin); - float addedAmount = Math.min(liquid.amount * efficiency, Mathf.maxZero(build.block.liquidCapacity - build.liquids.get(liquid.liquid))); - build.liquids.add(liquid.liquid, addedAmount); - } -} diff --git a/src/meld/world/blocks/crafting/modules/rework/AttributeModule.java b/src/meld/world/blocks/crafting/modules/rework/AttributeModule.java new file mode 100644 index 0000000..dd8bc08 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/AttributeModule.java @@ -0,0 +1,45 @@ +package meld.world.blocks.crafting.modules.rework; + +import meld.world.blocks.crafting.ModularCrafter; +import meld.world.blocks.crafting.ModularCrafter.*; +import mindustry.world.meta.Attribute; + +public class AttributeModule extends CrafterModule { + /// Pins to provide efficiency on. + public int[] outputPins; + /// Pin to store the efficiency that should be output. Don't let other modules touch it. + public int storagePin; + + public Attribute attribute; + public float baseEfficiency = 1; + public float boostScale = 1; + public float maxBoost = 1; + /// The minimum attribute efficiency needed for it to affect output. + public float minEfficiency = -1; + + public AttributeModule(int... outputPins){ + this.outputPins = outputPins; + } + + @Override + public void update(ModularCrafterBuild build){ + for(int i : outputPins) build.setPin(i, Math.max(build.getPin(storagePin), build.getPin(i))); + } + + @Override + public void on_event(ModularCrafterBuild build){ + float efficiency = baseEfficiency + Math.min(maxBoost, boostScale * build.block.sumAttribute(attribute, build.tileX(), build.tileY()) + attribute.env()); + + if(efficiency < minEfficiency) { + build.setPin(storagePin, 0); + return; + } + + build.setPin(storagePin, efficiency); + } + + @Override + public void setup(ModularCrafter block){ + block.hook(BlockEvent.Defaults.proximityUpdate, this); + } +} \ No newline at end of file diff --git a/src/meld/world/blocks/crafting/modules/rework/ConsumeHeatModule.java b/src/meld/world/blocks/crafting/modules/rework/ConsumeHeatModule.java new file mode 100644 index 0000000..6ecdde7 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/ConsumeHeatModule.java @@ -0,0 +1,30 @@ +package meld.world.blocks.crafting.modules.rework; + +import arc.math.*; +import meld.world.blocks.crafting.*; +import meld.world.blocks.crafting.ModularCrafter.*; +import meld.world.blocks.crafting.modules.rework.base.*; + +public class ConsumeHeatModule extends ConsumeModule{ + public float baseEfficiency = 0f; + /// Base heat requirement for 100% efficiency. + public float heatRequirement = 10f; + /// After heat meets this requirement, excess heat will be scaled by this number. + public float overheatScale = 1f; + /// Maximum possible efficiency after overheat. + public float maxEfficiency = 4f; + + public ConsumeHeatModule(int... outputPins){ + super(outputPins); + } + + @Override + public void update(ModularCrafterBuild build){ + build.heat = build.calculateHeat(build.sideHeat); + + float over = Math.max(build.heat - heatRequirement, 0f); + float scaled = Math.min(Mathf.clamp(build.heat / heatRequirement) + over / heatRequirement * overheatScale, maxEfficiency); + + for(int i : outputPins) build.setPin(i, Math.max(baseEfficiency + scaled, build.getPin(i))); + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/ConsumeHighestModule.java b/src/meld/world/blocks/crafting/modules/rework/ConsumeHighestModule.java new file mode 100644 index 0000000..3690bd8 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/ConsumeHighestModule.java @@ -0,0 +1,35 @@ +package meld.world.blocks.crafting.modules.rework; + +import meld.world.blocks.crafting.ModularCrafter.*; +import meld.world.blocks.crafting.modules.rework.base.*; + +/// Will only consume from the pin with the highest efficiency. +public class ConsumeHighestModule extends ConsumeModule{ + public int[] inputPins; + + public ConsumeHighestModule(int... outputPins){ + super(outputPins); + } + + public void update(ModularCrafterBuild build){ + //Get the highest input pin + float input = 0f; + int inputPin = 0; + for(int i : inputPins){ + if(build.getPin(i) > input){ + input = build.getPin(i); + inputPin = i; + } + } + + //Find the least consumed output, it signals inactivity + float current = getCurrent(build); + + if(input > current){ + //Just swap pin contents + build.setPin(inputPin, current); + build.setPins(outputPins, input); + } + + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/ConsumeItemModule.java b/src/meld/world/blocks/crafting/modules/rework/ConsumeItemModule.java new file mode 100644 index 0000000..bd8713a --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/ConsumeItemModule.java @@ -0,0 +1,32 @@ +package meld.world.blocks.crafting.modules.rework; + +import meld.world.blocks.crafting.*; +import meld.world.blocks.crafting.ModularCrafter.*; +import meld.world.blocks.crafting.modules.rework.base.*; +import mindustry.type.*; + +public class ConsumeItemModule extends ConsumeDiscreteModule{ + public ItemStack[] items; + + public ConsumeItemModule(int... outputPins){ + super(outputPins); + } + + @Override + public boolean canConsume(ModularCrafterBuild build){ + return build.items.has(items); + } + + @Override + public void consume(ModularCrafterBuild build){ + build.items.remove(items); + } + + @Override + public void setup(ModularCrafter block){ + block.hasItems = true; + for(ItemStack stack : items){ + block.acceptedItems.add(stack.item); + } + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/ConsumeLiquidModule.java b/src/meld/world/blocks/crafting/modules/rework/ConsumeLiquidModule.java new file mode 100644 index 0000000..c799091 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/ConsumeLiquidModule.java @@ -0,0 +1,52 @@ +package meld.world.blocks.crafting.modules.rework; + +import arc.util.*; +import meld.world.blocks.crafting.*; +import meld.world.blocks.crafting.ModularCrafter.*; +import meld.world.blocks.crafting.modules.rework.base.*; +import mindustry.type.*; + +public class ConsumeLiquidModule extends ConsumeModule{ + public LiquidStack[] liquids; + + public float baseEfficiency = 0; + public float efficiencyIncrease = 1; + + public ConsumeLiquidModule(int... outputPins){ + super(outputPins); + } + + @Override + public void update(ModularCrafterBuild build){ + //Find the least consumed output, it signals inactivity + float current = getCurrent(build); + //Get the amount of efficiency that was eaten + float consumed = (efficiencyIncrease - current - baseEfficiency) / (efficiencyIncrease - baseEfficiency); + float output = Math.max(baseEfficiency, current); + + //if efficiency has been used + if(consumed > 0f){ + float min = 10000f; + for(LiquidStack stack : liquids){ + min = Math.min(build.liquids.get(stack.liquid) / (stack.amount * consumed * Time.delta), min); + } + + if(min > 0.00001f){ + for(LiquidStack stack : liquids){ + build.liquids.remove(stack.liquid, stack.amount * min); + } + output = baseEfficiency + efficiencyIncrease * min; + } + } + + build.setPins(outputPins, output); + } + + @Override + public void setup(ModularCrafter block){ + block.hasLiquids = true; + for(LiquidStack stack : liquids){ + block.acceptedLiquids.add(stack.liquid); + } + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/ConsumePayloadModule.java b/src/meld/world/blocks/crafting/modules/rework/ConsumePayloadModule.java new file mode 100644 index 0000000..37ecab7 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/ConsumePayloadModule.java @@ -0,0 +1,55 @@ +package meld.world.blocks.crafting.modules.rework; + +import meld.world.blocks.crafting.*; +import meld.world.blocks.crafting.ModularCrafter.*; +import meld.world.blocks.crafting.modules.rework.base.*; +import mindustry.type.*; +import mindustry.world.blocks.payloads.*; + +import java.util.*; + +public class ConsumePayloadModule extends ConsumeDiscreteModule{ + public PayloadStack[] payloads; + + public ConsumePayloadModule(int... outputPins){ + super(outputPins); + } + + @Override + public void update(ModularCrafterBuild build){ + super.update(build); + + if(build.payload != null && wants(build.payload) && build.moveInPayload()){ + build.payloads.add(build.payload.content()); + build.payload = null; + } + } + + @Override + public boolean canConsume(ModularCrafterBuild build){ + return Arrays.stream(payloads).allMatch(stack -> build.payloads.contains(stack)); + } + + @Override + public void consume(ModularCrafterBuild build){ + for(PayloadStack stack : payloads){ + build.payloads.remove(stack.item, stack.amount); + } + } + + public boolean wants(Payload pay){ + for(PayloadStack stack : payloads){ + if(stack.item == pay.content()) return true; + } + return false; + } + + @Override + public void setup(ModularCrafter block){ + block.acceptsPayload = true; + block.acceptsUnitPayloads = true; + for(PayloadStack stack : payloads){ + block.acceptedPayloads.add(stack.item); + } + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/EfficiencySourceModule.java b/src/meld/world/blocks/crafting/modules/rework/EfficiencySourceModule.java new file mode 100644 index 0000000..b73b9f2 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/EfficiencySourceModule.java @@ -0,0 +1,21 @@ +package meld.world.blocks.crafting.modules.rework; + +import meld.world.blocks.crafting.ModularCrafter.*; + +/// When you have multiple modules draw from the same pin, the first module in +/// the update order to craft something will block the rest from working. +/// This module is made for when you need this behavior, but without a shared input. +public class EfficiencySourceModule extends CrafterModule{ + /// Pins to provide efficiency on. + public int[] outputPins; + public float baseEfficiency = 1f; + + public EfficiencySourceModule(int... outputPins){ + this.outputPins = outputPins; + } + + @Override + public void update(ModularCrafterBuild build){ + for(int o : outputPins) build.setPin(o, baseEfficiency); + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/EfficiencyVoidModule.java b/src/meld/world/blocks/crafting/modules/rework/EfficiencyVoidModule.java new file mode 100644 index 0000000..1ca1e57 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/EfficiencyVoidModule.java @@ -0,0 +1,22 @@ +package meld.world.blocks.crafting.modules.rework; + +import arc.util.*; +import meld.world.blocks.crafting.ModularCrafter.*; + +/// Can be used to make blocks consume, regardless of whether they're doing something. +/// To do this, you can place it after a producer module, and make it consume from its input pin. +public class EfficiencyVoidModule extends CrafterModule{ + /// Pins to consume efficiency of. + public int[] inputPins; + /// The amount of efficiency consumed. + public float amount = Float.POSITIVE_INFINITY; + + public EfficiencyVoidModule(int... inputPins){ + this.inputPins = inputPins; + } + + @Override + public void update(ModularCrafterBuild build){ + for(int i : inputPins) build.setPin(i, Math.max(0f, build.getPin(i) - amount * build.timeScale() * Time.delta)); + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/ProduceHeatModule.java b/src/meld/world/blocks/crafting/modules/rework/ProduceHeatModule.java new file mode 100644 index 0000000..936b884 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/ProduceHeatModule.java @@ -0,0 +1,25 @@ +package meld.world.blocks.crafting.modules.rework; + +import arc.math.*; +import arc.util.*; +import meld.world.blocks.crafting.*; +import meld.world.blocks.crafting.ModularCrafter.*; +import meld.world.blocks.crafting.modules.rework.base.*; + +public class ProduceHeatModule extends ProduceModule{ + public float heatOutput = 10f; + public float warmupRate = 0.15f; + + public ProduceHeatModule(int... inputPins){ + super(inputPins); + } + + @Override + public void update(ModularCrafterBuild build){ + float input = takeEfficiency(build); + + build.heat = Mathf.approachDelta(build.heat, heatOutput * input, warmupRate * Time.delta); + + build.visualEfficiency = Math.max(input, build.visualEfficiency); + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/ProduceItemModule.java b/src/meld/world/blocks/crafting/modules/rework/ProduceItemModule.java new file mode 100644 index 0000000..c0d6b2e --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/ProduceItemModule.java @@ -0,0 +1,44 @@ +package meld.world.blocks.crafting.modules.rework; + +import meld.world.blocks.crafting.*; +import meld.world.blocks.crafting.ModularCrafter.*; +import meld.world.blocks.crafting.modules.rework.base.*; +import mindustry.type.*; +import java.util.*; + +public class ProduceItemModule extends ProduceDiscreteModule{ + public ItemStack[] items; + + public ProduceItemModule(int... inputPins){ + super(inputPins); + } + + @Override + public void update(ModularCrafterBuild build){ + super.update(build); + + for(ItemStack stack : items){ + build.dump(stack.item); + } + } + + @Override + public boolean canOutput(ModularCrafterBuild build){ + return Arrays.stream(items).allMatch(stack -> build.items.get(stack.item) + stack.amount <= build.block.itemCapacity); + } + + @Override + public void output(ModularCrafterBuild build){ + for(ItemStack stack : items){ + build.items.add(stack.item, stack.amount); + } + } + + @Override + public void setup(ModularCrafter block){ + block.hasItems = true; + for(ItemStack stack : items){ + block.dumpedItems.add(stack.item); + } + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/ProduceLiquidModule.java b/src/meld/world/blocks/crafting/modules/rework/ProduceLiquidModule.java new file mode 100644 index 0000000..bd82e2e --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/ProduceLiquidModule.java @@ -0,0 +1,53 @@ +package meld.world.blocks.crafting.modules.rework; + +import arc.util.*; +import meld.world.blocks.crafting.*; +import meld.world.blocks.crafting.ModularCrafter.*; +import meld.world.blocks.crafting.modules.rework.base.*; +import mindustry.type.*; + +public class ProduceLiquidModule extends ProduceModule{ + public LiquidStack[] liquids; + + public ProduceLiquidModule(int... inputPins){ + super(inputPins); + } + + @Override + public void update(ModularCrafterBuild build){ + //dump/check full + boolean full = false; + for(LiquidStack stack : liquids){ + build.dumpLiquid(stack.liquid); + + if(build.liquids.get(stack.liquid) >= build.block.liquidCapacity - 0.001f){ + full = true; + } + } + if(full) return; + + //Sum efficiencies and timescale up + float input = takeEfficiency(build); + + //continuously output based on efficiency + for(LiquidStack stack : liquids){ + build.handleLiquid(build, stack.liquid, + Math.min( + stack.amount * input * Time.delta, + build.block.liquidCapacity - build.liquids.get(stack.liquid) + ) + ); + } + + build.visualEfficiency = Math.max(input, build.visualEfficiency); + } + + @Override + public void setup(ModularCrafter block){ + block.hasLiquids = true; + block.outputsLiquid = true; + for(LiquidStack stack : liquids){ + block.dumpedLiquids.add(stack.liquid); + } + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/ProducePayloadModule.java b/src/meld/world/blocks/crafting/modules/rework/ProducePayloadModule.java new file mode 100644 index 0000000..6ce1c90 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/ProducePayloadModule.java @@ -0,0 +1,81 @@ +package meld.world.blocks.crafting.modules.rework; + +import arc.*; +import meld.world.blocks.crafting.*; +import meld.world.blocks.crafting.ModularCrafter.*; +import meld.world.blocks.crafting.modules.rework.base.*; +import mindustry.game.EventType.*; +import mindustry.gen.*; +import mindustry.type.*; +import mindustry.world.*; +import mindustry.world.blocks.payloads.*; + +import java.util.*; + +public class ProducePayloadModule extends ProduceDiscreteModule{ + public PayloadStack[] payloads; + + public ProducePayloadModule(int... inputPins){ + super(inputPins); + } + + @Override + public void update(ModularCrafterBuild build){ + super.update(build); + + //dump payloads + if(build.payload == null && build.payloads.any()){ + for(PayloadStack stack : payloads){ + if(build.payloads.contains(stack.item)){ + build.payloads.remove(stack.item); + + if(stack.item instanceof UnitType type){ + build.payload = new UnitPayload(type.create(build.team)); + Unit p = ((UnitPayload)build.payload).unit; + /*if(commandPos != null && p.isCommandable()){ + p.command().commandPosition(commandPos); + }*/ + Events.fire(new UnitCreateEvent(p, build)); + }else if(stack.item instanceof Block block){ + build.payload = new BuildPayload(block, build.team); + } + build.payVector.setZero(); + build.payRotation = build.rotdeg(); + break; + } + } + } + + if(build.payload != null && shouldDump(build.payload)){ + build.moveOutPayload(); + } + } + + @Override + public boolean canOutput(ModularCrafterBuild build){ + return Arrays.stream(payloads).allMatch(stack -> build.payloads.get(stack.item) + stack.amount <= build.modular.payloadCapacity); + } + + @Override + public void output(ModularCrafterBuild build){ + for(PayloadStack stack : payloads){ + build.payloads.add(stack.item, stack.amount); + } + } + + public boolean shouldDump(Payload pay){ + for(PayloadStack stack : payloads){ + if(stack.item == pay.content()) return true; + } + return false; + } + + @Override + public void setup(ModularCrafter block){ + block.rotate = true; + block.outputsPayload = true; + for(PayloadStack stack : payloads){ + block.dumpedPayloads.add(stack.item); + } + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/base/ConsumeDiscreteModule.java b/src/meld/world/blocks/crafting/modules/rework/base/ConsumeDiscreteModule.java new file mode 100644 index 0000000..f78f10e --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/base/ConsumeDiscreteModule.java @@ -0,0 +1,45 @@ +package meld.world.blocks.crafting.modules.rework.base; + +import arc.util.*; +import meld.world.blocks.crafting.ModularCrafter.*; + +public abstract class ConsumeDiscreteModule extends ConsumeModule{ + /// Pin to store consumption progress. + public int progressPin; + public float time = 60f; + + public float baseEfficiency = 0f; + public float efficiencyIncrease = 1f; + + public ConsumeDiscreteModule(int... outputPins){ + super(outputPins); + } + + public abstract boolean canConsume(ModularCrafterBuild build); + + public abstract void consume(ModularCrafterBuild build); + + @Override + public void update(ModularCrafterBuild build){ + float current = getCurrent(build); + //Get the amount of efficiency that was eaten + float consumed = (efficiencyIncrease - current - baseEfficiency) / (efficiencyIncrease - baseEfficiency); + float output = Math.max(baseEfficiency, current); + + //if efficiency has been used + if(consumed > 0f && canConsume(build)){ + float progress = build.getPin(progressPin); + progress += consumed * Time.delta; + output = baseEfficiency + efficiencyIncrease; + + //consumption + while(progress > time && canConsume(build)){ + consume(build); + progress -= time; + } + build.setPin(progressPin, progress); + } + + build.setPins(outputPins, output); + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/base/ConsumeModule.java b/src/meld/world/blocks/crafting/modules/rework/base/ConsumeModule.java new file mode 100644 index 0000000..07f00b8 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/base/ConsumeModule.java @@ -0,0 +1,33 @@ +package meld.world.blocks.crafting.modules.rework.base; + +import meld.world.blocks.crafting.ModularCrafter.*; + +public abstract class ConsumeModule extends CrafterModule{ + /// Pins to provide efficiency on. + public int[] outputPins; + /// Makes the module ignore other pins that are full until no more can be output. + public boolean dumpExtra = false; + + public ConsumeModule(int... outputPins){ + this.outputPins = outputPins; + } + + public float getCurrent(ModularCrafterBuild build){ + if(!dumpExtra){ + //Find the least consumed output, it signals inactivity + float max = Float.NEGATIVE_INFINITY; + for(int i : outputPins){ + max = Math.max(max, build.getPin(i)); + } + return max; + }else{ + //If we don't care about a few full inputs, pick the minimum instead + float min = Float.POSITIVE_INFINITY; + for(int i : outputPins){ + min = Math.min(min, build.getPin(i)); + } + return min; + } + + } +} diff --git a/src/meld/world/blocks/crafting/modules/rework/base/ProduceDiscreteModule.java b/src/meld/world/blocks/crafting/modules/rework/base/ProduceDiscreteModule.java new file mode 100644 index 0000000..d0b2213 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/base/ProduceDiscreteModule.java @@ -0,0 +1,38 @@ +package meld.world.blocks.crafting.modules.rework.base; + +import arc.util.*; +import meld.world.blocks.crafting.ModularCrafter.*; + +public abstract class ProduceDiscreteModule extends ProduceModule{ + + /// Pin used to store crafting progress. + public int progressPin; + public float time = 60f; + + public ProduceDiscreteModule(int... inputPins){ + super(inputPins); + } + + @Override + public void update(ModularCrafterBuild build){ + if(!canOutput(build)) return; + + //Sum efficiencies and timescale up + float input = takeEfficiency(build); + + float progress = build.getPin(progressPin); + progress += input * Time.delta; + + while(progress > time && canOutput(build)){ + output(build); + progress -= time; + } + build.setPin(progressPin, progress); + + build.visualEfficiency = Math.max(input, build.visualEfficiency); + } + + public abstract boolean canOutput(ModularCrafterBuild build); + + public abstract void output(ModularCrafterBuild build); +} diff --git a/src/meld/world/blocks/crafting/modules/rework/base/ProduceModule.java b/src/meld/world/blocks/crafting/modules/rework/base/ProduceModule.java new file mode 100644 index 0000000..428a3d7 --- /dev/null +++ b/src/meld/world/blocks/crafting/modules/rework/base/ProduceModule.java @@ -0,0 +1,23 @@ +package meld.world.blocks.crafting.modules.rework.base; + +import meld.world.blocks.crafting.ModularCrafter.*; + +public abstract class ProduceModule extends CrafterModule{ + /// Pins to consume efficiency from. + public int[] inputPins; + + public ProduceModule(int... inputPins){ + this.inputPins = inputPins; + } + + public float takeEfficiency(ModularCrafterBuild build){ + //Sum efficiencies and timescale up + float input = build.timeScale(); + for(int i : inputPins) input *= build.getPin(i); + + //After summing, subtract the final efficiency + for(int i : inputPins) build.setPin(i, build.getPin(i) - input); + + return input; + } +}