diff --git a/core/assets-raw/sprites/blocks/payload/block-forge.png b/core/assets-raw/sprites/blocks/payload/block-forge.png deleted file mode 100644 index 6d37c59675..0000000000 Binary files a/core/assets-raw/sprites/blocks/payload/block-forge.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/payload/block-loader.png b/core/assets-raw/sprites/blocks/payload/block-loader.png deleted file mode 100644 index 08c851a0cd..0000000000 Binary files a/core/assets-raw/sprites/blocks/payload/block-loader.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/payload/block-unloader.png b/core/assets-raw/sprites/blocks/payload/block-unloader.png deleted file mode 100644 index 2ee0b89d9b..0000000000 Binary files a/core/assets-raw/sprites/blocks/payload/block-unloader.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/payload/constructor-top.png b/core/assets-raw/sprites/blocks/payload/constructor-top.png new file mode 100644 index 0000000000..39a3ca79f3 Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/constructor-top.png differ diff --git a/core/assets-raw/sprites/blocks/payload/constructor.png b/core/assets-raw/sprites/blocks/payload/constructor.png new file mode 100644 index 0000000000..8f68ec1708 Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/constructor.png differ diff --git a/core/assets-raw/sprites/blocks/payload/deconstructor-top.png b/core/assets-raw/sprites/blocks/payload/deconstructor-top.png new file mode 100644 index 0000000000..e75a3e44cf Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/deconstructor-top.png differ diff --git a/core/assets-raw/sprites/blocks/payload/deconstructor.png b/core/assets-raw/sprites/blocks/payload/deconstructor.png new file mode 100644 index 0000000000..8c85cf1abc Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/deconstructor.png differ diff --git a/core/assets-raw/sprites/blocks/payload/factory-in-3.png b/core/assets-raw/sprites/blocks/payload/factory-in-3.png new file mode 100644 index 0000000000..9ea0ed0f19 Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/factory-in-3.png differ diff --git a/core/assets-raw/sprites/blocks/units/factory-in-5.png b/core/assets-raw/sprites/blocks/payload/factory-in-5.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-in-5.png rename to core/assets-raw/sprites/blocks/payload/factory-in-5.png diff --git a/core/assets-raw/sprites/blocks/units/factory-in-7.png b/core/assets-raw/sprites/blocks/payload/factory-in-7.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-in-7.png rename to core/assets-raw/sprites/blocks/payload/factory-in-7.png diff --git a/core/assets-raw/sprites/blocks/units/factory-in-9.png b/core/assets-raw/sprites/blocks/payload/factory-in-9.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-in-9.png rename to core/assets-raw/sprites/blocks/payload/factory-in-9.png diff --git a/core/assets-raw/sprites/blocks/payload/factory-out-3.png b/core/assets-raw/sprites/blocks/payload/factory-out-3.png new file mode 100644 index 0000000000..84caaa1c31 Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/factory-out-3.png differ diff --git a/core/assets-raw/sprites/blocks/units/factory-out-5.png b/core/assets-raw/sprites/blocks/payload/factory-out-5.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-out-5.png rename to core/assets-raw/sprites/blocks/payload/factory-out-5.png diff --git a/core/assets-raw/sprites/blocks/units/factory-out-7.png b/core/assets-raw/sprites/blocks/payload/factory-out-7.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-out-7.png rename to core/assets-raw/sprites/blocks/payload/factory-out-7.png diff --git a/core/assets-raw/sprites/blocks/units/factory-out-9.png b/core/assets-raw/sprites/blocks/payload/factory-out-9.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-out-9.png rename to core/assets-raw/sprites/blocks/payload/factory-out-9.png diff --git a/core/assets-raw/sprites/blocks/units/factory-top-3.png b/core/assets-raw/sprites/blocks/payload/factory-top-3.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-top-3.png rename to core/assets-raw/sprites/blocks/payload/factory-top-3.png diff --git a/core/assets-raw/sprites/blocks/units/factory-top-5.png b/core/assets-raw/sprites/blocks/payload/factory-top-5.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-top-5.png rename to core/assets-raw/sprites/blocks/payload/factory-top-5.png diff --git a/core/assets-raw/sprites/blocks/payload/large-constructor-top.png b/core/assets-raw/sprites/blocks/payload/large-constructor-top.png new file mode 100644 index 0000000000..eabff724be Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/large-constructor-top.png differ diff --git a/core/assets-raw/sprites/blocks/payload/large-constructor.png b/core/assets-raw/sprites/blocks/payload/large-constructor.png new file mode 100644 index 0000000000..f82c56b17d Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/large-constructor.png differ diff --git a/core/assets-raw/sprites/blocks/payload/payload-loader-top.png b/core/assets-raw/sprites/blocks/payload/payload-loader-top.png new file mode 100644 index 0000000000..2207273e02 Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/payload-loader-top.png differ diff --git a/core/assets-raw/sprites/blocks/payload/payload-loader.png b/core/assets-raw/sprites/blocks/payload/payload-loader.png new file mode 100644 index 0000000000..19762a9ef4 Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/payload-loader.png differ diff --git a/core/assets-raw/sprites/blocks/payload/payload-source.png b/core/assets-raw/sprites/blocks/payload/payload-source.png index 4c6b7b2070..a103553b71 100644 Binary files a/core/assets-raw/sprites/blocks/payload/payload-source.png and b/core/assets-raw/sprites/blocks/payload/payload-source.png differ diff --git a/core/assets-raw/sprites/blocks/payload/payload-unloader-top.png b/core/assets-raw/sprites/blocks/payload/payload-unloader-top.png new file mode 100644 index 0000000000..34ec963e54 Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/payload-unloader-top.png differ diff --git a/core/assets-raw/sprites/blocks/payload/payload-unloader.png b/core/assets-raw/sprites/blocks/payload/payload-unloader.png new file mode 100644 index 0000000000..2511a0db65 Binary files /dev/null and b/core/assets-raw/sprites/blocks/payload/payload-unloader.png differ diff --git a/core/assets-raw/sprites/blocks/units/factory-in-3.png b/core/assets-raw/sprites/blocks/units/factory-in-3.png deleted file mode 100644 index 7944814739..0000000000 Binary files a/core/assets-raw/sprites/blocks/units/factory-in-3.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/units/factory-out-3.png b/core/assets-raw/sprites/blocks/units/factory-out-3.png deleted file mode 100644 index 4553a690dd..0000000000 Binary files a/core/assets-raw/sprites/blocks/units/factory-out-3.png and /dev/null differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 6b6df7cfd7..1a85f5e625 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1341,10 +1341,16 @@ block.disassembler.name = Disassembler block.silicon-crucible.name = Silicon Crucible block.overdrive-dome.name = Overdrive Dome block.interplanetary-accelerator.name = Interplanetary Accelerator -#experimental, may be removed -block.block-forge.name = Block Forge -block.block-loader.name = Block Loader -block.block-unloader.name = Block Unloader +block.constructor.name = Constructor +block.constructor.description = Fabricates structures up to 2x2 tiles in size. +block.large-constructor.name = Large Constructor +block.large-constructor.description = Fabricates structures up to 4x4 tiles in size. +block.deconstructor.name = Deconstructor +block.deconstructor.description = Deconstructs structures and units. Returns 100% of build cost. +block.payload-loader.name = Payload Loader +block.payload-loader.description = Load liquids and items into blocks. +block.payload-unloader.name = Payload Unloader +block.payload-unloader.description = Unloads liquids and items from blocks. block.switch.name = Switch block.micro-processor.name = Micro Processor diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index c2697d7487..e4ec21e238 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -64,7 +64,7 @@ public class Blocks implements ContentList{ duct, ductRouter, ductBridge, //liquid - mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, platedConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit, + mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, platedConduit, liquidRouter, liquidContainer, liquidTank, liquidJunction, bridgeConduit, phaseConduit, //power combustionGenerator, thermalGenerator, steamGenerator, differentialGenerator, rtgGenerator, solarPanel, largeSolarPanel, thoriumReactor, @@ -86,18 +86,19 @@ public class Blocks implements ContentList{ repairPoint, repairTurret, //payloads - payloadConveyor, payloadRouter, payloadPropulsionTower, + payloadConveyor, payloadRouter, payloadPropulsionTower, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader, //logic message, switchBlock, microProcessor, logicProcessor, hyperProcessor, largeLogicDisplay, logicDisplay, memoryCell, memoryBank, //campaign - launchPad, interplanetaryAccelerator, - - //misc experimental - blockForge, blockLoader, blockUnloader + launchPad, interplanetaryAccelerator ; + /** @deprecated use the blocks with proper names, */ + @Deprecated + public static Block blockForge, blockLoader, blockUnloader; + @Override public void load(){ //region environment @@ -125,7 +126,7 @@ public class Blocks implements ContentList{ isLiquid = true; status = StatusEffects.wet; statusDuration = 120f; - drownTime = 140f; + drownTime = 200f; cacheLayer = CacheLayer.water; albedo = 0.9f; }}; @@ -158,7 +159,7 @@ public class Blocks implements ContentList{ variants = 0; status = StatusEffects.wet; statusDuration = 140f; - drownTime = 120f; + drownTime = 200f; liquidDrop = Liquids.water; isLiquid = true; cacheLayer = CacheLayer.water; @@ -186,7 +187,7 @@ public class Blocks implements ContentList{ }}; tar = new Floor("tar"){{ - drownTime = 150f; + drownTime = 230f; status = StatusEffects.tarred; statusDuration = 240f; speedMultiplier = 0.19f; @@ -213,7 +214,7 @@ public class Blocks implements ContentList{ }}; slag = new Floor("molten-slag"){{ - drownTime = 150f; + drownTime = 230f; status = StatusEffects.melting; statusDuration = 240f; speedMultiplier = 0.19f; @@ -233,6 +234,12 @@ public class Blocks implements ContentList{ placeableOn = false; solid = true; variants = 0; + canShadow = false; + }}; + + empty = new EmptyFloor("empty"){{ + placeableOn = false; + solid = true; }}; stone = new Floor("stone"); @@ -337,34 +344,36 @@ public class Blocks implements ContentList{ attributes.set(Attribute.oil, 1.6f); }}; + moss = new Floor("moss"){{ + variants = 3; + attributes.set(Attribute.spores, 0.15f); + }}; + + sporeMoss = new Floor("spore-moss"){{ + variants = 3; + attributes.set(Attribute.spores, 0.3f); + }}; + stoneWall = new StaticWall("stone-wall"){{ variants = 2; }}; sporeWall = new StaticWall("spore-wall"){{ - variants = 2; - taintedWater.asFloor().wall = deepTaintedWater.asFloor().wall = this; + taintedWater.asFloor().wall = deepTaintedWater.asFloor().wall = sporeMoss.asFloor().wall = this; }}; - dirtWall = new StaticWall("dirt-wall"){{ - variants = 2; - }}; + dirtWall = new StaticWall("dirt-wall"); - daciteWall = new StaticWall("dacite-wall"){{ - variants = 2; - }}; + daciteWall = new StaticWall("dacite-wall"); iceWall = new StaticWall("ice-wall"){{ - variants = 2; iceSnow.asFloor().wall = this; + albedo = 0.6f; }}; - snowWall = new StaticWall("snow-wall"){{ - variants = 2; - }}; + snowWall = new StaticWall("snow-wall"); duneWall = new StaticWall("dune-wall"){{ - variants = 2; basalt.asFloor().wall = darksandWater.asFloor().wall = darksandTaintedWater.asFloor().wall = this; }}; @@ -377,21 +386,15 @@ public class Blocks implements ContentList{ shrubs = new StaticWall("shrubs"); - shaleWall = new StaticWall("shale-wall"){{ - variants = 2; - }}; + shaleWall = new StaticWall("shale-wall"); sporePine = new StaticTree("spore-pine"){{ - variants = 0; + moss.asFloor().wall = this; }}; - snowPine = new StaticTree("snow-pine"){{ - variants = 0; - }}; + snowPine = new StaticTree("snow-pine"); - pine = new StaticTree("pine"){{ - variants = 0; - }}; + pine = new StaticTree("pine"); whiteTreeDead = new TreeBlock("white-tree-dead"); @@ -404,7 +407,7 @@ public class Blocks implements ContentList{ boulder = new Prop("boulder"){{ variants = 2; - stone.asFloor().decoration = this; + stone.asFloor().decoration = craters.asFloor().decoration = charr.asFloor().decoration = this; }}; snowBoulder = new Prop("snow-boulder"){{ @@ -414,18 +417,22 @@ public class Blocks implements ContentList{ shaleBoulder = new Prop("shale-boulder"){{ variants = 2; + shale.asFloor().decoration = this; }}; sandBoulder = new Prop("sand-boulder"){{ variants = 2; + sand.asFloor().decoration = this; }}; daciteBoulder = new Prop("dacite-boulder"){{ variants = 2; + dacite.asFloor().decoration = this; }}; basaltBoulder = new Prop("basalt-boulder"){{ variants = 2; + basalt.asFloor().decoration = hotrock.asFloor().decoration = darksand.asFloor().decoration = magmarock.asFloor().decoration = this; }}; moss = new Floor("moss"){{ @@ -1130,10 +1137,16 @@ public class Blocks implements ContentList{ liquidCapacity = 20f; }}; + liquidContainer = new LiquidRouter("liquid-container"){{ + requirements(Category.liquid, with(Items.titanium, 10, Items.metaglass, 15)); + liquidCapacity = 700f; + size = 2; + }}; + liquidTank = new LiquidRouter("liquid-tank"){{ - requirements(Category.liquid, with(Items.titanium, 25, Items.metaglass, 25)); + requirements(Category.liquid, with(Items.titanium, 30, Items.metaglass, 40)); size = 3; - liquidCapacity = 1500f; + liquidCapacity = 1800f; health = 500; }}; @@ -1899,6 +1912,7 @@ public class Blocks implements ContentList{ length = 200f; hitEffect = Fx.hitMeltdown; hitColor = Pal.meltdownHit; + status = StatusEffects.melting; drawSize = 420f; incendChance = 0.4f; @@ -2082,6 +2096,49 @@ public class Blocks implements ContentList{ consumes.power(6f); }}; + deconstructor = new PayloadDeconstructor("deconstructor"){{ + requirements(Category.units, with(Items.thorium, 250, Items.silicon, 200, Items.graphite, 250)); + itemCapacity = 250; + consumes.power(3f); + size = 5; + deconstructSpeed = 2f; + }}; + + constructor = new Constructor("constructor"){{ + requirements(Category.units, with(Items.thorium, 100)); + hasPower = true; + consumes.power(2f); + size = 3; + }}; + + largeConstructor = new Constructor("large-constructor"){{ + requirements(Category.units, with(Items.thorium, 100)); + hasPower = true; + consumes.power(2f); + maxBlockSize = 4; + minBlockSize = 3; + size = 5; + }}; + + payloadLoader = new PayloadLoader("payload-loader"){{ + requirements(Category.units, with(Items.thorium, 100)); + hasPower = true; + consumes.power(2f); + size = 3; + }}; + + payloadUnloader = new PayloadUnloader("payload-unloader"){{ + requirements(Category.units, with(Items.thorium, 100)); + hasPower = true; + consumes.power(2f); + size = 3; + }}; + + //TODO deprecated + blockForge = constructor; + blockLoader = payloadLoader; + blockUnloader = payloadUnloader; + //endregion //region sandbox @@ -2244,30 +2301,6 @@ public class Blocks implements ContentList{ size = 6; }}; - //endregion - //region experimental - - blockForge = new BlockForge("block-forge"){{ - requirements(Category.units, BuildVisibility.debugOnly, with(Items.thorium, 100)); - hasPower = true; - consumes.power(2f); - size = 3; - }}; - - blockLoader = new BlockLoader("block-loader"){{ - requirements(Category.units, BuildVisibility.debugOnly, with(Items.thorium, 100)); - hasPower = true; - consumes.power(2f); - size = 3; - }}; - - blockUnloader = new BlockUnloader("block-unloader"){{ - requirements(Category.units, BuildVisibility.debugOnly, with(Items.thorium, 100)); - hasPower = true; - consumes.power(2f); - size = 3; - }}; - //endregion } } diff --git a/core/src/mindustry/world/blocks/payloads/BlockProducer.java b/core/src/mindustry/world/blocks/payloads/BlockProducer.java index ec8642cc90..a3186a0dc3 100644 --- a/core/src/mindustry/world/blocks/payloads/BlockProducer.java +++ b/core/src/mindustry/world/blocks/payloads/BlockProducer.java @@ -5,6 +5,7 @@ import arc.math.*; import arc.util.*; import arc.util.io.*; import mindustry.*; +import mindustry.content.*; import mindustry.entities.units.*; import mindustry.gen.*; import mindustry.graphics.*; @@ -34,7 +35,14 @@ public abstract class BlockProducer extends PayloadBlock{ @Override public TextureRegion[] icons(){ - return new TextureRegion[]{region, outRegion}; + return new TextureRegion[]{region, outRegion, topRegion}; + } + + @Override + public void drawRequestRegion(BuildPlan req, Eachable list){ + Draw.rect(region, req.drawx(), req.drawy()); + Draw.rect(outRegion, req.drawx(), req.drawy(), req.rotation * 90); + Draw.rect(topRegion, req.drawx(), req.drawy()); } @Override @@ -43,12 +51,6 @@ public abstract class BlockProducer extends PayloadBlock{ bars.add("progress", (BlockProducerBuild entity) -> new Bar("bar.progress", Pal.ammo, () -> entity.recipe() == null ? 0f : (entity.progress / entity.recipe().buildCost))); } - - @Override - public void drawRequestRegion(BuildPlan req, Eachable list){ - Draw.rect(region, req.drawx(), req.drawy()); - Draw.rect(outRegion, req.drawx(), req.drawy(), req.rotation * 90); - } public abstract class BlockProducerBuild extends PayloadBlockBuild{ public float progress, time, heat; @@ -85,6 +87,7 @@ public abstract class BlockProducer extends PayloadBlock{ if(progress >= recipe.buildCost){ consume(); payload = new BuildPayload(recipe, team); + Fx.placeBlock.at(x, y, payload.size() / tilesize); payVector.setZero(); progress %= 1f; } @@ -109,6 +112,7 @@ public abstract class BlockProducer extends PayloadBlock{ for(TextureRegion region : recipe.getGeneratedIcons()){ Shaders.blockbuild.region = region; + Shaders.blockbuild.time = time; Shaders.blockbuild.progress = progress / recipe.buildCost; Draw.rect(region, x, y, recipe.rotate ? rotdeg() : 0); @@ -126,6 +130,9 @@ public abstract class BlockProducer extends PayloadBlock{ } drawPayload(); + + Draw.z(Layer.blockBuilding + 1.1f); + Draw.rect(topRegion, x, y); } @Override diff --git a/core/src/mindustry/world/blocks/payloads/BlockUnloader.java b/core/src/mindustry/world/blocks/payloads/BlockUnloader.java deleted file mode 100644 index 8f4a644fce..0000000000 --- a/core/src/mindustry/world/blocks/payloads/BlockUnloader.java +++ /dev/null @@ -1,67 +0,0 @@ -package mindustry.world.blocks.payloads; - -import mindustry.gen.*; -import mindustry.type.*; - -import static mindustry.Vars.*; - -public class BlockUnloader extends BlockLoader{ - - public BlockUnloader(String name){ - super(name); - } - - @Override - public boolean outputsItems(){ - return true; - } - - @Override - public boolean rotatedOutput(int x, int y){ - return false; - } - - public class BlockUnloaderBuild extends BlockLoaderBuild{ - - @Override - public boolean acceptItem(Building source, Item item){ - return false; - } - - @Override - public void updateTile(){ - if(shouldExport()){ - moveOutPayload(); - }else if(moveInPayload()){ - - //load up items - if(payload.block().hasItems && !full()){ - if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){ - //load up items a set amount of times - for(int j = 0; j < itemsLoaded && !full(); j++){ - for(int i = 0; i < items.length(); i++){ - if(payload.build.items.get(i) > 0){ - Item item = content.item(i); - payload.build.items.remove(item, 1); - items.add(item, 1); - break; - } - } - } - } - } - } - - dump(); - } - - public boolean full(){ - return items.total() >= itemCapacity; - } - - @Override - public boolean shouldExport(){ - return payload != null && (payload.block().hasItems && payload.build.items.empty()); - } - } -} diff --git a/core/src/mindustry/world/blocks/payloads/BuildPayload.java b/core/src/mindustry/world/blocks/payloads/BuildPayload.java index d9e6c08fa0..ad6a6a0fc9 100644 --- a/core/src/mindustry/world/blocks/payloads/BuildPayload.java +++ b/core/src/mindustry/world/blocks/payloads/BuildPayload.java @@ -5,6 +5,7 @@ import arc.util.io.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.type.*; import mindustry.world.*; import static mindustry.Vars.*; @@ -33,6 +34,16 @@ public class BuildPayload implements Payload{ build.dropped(); } + @Override + public ItemStack[] requirements(){ + return build.block.requirements; + } + + @Override + public float buildTime(){ + return build.block.buildCost; + } + @Override public float x(){ return build.x; @@ -61,9 +72,14 @@ public class BuildPayload implements Payload{ build.set(x, y); } + @Override + public void drawShadow(float alpha){ + Drawf.shadow(build.x, build.y, build.block.size * tilesize * 2f, alpha); + } + @Override public void draw(){ - Drawf.shadow(build.x, build.y, build.block.size * tilesize * 2f); + drawShadow(1f); Draw.rect(build.block.fullIcon, build.x, build.y); } diff --git a/core/src/mindustry/world/blocks/payloads/BlockForge.java b/core/src/mindustry/world/blocks/payloads/Constructor.java similarity index 88% rename from core/src/mindustry/world/blocks/payloads/BlockForge.java rename to core/src/mindustry/world/blocks/payloads/Constructor.java index 52827780af..4359fd581d 100644 --- a/core/src/mindustry/world/blocks/payloads/BlockForge.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.ui.*; import mindustry.world.*; import mindustry.world.blocks.*; import mindustry.world.meta.*; @@ -14,17 +13,17 @@ import mindustry.world.meta.*; import static mindustry.Vars.*; /** Configurable BlockProducer variant. */ -public class BlockForge extends BlockProducer{ +public class Constructor extends BlockProducer{ public float buildSpeed = 0.4f; public int minBlockSize = 1, maxBlockSize = 2; - public BlockForge(String name){ + public Constructor(String name){ super(name); size = 3; configurable = true; - config(Block.class, (BlockForgeBuild tile, Block block) -> { + config(Block.class, (ConstructorBuild tile, Block block) -> { if(tile.recipe != block) tile.progress = 0f; if(canProduce(block)){ tile.recipe = block; @@ -43,7 +42,7 @@ public class BlockForge extends BlockProducer{ return b.isVisible() && b.size >= minBlockSize && b.size <= maxBlockSize; } - public class BlockForgeBuild extends BlockProducerBuild{ + public class ConstructorBuild extends BlockProducerBuild{ public @Nullable Block recipe; @Override @@ -53,7 +52,7 @@ public class BlockForge extends BlockProducer{ @Override public void buildConfiguration(Table table){ - ItemSelection.buildTable(table, content.blocks().select(BlockForge.this::canProduce), () -> recipe, this::configure); + ItemSelection.buildTable(table, content.blocks().select(Constructor.this::canProduce), () -> recipe, this::configure); } @Override diff --git a/core/src/mindustry/world/blocks/payloads/Payload.java b/core/src/mindustry/world/blocks/payloads/Payload.java index 9563db51d3..4be19f66bf 100644 --- a/core/src/mindustry/world/blocks/payloads/Payload.java +++ b/core/src/mindustry/world/blocks/payloads/Payload.java @@ -7,6 +7,7 @@ import arc.util.io.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.ui.*; +import mindustry.type.*; import mindustry.world.*; import static mindustry.Vars.*; @@ -20,6 +21,8 @@ public interface Payload extends Position{ /** draws this payload at a position. */ void draw(); + void drawShadow(float alpha); + /** @return hitbox size of the payload. */ float size(); @@ -27,6 +30,12 @@ public interface Payload extends Position{ float y(); + /** @return the items needed to make this payload; may be empty. */ + ItemStack[] requirements(); + + /** @return the time taken to build this payload. */ + float buildTime(); + /** @return whether this payload was dumped. */ default boolean dump(){ return false; diff --git a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java index 45bb21eee0..a7885e76c7 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java @@ -9,6 +9,7 @@ import mindustry.annotations.Annotations.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.world.*; +import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -24,6 +25,7 @@ public class PayloadBlock extends Block{ update = true; sync = true; + envEnabled |= Env.space; } public static boolean blends(Building build, int direction){ @@ -78,16 +80,16 @@ public class PayloadBlock extends Block{ } @Override - public boolean canControlSelect(Unit player){ - return !player.spawnedByCore && this.payload == null && acceptUnitPayload(player) && player.tileOn() != null && player.tileOn().build == this; + public boolean canControlSelect(Player player){ + return !player.unit().spawnedByCore && this.payload == null && acceptUnitPayload(player.unit()) && player.tileOn() != null && player.tileOn().build == this; } @Override - public void onControlSelect(Unit player){ + public void onControlSelect(Player player){ float x = player.x, y = player.y; - handleUnitPayload(player, p -> payload = (T)p); + acceptPlayerPayload(player, p -> payload = (T)p); this.payVector.set(x, y).sub(this).clamp(-size * tilesize / 2f, -size * tilesize / 2f, size * tilesize / 2f, size * tilesize / 2f); - this.payRotation = player.rotation; + this.payRotation = player.unit().rotation; } @Override diff --git a/core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java b/core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java new file mode 100644 index 0000000000..328549f0a4 --- /dev/null +++ b/core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java @@ -0,0 +1,205 @@ +package mindustry.world.blocks.payloads; + +import arc.graphics.g2d.*; +import arc.math.*; +import arc.util.*; +import arc.util.io.*; +import mindustry.content.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.ui.*; + +import static mindustry.Vars.*; + +public class PayloadDeconstructor extends PayloadBlock{ + public float maxPayloadSize = 4; + public float deconstructSpeed = 2.5f; + public int dumpRate = 4; + + public PayloadDeconstructor(String name){ + super(name); + + outputsPayload = false; + acceptsPayload = true; + update = true; + rotate = false; + solid = true; + size = 5; + payloadSpeed = 1f; + //make sure to display large units. + clipSize = 120; + hasItems = true; + hasPower = true; + itemCapacity = 100; + } + + @Override + public TextureRegion[] icons(){ + return new TextureRegion[]{region, topRegion}; + } + + @Override + public void setBars(){ + super.setBars(); + + bars.add("progress", (PayloadDeconstructorBuild e) -> new Bar("bar.progress", Pal.ammo, () -> e.progress)); + } + + public class PayloadDeconstructorBuild extends PayloadBlockBuild{ + public @Nullable Payload deconstructing; + public @Nullable float[] accum; + public float progress; + public float time, speedScl; + + @Override + public void draw(){ + Draw.rect(region, x, y); + + //draw input + for(int i = 0; i < 4; i++){ + if(blends(i)){ + Draw.rect(inRegion, x, y, (i * 90) - 180); + } + } + + Draw.z(Layer.blockOver); + drawPayload(); + if(deconstructing != null){ + deconstructing.set(x + payVector.x, y + payVector.y, payRotation); + + Draw.z(Layer.blockOver); + deconstructing.drawShadow(1f - progress); + + //TODO looks really bad + Draw.draw(Layer.blockOver, () -> { + Drawf.construct(x, y, deconstructing.icon(), Pal.remove, deconstructing instanceof BuildPayload ? 0f : payRotation - 90f, 1f - progress, 1f - progress, time); + Draw.color(Pal.remove); + Draw.alpha(1f); + + Lines.lineAngleCenter(x + Mathf.sin(time, 20f, tilesize / 2f * block.size - 3f), y, 90f, block.size * tilesize - 6f); + + Draw.reset(); + }); + } + + Draw.rect(topRegion, x, y); + } + + @Override + public void handlePayload(Building source, Payload payload){ + super.handlePayload(source, payload); + accum = null; + } + + @Override + public boolean acceptPayload(Building source, Payload payload){ + return deconstructing == null && super.acceptPayload(source, payload) && payload.requirements().length > 0 && payload.fits(maxPayloadSize); + } + + @Override + public void updateTile(){ + if(items.total() > 0){ + for(int i = 0; i < dumpRate; i++){ + dumpAccumulate(); + } + } + + if(deconstructing == null){ + progress = 0f; + } + + payRotation = Angles.moveToward(payRotation, 90f, payloadRotateSpeed * edelta()); + + if(deconstructing != null){ + var reqs = deconstructing.requirements(); + if(accum == null || reqs.length != accum.length){ + accum = new float[reqs.length]; + } + + //check if there is enough space to get the items for deconstruction + boolean canProgress = items.total() <= itemCapacity; + if(canProgress){ + for(var ac : accum){ + if(ac >= 1f){ + canProgress = false; + break; + } + } + } + + //move progress forward if possible + if(canProgress){ + float shift = edelta() * deconstructSpeed / deconstructing.buildTime(); + float realShift = Math.min(shift, 1f - progress); + + progress += shift; + time += edelta(); + + for(int i = 0; i < reqs.length; i++){ + accum[i] += reqs[i].amount * realShift; + } + } + + speedScl = Mathf.lerpDelta(speedScl, canProgress ? 1f : 0f, 0.1f); + + //transfer items from accumulation buffer into block inventory when they reach integers + for(int i = 0; i < reqs.length; i++){ + int taken = Math.min((int)accum[i], itemCapacity - items.total()); + if(taken > 0){ + items.add(reqs[i].item, taken); + accum[i] -= taken; + } + } + + //finish deconstruction, prepare for next payload. + if(progress >= 1f){ + Fx.breakBlock.at(x, y, deconstructing.size() / tilesize); + + deconstructing = null; + accum = null; + } + }else if(moveInPayload(false) && payload != null){ + accum = new float[payload.requirements().length]; + deconstructing = payload; + payload = null; + progress = 0f; + } + } + + @Override + public boolean shouldConsume(){ + return deconstructing != null && enabled; + } + + @Override + public void write(Writes write){ + super.write(write); + + write.f(progress); + if(accum != null){ + write.s(accum.length); + for(float v : accum){ + write.f(v); + } + }else{ + write.s(0); + } + Payload.write(deconstructing, write); + } + + @Override + public void read(Reads read, byte revision){ + super.read(read, revision); + + progress = read.f(); + short accums = read.s(); + if(accums > 0){ + accum = new float[accums]; + for(int i = 0; i < accums; i++){ + accum[i] = read.f(); + } + } + deconstructing = Payload.read(read); + } + } +} diff --git a/core/src/mindustry/world/blocks/payloads/BlockLoader.java b/core/src/mindustry/world/blocks/payloads/PayloadLoader.java similarity index 74% rename from core/src/mindustry/world/blocks/payloads/BlockLoader.java rename to core/src/mindustry/world/blocks/payloads/PayloadLoader.java index 001f93712a..04c2d7c60b 100644 --- a/core/src/mindustry/world/blocks/payloads/BlockLoader.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadLoader.java @@ -11,20 +11,21 @@ import mindustry.ui.*; import static mindustry.Vars.*; -public class BlockLoader extends PayloadBlock{ +public class PayloadLoader extends PayloadBlock{ public final int timerLoad = timers++; public float loadTime = 2f; - public int itemsLoaded = 5; - public float liquidsLoaded = 5f; + public int itemsLoaded = 8; + public float liquidsLoaded = 40f; public int maxBlockSize = 2; - public BlockLoader(String name){ + public PayloadLoader(String name){ super(name); hasItems = true; - itemCapacity = 25; - //liquidCapacity = 25; + hasLiquids = true; + itemCapacity = 100; + liquidCapacity = 100f; update = true; outputsPayload = true; size = 3; @@ -45,7 +46,7 @@ public class BlockLoader extends PayloadBlock{ public void setBars(){ super.setBars(); - bars.add("progress", (BlockLoaderBuild entity) -> new Bar(() -> Core.bundle.format("bar.items", entity.payload == null ? 0 : entity.payload.build.items.total()), () -> Pal.items, entity::fraction)); + bars.add("progress", (PayloadLoaderBuild entity) -> new Bar(() -> Core.bundle.format("bar.items", entity.payload == null ? 0 : entity.payload.build.items.total()), () -> Pal.items, entity::fraction)); } @Override @@ -56,14 +57,14 @@ public class BlockLoader extends PayloadBlock{ Draw.rect(topRegion, req.drawx(), req.drawy()); } - public class BlockLoaderBuild extends PayloadBlockBuild{ + public class PayloadLoaderBuild extends PayloadBlockBuild{ @Override public boolean acceptPayload(Building source, Payload payload){ return super.acceptPayload(source, payload) && - (payload instanceof BuildPayload build) && - ((build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize)/* || - ((BlockPayload)payload).entity.block().hasLiquids && ((BlockPayload)payload).block().liquidCapacity >= 10f)*/); + payload instanceof BuildPayload build && + ((build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize) || + build.build.block().hasLiquids && build.block().liquidCapacity >= 10f); } @Override @@ -71,6 +72,11 @@ public class BlockLoader extends PayloadBlock{ return items.total() < itemCapacity; } + @Override + public boolean acceptLiquid(Building source, Liquid liquid){ + return liquids.current() == liquid || liquids.currentAmount() < 0.2f; + } + @Override public void draw(){ Draw.rect(region, x, y); @@ -120,17 +126,17 @@ public class BlockLoader extends PayloadBlock{ } } - //load up liquids (disabled) - /* + //load up liquids if(payload.block().hasLiquids && liquids.total() >= 0.001f){ Liquid liq = liquids.current(); float total = liquids.currentAmount(); - float flow = Math.min(Math.min(liquidsLoaded * delta(), payload.block().liquidCapacity - payload.entity.liquids.get(liq) - 0.0001f), total); - if(payload.entity.acceptLiquid(payload.entity, liq, flow)){ - payload.entity.liquids.add(liq, flow); + float flow = Math.min(Math.min(liquidsLoaded * edelta(), payload.block().liquidCapacity - payload.build.liquids.get(liq)), total); + //TODO potential crash here + if(payload.build.acceptLiquid(payload.build, liq)){ + payload.build.liquids.add(liq, flow); liquids.remove(liq, flow); } - }*/ + } } } @@ -139,8 +145,8 @@ public class BlockLoader extends PayloadBlock{ } public boolean shouldExport(){ - return payload != null && - ((payload.block().hasLiquids && payload.build.liquids.total() >= payload.block().liquidCapacity - 0.001f) || + return payload != null && ( + (payload.block().hasLiquids && payload.build.liquids.total() >= payload.block().liquidCapacity - 0.001f) || (payload.block().hasItems && payload.build.items.total() >= payload.block().itemCapacity)); } } diff --git a/core/src/mindustry/world/blocks/payloads/PayloadUnloader.java b/core/src/mindustry/world/blocks/payloads/PayloadUnloader.java new file mode 100644 index 0000000000..7d63380528 --- /dev/null +++ b/core/src/mindustry/world/blocks/payloads/PayloadUnloader.java @@ -0,0 +1,97 @@ +package mindustry.world.blocks.payloads; + +import mindustry.gen.*; +import mindustry.type.*; + +import static mindustry.Vars.*; + +public class PayloadUnloader extends PayloadLoader{ + public int offloadSpeed = 4; + + public PayloadUnloader(String name){ + super(name); + } + + @Override + public boolean outputsItems(){ + return true; + } + + @Override + public boolean rotatedOutput(int x, int y){ + return false; + } + + public class PayloadUnloaderBuild extends PayloadLoaderBuild{ + + @Override + public boolean acceptItem(Building source, Item item){ + return false; + } + + @Override + public boolean acceptLiquid(Building source, Liquid liquid){ + return false; + } + + @Override + public void updateTile(){ + if(shouldExport()){ + //one-use, disposable block + if(payload.block().instantDeconstruct){ + payload.block().breakEffect.at(this, payload.block().size); + payload = null; + }else{ + moveOutPayload(); + } + }else if(moveInPayload()){ + + //unload items + if(payload.block().hasItems && !full()){ + if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){ + //load up items a set amount of times + for(int j = 0; j < itemsLoaded && !full(); j++){ + for(int i = 0; i < items.length(); i++){ + if(payload.build.items.get(i) > 0){ + Item item = content.item(i); + payload.build.items.remove(item, 1); + items.add(item, 1); + break; + } + } + } + } + } + + //unload liquids + //TODO tile is null may crash + if(payload.block().hasLiquids && payload.build.liquids.currentAmount() >= 0.01f && + (liquids.current() == payload.build.liquids.current() || liquids.currentAmount() <= 0.2f)){ + var liq = payload.build.liquids.current(); + float remaining = liquidCapacity - liquids.currentAmount(); + float flow = Math.min(Math.min(liquidsLoaded * delta(), remaining), payload.build.liquids.currentAmount()); + + liquids.add(liq, flow); + payload.build.liquids.remove(liq, flow); + } + } + + dumpLiquid(liquids.current()); + for(int i = 0; i < offloadSpeed; i++){ + dumpAccumulate(); + } + } + + public boolean full(){ + return items.total() >= itemCapacity; + } + + @Override + public boolean shouldExport(){ + return payload != null && ( + (!payload.block().hasItems || payload.build.items.empty()) && + (!payload.block().hasLiquids || payload.build.liquids.currentAmount() <= 0.001f) + ); + } + } +} diff --git a/core/src/mindustry/world/blocks/payloads/UnitPayload.java b/core/src/mindustry/world/blocks/payloads/UnitPayload.java index 99558971da..838f987477 100644 --- a/core/src/mindustry/world/blocks/payloads/UnitPayload.java +++ b/core/src/mindustry/world/blocks/payloads/UnitPayload.java @@ -13,6 +13,7 @@ import mindustry.entities.EntityCollisions.*; import mindustry.entities.*; import mindustry.game.EventType.*; import mindustry.gen.*; +import mindustry.type.*; import static mindustry.Vars.*; @@ -39,6 +40,16 @@ public class UnitPayload implements Payload{ showOverlay(icon.getRegion()); } + @Override + public ItemStack[] requirements(){ + return unit.type.getTotalRequirements(); + } + + @Override + public float buildTime(){ + return unit.type.getBuildTime(); + } + @Override public void write(Writes write){ write.b(payloadUnit); @@ -105,11 +116,20 @@ public class UnitPayload implements Payload{ //prevents stacking unit.vel.add(Mathf.range(0.5f), Mathf.range(0.5f)); unit.add(); + unit.unloaded(); Events.fire(new UnitUnloadEvent(unit)); return true; } + @Override + public void drawShadow(float alpha){ + //TODO should not happen + if(unit.type == null) return; + + unit.type.drawSoftShadow(unit, alpha); + } + @Override public void draw(){ //TODO should not happen