diff --git a/core/src/mindustry/world/blocks/ConstructBlock.java b/core/src/mindustry/world/blocks/ConstructBlock.java index df7434a222..15553854a9 100644 --- a/core/src/mindustry/world/blocks/ConstructBlock.java +++ b/core/src/mindustry/world/blocks/ConstructBlock.java @@ -166,6 +166,7 @@ public class ConstructBlock extends Block{ private float[] accumulator; private float[] totalAccumulator; + private int[] itemsLeft; @Override public String getDisplayName(){ @@ -270,7 +271,7 @@ public class ConstructBlock extends Block{ for(int i = 0; i < current.requirements.length; i++){ int reqamount = Math.round(state.rules.buildCostMultiplier * current.requirements[i].amount); - accumulator[i] += Math.min(reqamount * maxProgress, reqamount - totalAccumulator[i] + 0.00001f); //add min amount progressed to the accumulator + accumulator[i] += Math.min(reqamount * maxProgress, reqamount - totalAccumulator[i]); //add min amount progressed to the accumulator totalAccumulator[i] = Math.min(totalAccumulator[i] + reqamount * maxProgress, reqamount); } @@ -279,9 +280,28 @@ public class ConstructBlock extends Block{ progress = Mathf.clamp(progress + maxProgress); if(progress >= 1f || state.rules.infiniteResources){ - if(lastBuilder == null) lastBuilder = builder; - if(!net.client()){ - constructed(tile, current, lastBuilder, (byte)rotation, builder.team, config); + boolean canFinish = true; + + //look at leftover resources to consume, get them from the core if necessary, delay building if not + if(!state.rules.infiniteResources){ + for(int i = 0; i < itemsLeft.length; i++){ + if(itemsLeft[i] > 0){ + if(core != null && core.items.has(current.requirements[i].item, itemsLeft[i])){ + core.items.remove(current.requirements[i].item, itemsLeft[i]); + itemsLeft[i] = 0; + }else{ + canFinish = false; + break; + } + } + } + } + + if(canFinish){ + if(lastBuilder == null) lastBuilder = builder; + if(!net.client()){ + constructed(tile, current, lastBuilder, (byte)rotation, builder.team, config); + } } } } @@ -321,6 +341,7 @@ public class ConstructBlock extends Block{ int accepting = Math.min(accumulated, core.storageCapacity - core.items.get(requirements[i].item)); //transfer items directly, as this is not production. core.items.add(requirements[i].item, accepting); + itemsLeft[i] -= accepting; accumulator[i] -= accepting; }else{ accumulator[i] -= accumulated; @@ -331,6 +352,14 @@ public class ConstructBlock extends Block{ progress = Mathf.clamp(progress - amount); if(progress <= current.deconstructThreshold || state.rules.infiniteResources){ + //add any leftover items that weren't obtained due to rounding errors + if(core != null){ + for(int i = 0; i < itemsLeft.length; i++){ + core.items.add(current.requirements[i].item, Mathf.clamp(itemsLeft[i], 0, core.storageCapacity - core.items.get(current.requirements[i].item))); + itemsLeft[i] = 0; + } + } + if(lastBuilder == null) lastBuilder = builder; Call.deconstructFinish(tile, this.current, lastBuilder); } @@ -341,6 +370,11 @@ public class ConstructBlock extends Block{ boolean infinite = team.rules().infiniteResources || state.rules.infiniteResources; for(int i = 0; i < current.requirements.length; i++){ + //there is no need to remove items that have already been fully taken out + if(itemsLeft[i] == 0){ + continue; + } + int sclamount = Math.round(state.rules.buildCostMultiplier * current.requirements[i].amount); int required = (int)(accumulator[i]); //calculate items that are required now @@ -360,6 +394,7 @@ public class ConstructBlock extends Block{ //remove stuff that is actually used if(remove && !infinite){ inventory.remove(current.requirements[i].item, maxUse); + itemsLeft[i] -= maxUse; } } //else, no items are required yet, so just keep going @@ -368,6 +403,7 @@ public class ConstructBlock extends Block{ return maxProgress; } + @Override public float progress(){ return progress; } @@ -380,8 +416,14 @@ public class ConstructBlock extends Block{ this.current = block; this.previous = previous; this.buildCost = block.buildCost * state.rules.buildCostMultiplier; + this.itemsLeft = new int[block.requirements.length]; this.accumulator = new float[block.requirements.length]; this.totalAccumulator = new float[block.requirements.length]; + + ItemStack[] requirements = current.requirements; + for(int i = 0; i < requirements.length; i++){ + this.itemsLeft[i] = Mathf.round(requirements[i].amount * state.rules.buildCostMultiplier); + } pathfinder.updateTile(tile); } @@ -394,8 +436,14 @@ public class ConstructBlock extends Block{ this.progress = 1f; this.current = previous; this.buildCost = previous.buildCost * state.rules.buildCostMultiplier; + this.itemsLeft = new int[previous.requirements.length]; this.accumulator = new float[previous.requirements.length]; this.totalAccumulator = new float[previous.requirements.length]; + + ItemStack[] requirements = current.requirements; + for(int i = 0; i < requirements.length; i++){ + this.itemsLeft[i] = Mathf.round(requirements[i].amount * state.rules.buildCostMultiplier * state.rules.deconstructRefundMultiplier); + } pathfinder.updateTile(tile); }