diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index 8e021d53d7..926f033fc9 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.entities.traits; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Queue; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.blocks.Blocks; @@ -29,9 +30,7 @@ import io.anuke.ucore.graphics.Fill; import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Shapes; import io.anuke.ucore.util.Angles; -import io.anuke.ucore.util.Geometry; import io.anuke.ucore.util.Mathf; -import io.anuke.ucore.util.Translator; import java.io.DataInput; import java.io.DataOutput; @@ -47,6 +46,7 @@ public interface BuilderTrait extends Entity{ //these are not instance variables! float placeDistance = 150f; float mineDistance = 70f; + Array removal = new Array<>(); /**Returns the queue for storing build requests.*/ Queue getPlaceQueue(); @@ -171,6 +171,19 @@ public interface BuilderTrait extends Entity{ * This includes mining. */ default void updateBuilding(Unit unit){ + //remove already completed build requests + removal.clear(); + for(BuildRequest request : getPlaceQueue()){ + if((request.breaking && world.tile(request.x, request.y).block() == Blocks.air) || + (!request.breaking && world.tile(request.x, request.y).block() == request.recipe.result)){ + removal.add(request); + } + } + + for(BuildRequest req : removal){ + getPlaceQueue().removeValue(req, true); + } + BuildRequest current = getCurrentRequest(); //update mining here @@ -373,5 +386,18 @@ public interface BuilderTrait extends Entity{ this.recipe = Recipe.getByResult(world.tile(x, y).block()); this.breaking = true; } + + @Override + public String toString(){ + return "BuildRequest{" + + "x=" + x + + ", y=" + y + + ", rotation=" + rotation + + ", recipe=" + recipe + + ", breaking=" + breaking + + ", progress=" + progress + + ", initialized=" + initialized + + '}'; + } } } diff --git a/core/src/io/anuke/mindustry/entities/units/types/Drone.java b/core/src/io/anuke/mindustry/entities/units/types/Drone.java index b0adfeb4d5..b47215d4ea 100644 --- a/core/src/io/anuke/mindustry/entities/units/types/Drone.java +++ b/core/src/io/anuke/mindustry/entities/units/types/Drone.java @@ -352,7 +352,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{ @Override public boolean canCreateBlocks(){ - return false; + return true; } @Override diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index c6706a43a7..c13fe96662 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -14,7 +14,7 @@ import java.util.zip.InflaterInputStream; import static io.anuke.mindustry.Vars.*; public class SaveIO{ - public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58); + public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 63); public static final IntMap versions = new IntMap<>(); public static final Array versionArray = Array.with( new Save16() diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index 6ffab178db..991f747387 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -45,9 +45,9 @@ public class Build{ for(int dx = 0; dx < previous.size; dx++){ for(int dy = 0; dy < previous.size; dy++){ - int worldx = dx + offsetx + x; - int worldy = dy + offsety + y; - if(!(worldx == x && worldy == y)){ + int worldx = dx + offsetx + tile.x; + int worldy = dy + offsety + tile.y; + if(!(worldx == tile.x && worldy == tile.y)){ Tile toplace = world.tile(worldx, worldy); if(toplace != null){ toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety)); diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index 9845480b31..b690f63880 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -5,21 +5,22 @@ import com.badlogic.gdx.math.GridPoint2; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Items; import io.anuke.mindustry.content.UnitTypes; -import io.anuke.mindustry.content.blocks.Blocks; -import io.anuke.mindustry.content.blocks.CraftingBlocks; -import io.anuke.mindustry.content.blocks.PowerBlocks; -import io.anuke.mindustry.content.blocks.StorageBlocks; +import io.anuke.mindustry.content.blocks.*; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.Logic; import io.anuke.mindustry.core.NetServer; import io.anuke.mindustry.core.World; +import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.entities.units.BaseUnit; +import io.anuke.mindustry.entities.units.types.Spirit; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.io.BundleLoader; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.maps.Map; +import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Recipe; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Edges; import io.anuke.mindustry.world.Tile; @@ -229,6 +230,70 @@ public class ApplicationTests{ assertEquals(8, edges2.length); } + @Test + void buildingOverlap(){ + initBuilding(); + + Spirit d1 = (Spirit) UnitTypes.spirit.create(Team.blue); + Spirit d2 = (Spirit) UnitTypes.spirit.create(Team.blue); + + d1.set(10f, 20f); + d2.set(10f, 20f); + + d1.addBuildRequest(new BuildRequest(0, 0, 0, Recipe.getByResult(DefenseBlocks.copperWallLarge))); + d2.addBuildRequest(new BuildRequest(1, 1, 0, Recipe.getByResult(DefenseBlocks.copperWallLarge))); + + Timers.setDeltaProvider(() -> 9999999f); + d1.updateBuilding(d1); + d2.updateBuilding(d2); + + assertEquals(DefenseBlocks.copperWallLarge, world.tile(0, 0).block()); + assertEquals(Blocks.air, world.tile(2, 2).block()); + assertEquals(Blocks.blockpart, world.tile(1, 1).block()); + } + + @Test + void buildingDestruction(){ + initBuilding(); + + Spirit d1 = (Spirit) UnitTypes.spirit.create(Team.blue); + Spirit d2 = (Spirit) UnitTypes.spirit.create(Team.blue); + + d1.set(10f, 20f); + d2.set(10f, 20f); + + d1.addBuildRequest(new BuildRequest(0, 0, 0, Recipe.getByResult(DefenseBlocks.copperWallLarge))); + d2.addBuildRequest(new BuildRequest(1, 1)); + + Timers.setDeltaProvider(() -> 3f); + d1.updateBuilding(d1); + Timers.setDeltaProvider(() -> 1f); + d2.updateBuilding(d2); + + assertEquals(content.getByName(ContentType.block, "build2"), world.tile(0, 0).block()); + + Timers.setDeltaProvider(() -> 9999f); + + d1.updateBuilding(d1); + d2.updateBuilding(d2); + + assertEquals(Blocks.air, world.tile(0, 0).block()); + assertEquals(Blocks.air, world.tile(2, 2).block()); + assertEquals(Blocks.air, world.tile(1, 1).block()); + } + + void initBuilding(){ + createMap(); + + Tile core = world.tile(5, 5); + world.setBlock(core, StorageBlocks.core, Team.blue); + for(Item item : content.items()){ + core.entity.items.set(item, 3000); + } + + assertEquals(core, state.teams.get(Team.blue).cores.first()); + } + void depositTest(Block block, Item item){ BaseUnit unit = UnitTypes.alphaDrone.create(Team.none); Tile tile = new Tile(0, 0, Blocks.air.id, block.id);