WIP payload deconstructor
This commit is contained in:
@@ -96,7 +96,7 @@ public class Blocks implements ContentList{
|
||||
repairPoint, repairTurret, resupplyPoint,
|
||||
|
||||
//payloads
|
||||
payloadConveyor, payloadRouter, payloadPropulsionTower,
|
||||
payloadConveyor, payloadRouter, payloadPropulsionTower, payloadDeconstructor, blockForge, blockLoader, blockUnloader,
|
||||
|
||||
//logic
|
||||
message, switchBlock, microProcessor, logicProcessor, hyperProcessor, largeLogicDisplay, logicDisplay, memoryCell, memoryBank,
|
||||
@@ -105,10 +105,7 @@ public class Blocks implements ContentList{
|
||||
launchPad, payloadLaunchPad, interplanetaryAccelerator,
|
||||
|
||||
//nuclear?
|
||||
nuclearWarhead, warheadAssembler, ballisticSilo, //TODO
|
||||
|
||||
//misc experimental
|
||||
blockForge, blockLoader, blockUnloader
|
||||
nuclearWarhead, warheadAssembler, ballisticSilo //TODO
|
||||
;
|
||||
|
||||
@Override
|
||||
@@ -2206,6 +2203,35 @@ public class Blocks implements ContentList{
|
||||
consumes.power(6f);
|
||||
}};
|
||||
|
||||
payloadDeconstructor = new PayloadDeconstructor("payload-deconstructor"){{
|
||||
requirements(Category.units, with(Items.graphite, 30, Items.silicon, 30, Items.copper, 30));
|
||||
itemCapacity = 200;
|
||||
consumes.power(1f);
|
||||
size = 5;
|
||||
deconstructSpeed = 2f;
|
||||
}};
|
||||
|
||||
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
|
||||
//region sandbox
|
||||
|
||||
@@ -2390,30 +2416,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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,21 @@ public class ItemSeq implements Iterable<ItemStack>, JsonSerializable{
|
||||
return out;
|
||||
}
|
||||
|
||||
public ItemStack[] toArray(){
|
||||
int count = 0;
|
||||
for(int value : values){
|
||||
if(value != 0) count++;
|
||||
}
|
||||
ItemStack[] result = new ItemStack[count];
|
||||
int index = 0;
|
||||
for(int i = 0; i < values.length; i++){
|
||||
if(values[i] != 0){
|
||||
result[index ++] = new ItemStack(Vars.content.item(i), values[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void min(int number){
|
||||
for(Item item : Vars.content.items()){
|
||||
set(item, Math.min(get(item), number));
|
||||
@@ -90,6 +105,12 @@ public class ItemSeq implements Iterable<ItemStack>, JsonSerializable{
|
||||
itemModule.each(this::add);
|
||||
}
|
||||
|
||||
public void add(ItemStack[] stacks){
|
||||
for(var s : stacks){
|
||||
add(s);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(ItemSeq seq){
|
||||
seq.each(this::add);
|
||||
}
|
||||
|
||||
@@ -127,7 +127,9 @@ public class UnitType extends UnlockableContent{
|
||||
softShadowRegion, jointRegion, footRegion, legBaseRegion, baseJointRegion, outlineRegion;
|
||||
public TextureRegion[] wreckRegions;
|
||||
|
||||
protected float maxBuildTime = -1f;
|
||||
protected @Nullable ItemStack[] cachedRequirements;
|
||||
protected @Nullable ItemStack[] totalRequirements;
|
||||
|
||||
public UnitType(String name){
|
||||
super(name);
|
||||
@@ -460,25 +462,70 @@ public class UnitType extends UnlockableContent{
|
||||
}
|
||||
}
|
||||
|
||||
/** @return the time required to build this unit, as a maximum value that takes into account reconstructors */
|
||||
public float getBuildTime(){
|
||||
getTotalRequirements();
|
||||
return maxBuildTime;
|
||||
}
|
||||
|
||||
/** @return all items needed to build this unit, including reconstructor steps. */
|
||||
public ItemStack[] getTotalRequirements(){
|
||||
if(totalRequirements == null){
|
||||
UnitType[] ret = {null};
|
||||
float[] timeret = {0f};
|
||||
ItemStack[] result = getRequirements(ret, timeret);
|
||||
|
||||
//prevents stack overflow if requirements are circular and result != null
|
||||
totalRequirements = ItemStack.empty;
|
||||
|
||||
if(result != null){
|
||||
maxBuildTime = timeret[0];
|
||||
ItemSeq total = new ItemSeq();
|
||||
|
||||
total.add(result);
|
||||
if(ret[0] != null){
|
||||
total.add(ret[0].getTotalRequirements());
|
||||
maxBuildTime = Math.max(ret[0].maxBuildTime, maxBuildTime);
|
||||
}
|
||||
totalRequirements = total.toArray();
|
||||
}
|
||||
}
|
||||
return totalRequirements;
|
||||
}
|
||||
|
||||
/** @return item requirements based on reconstructors or factories found; returns previous unit in array if provided */
|
||||
public @Nullable ItemStack[] getRequirements(@Nullable UnitType[] prevReturn, @Nullable float[] timeReturn){
|
||||
var rec = (Reconstructor)content.blocks().find(b -> b instanceof Reconstructor re && re.upgrades.contains(u -> u[1] == this));
|
||||
|
||||
if(rec != null && rec.consumes.has(ConsumeType.item) && rec.consumes.get(ConsumeType.item) instanceof ConsumeItems ci){
|
||||
if(prevReturn != null){
|
||||
prevReturn[0] = rec.upgrades.find(u -> u[1] == this)[0];
|
||||
}
|
||||
if(timeReturn != null){
|
||||
timeReturn[0] = rec.constructTime;
|
||||
}
|
||||
return ci.items;
|
||||
}else{
|
||||
var factory = (UnitFactory)content.blocks().find(u -> u instanceof UnitFactory uf && uf.plans.contains(p -> p.unit == this));
|
||||
if(factory != null){
|
||||
|
||||
var plan = factory.plans.find(p -> p.unit == this);
|
||||
if(timeReturn != null){
|
||||
timeReturn[0] = plan.time;
|
||||
}
|
||||
return plan.requirements;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack[] researchRequirements(){
|
||||
if(cachedRequirements != null){
|
||||
return cachedRequirements;
|
||||
}
|
||||
|
||||
ItemStack[] stacks = null;
|
||||
|
||||
//calculate costs based on reconstructors or factories found
|
||||
Block rec = content.blocks().find(b -> b instanceof Reconstructor re && re.upgrades.contains(u -> u[1] == this));
|
||||
|
||||
if(rec != null && rec.consumes.has(ConsumeType.item) && rec.consumes.get(ConsumeType.item) instanceof ConsumeItems ci){
|
||||
stacks = ci.items;
|
||||
}else{
|
||||
UnitFactory factory = (UnitFactory)content.blocks().find(u -> u instanceof UnitFactory uf && uf.plans.contains(p -> p.unit == this));
|
||||
if(factory != null){
|
||||
stacks = factory.plans.find(p -> p.unit == this).requirements;
|
||||
}
|
||||
}
|
||||
ItemStack[] stacks = getRequirements(null, null);
|
||||
|
||||
if(stacks != null){
|
||||
ItemStack[] out = new ItemStack[stacks.length];
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -6,6 +6,7 @@ import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
@@ -25,6 +26,12 @@ public interface Payload extends Position{
|
||||
float x();
|
||||
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;
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
package mindustry.world.blocks.payloads;
|
||||
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
public class PayloadDeconstructor extends PayloadBlock{
|
||||
public float deconstructSpeed = 2f;
|
||||
|
||||
public PayloadDeconstructor(String name){
|
||||
super(name);
|
||||
|
||||
outputsPayload = false;
|
||||
acceptsPayload = true;
|
||||
update = true;
|
||||
rotate = false;
|
||||
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};
|
||||
}
|
||||
|
||||
public class PayloadDeconstructorBuild extends PayloadBlockBuild<Payload>{
|
||||
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.draw();
|
||||
|
||||
//TODO shadow
|
||||
Draw.draw(Layer.blockOver, () -> {
|
||||
Drawf.construct(x, y, deconstructing.icon(), Pal.remove, 0f, 1f - progress, speedScl, time);
|
||||
Draw.color(Pal.remove);
|
||||
Draw.alpha(speedScl);
|
||||
|
||||
Lines.lineAngleCenter(x + Mathf.sin(time, 20f, Vars.tilesize / 2f * block.size - 2f), y, 90, block.size * Vars.tilesize - 4f);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
//always dump items
|
||||
dumpAccumulate();
|
||||
|
||||
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){
|
||||
//TODO
|
||||
deconstructing = null;
|
||||
accum = null;
|
||||
}
|
||||
}else if(moveInPayload(false) && payload != null && cons.valid()){
|
||||
accum = new float[payload.requirements().length];
|
||||
deconstructing = payload;
|
||||
payload = null;
|
||||
progress = 0f;
|
||||
}
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import mindustry.entities.EntityCollisions.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
|
||||
public class UnitPayload implements Payload{
|
||||
public static final float deactiveDuration = 40f;
|
||||
@@ -23,6 +24,16 @@ public class UnitPayload implements Payload{
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
@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);
|
||||
|
||||
Reference in New Issue
Block a user