From 1d68f99c75e12d83597fc2c51117b4a5096564f7 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 30 Oct 2024 19:17:36 -0400 Subject: [PATCH] Fixed plans being canceled by blocked units --- core/src/mindustry/content/Blocks.java | 2 +- .../mindustry/entities/comp/BuilderComp.java | 27 +++++++++++------- core/src/mindustry/input/InputHandler.java | 28 +++++++++++-------- core/src/mindustry/input/MobileInput.java | 2 +- core/src/mindustry/world/Build.java | 18 ++++++++---- 5 files changed, 48 insertions(+), 29 deletions(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 282fd46a1c..0da58ff1f1 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -977,7 +977,7 @@ public class Blocks{ consumeItems(with(Items.thorium, 4, Items.sand, 10)); consumePower(5f); - itemCapacity = 20; + itemCapacity = 30; }}; surgeSmelter = new GenericCrafter("surge-smelter"){{ diff --git a/core/src/mindustry/entities/comp/BuilderComp.java b/core/src/mindustry/entities/comp/BuilderComp.java index 4544d055a0..a81d0644fa 100644 --- a/core/src/mindustry/entities/comp/BuilderComp.java +++ b/core/src/mindustry/entities/comp/BuilderComp.java @@ -63,7 +63,7 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{ Tile tile = world.tile(plan.x, plan.y); boolean isSameDerelict = (tile != null && tile.build != null && tile.block() == plan.block && tile.build.tileX() == plan.x && tile.build.tileY() == plan.y && tile.team() == Team.derelict); if(tile == null || (plan.breaking && tile.block() == Blocks.air) || (!plan.breaking && ((tile.build != null && tile.build.rotation == plan.rotation && !isSameDerelict) || !plan.block.rotate) && - //th block must be the same, but not derelict and the same + //the block must be the same, but not derelict and the same ((tile.block() == plan.block && !isSameDerelict) || //same floor or overlay (plan.block != null && (plan.block.isOverlay() && plan.block == tile.overlay() || (plan.block.isFloor() && plan.block == tile.floor())))))){ @@ -137,24 +137,31 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{ } if(!(tile.build instanceof ConstructBuild cb)){ - if(!current.initialized && !current.breaking && Build.validPlace(current.block, team, current.x, current.y, current.rotation)){ - boolean hasAll = infinite || current.isRotation(team) || + if(!current.initialized && !current.breaking && Build.validPlace(current.block, team, current.x, current.y, current.rotation, true)){ + if(Build.checkNoUnitOverlap(current.block, current.x, current.y)){ + boolean hasAll = infinite || current.isRotation(team) || //derelict repair (tile.team() == Team.derelict && tile.block() == current.block && tile.build != null && tile.block().allowDerelictRepair && state.rules.derelictRepair) || //make sure there's at least 1 item of each type first !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item, Math.min(Mathf.round(i.amount * state.rules.buildCostMultiplier), 1))); - if(hasAll){ - Call.beginPlace(self(), current.block, team, current.x, current.y, current.rotation); + if(hasAll){ + Call.beginPlace(self(), current.block, team, current.x, current.y, current.rotation); - if(current.block.instantBuild){ - if(plans.size > 0){ - plans.removeFirst(); + if(current.block.instantBuild){ + if(plans.size > 0){ + plans.removeFirst(); + } + continue; } - continue; + }else{ + current.stuck = true; } }else{ - current.stuck = true; + //there's a unit blocking the plan, skip it + plans.removeFirst(); + plans.addLast(current); + continue; } }else if(!current.initialized && current.breaking && Build.validBreak(team, current.x, current.y)){ Call.beginBreak(self(), team, current.x, current.y); diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 9c1a90919e..777511401d 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -827,15 +827,18 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } if(player.isBuilder()){ - if(player.unit() != lastUnit && player.unit().plans.size <= 1){ - player.unit().plans.ensureCapacity(lastPlans.size); + var playerPlans = player.unit().plans; + if(player.unit() != lastUnit && playerPlans.size <= 1){ + playerPlans.ensureCapacity(lastPlans.size); for(var plan : lastPlans){ - player.unit().plans.addLast(plan); + playerPlans.addLast(plan); } } - lastPlans.clear(); - for(var plan : player.unit().plans){ - lastPlans.addLast(plan); + if(lastPlans.size != playerPlans.size || (lastPlans.size > 0 && playerPlans.size > 0 && lastPlans.first() != playerPlans.first())){ + lastPlans.clear(); + for(var plan : playerPlans){ + lastPlans.addLast(plan); + } } } @@ -1465,7 +1468,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ protected void flushSelectPlans(Seq plans){ for(BuildPlan plan : plans){ - if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation)){ + if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation, null, true)){ BuildPlan other = getPlan(plan.x, plan.y, plan.block.size, null); if(other == null){ selectPlans.add(plan.copy()); @@ -1481,7 +1484,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ //reversed iteration. for(int i = plans.size - 1; i >= 0; i--){ var plan = plans.get(i); - if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation)){ + if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation, null, true)){ BuildPlan copy = plan.copy(); plan.block.onNewPlan(copy); player.unit().addBuild(copy, false); @@ -1491,7 +1494,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ protected void flushPlans(Seq plans){ for(var plan : plans){ - if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation)){ + if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation, null, true)){ BuildPlan copy = plan.copy(); plan.block.onNewPlan(copy); player.unit().addBuild(copy); @@ -1988,8 +1991,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public boolean validPlace(int x, int y, Block type, int rotation){ return validPlace(x, y, type, rotation, null); } + public boolean validPlace(int x, int y, Block type, int rotation, @Nullable BuildPlan ignore){ + return validPlace(x, y, type, rotation, ignore, false); + } - public boolean validPlace(int x, int y, Block type, int rotation, BuildPlan ignore){ + public boolean validPlace(int x, int y, Block type, int rotation, @Nullable BuildPlan ignore, boolean ignoreUnits){ if(player.unit().plans.size > 0){ Tmp.r1.setCentered(x * tilesize + type.offset, y * tilesize + type.offset, type.size * tilesize); plansOut.clear(); @@ -2006,7 +2012,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } } - return Build.validPlace(type, player.team(), x, y, rotation); + return ignoreUnits ? Build.validPlaceIgnoreUnits(type, player.team(), x, y, rotation, true) : Build.validPlace(type, player.team(), x, y, rotation); } public boolean validBreak(int x, int y){ diff --git a/core/src/mindustry/input/MobileInput.java b/core/src/mindustry/input/MobileInput.java index 24a74521fd..37ec6c9ec9 100644 --- a/core/src/mindustry/input/MobileInput.java +++ b/core/src/mindustry/input/MobileInput.java @@ -234,7 +234,7 @@ public class MobileInput extends InputHandler implements GestureListener{ //actually place/break all selected blocks if(tile != null){ if(!plan.breaking){ - if(validPlace(plan.x, plan.y, plan.block, plan.rotation)){ + if(validPlace(plan.x, plan.y, plan.block, plan.rotation, null, true)){ BuildPlan other = getPlan(plan.x, plan.y, plan.block.size, null); BuildPlan copy = plan.copy(); diff --git a/core/src/mindustry/world/Build.java b/core/src/mindustry/world/Build.java index 5388ea9789..777d2a8be6 100644 --- a/core/src/mindustry/world/Build.java +++ b/core/src/mindustry/world/Build.java @@ -157,22 +157,28 @@ public class Build{ result.placeBegan(tile, previous, unit); } - /** Returns whether a tile can be placed at this location by this team. */ + /** @return whether a tile can be placed at this location by this team. */ public static boolean validPlace(Block type, Team team, int x, int y, int rotation){ return validPlace(type, team, x, y, rotation, true); } - /** Returns whether a tile can be placed at this location by this team. */ + /** @return whether a tile can be placed at this location by this team. */ public static boolean validPlace(Block type, Team team, int x, int y, int rotation, boolean checkVisible){ + return validPlaceIgnoreUnits(type, team, x, y, rotation, checkVisible) && checkNoUnitOverlap(type, x, y); + } + + /** @return whether a tile can be placed at this location by this team. */ + public static boolean checkNoUnitOverlap(Block type, int x, int y){ + return (!type.solid && !type.solidifes) || !Units.anyEntities(x * tilesize + type.offset - type.size * tilesize / 2f, y * tilesize + type.offset - type.size * tilesize / 2f, type.size * tilesize, type.size * tilesize); + } + + /** Returns whether a tile can be placed at this location by this team. Ignores units at this location. */ + public static boolean validPlaceIgnoreUnits(Block type, Team team, int x, int y, int rotation, boolean checkVisible){ //the wave team can build whatever they want as long as it's visible - banned blocks are not applicable if(type == null || (!state.rules.editor && (checkVisible && (!type.environmentBuildable() || (!type.isPlaceable() && !(state.rules.waves && team == state.rules.waveTeam && type.isVisible())))))){ return false; } - if((type.solid || type.solidifes) && Units.anyEntities(x * tilesize + type.offset - type.size*tilesize/2f, y * tilesize + type.offset - type.size*tilesize/2f, type.size * tilesize, type.size*tilesize)){ - return false; - } - if(!state.rules.editor){ //find closest core, if it doesn't match the team, placing is not legal if(state.rules.polygonCoreProtection){