diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index dbf2c9c30c..53c61daca8 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -354,6 +354,7 @@ command.rebuild = Rebuild command.assist = Assist Player command.move = Move command.boost = Boost +command.enterPayload = Enter Payload Block command.loadUnits = Load Units command.loadBlocks = Load Blocks command.unloadPayload = Unload Payload diff --git a/core/src/mindustry/ai/UnitCommand.java b/core/src/mindustry/ai/UnitCommand.java index b84036b493..ef5f382cd0 100644 --- a/core/src/mindustry/ai/UnitCommand.java +++ b/core/src/mindustry/ai/UnitCommand.java @@ -17,7 +17,7 @@ public class UnitCommand extends MappableContent{ @Deprecated public static final Seq all = new Seq<>(); - public static UnitCommand moveCommand, repairCommand, rebuildCommand, assistCommand, mineCommand, boostCommand, loadUnitsCommand, loadBlocksCommand, unloadPayloadCommand; + public static UnitCommand moveCommand, repairCommand, rebuildCommand, assistCommand, mineCommand, boostCommand, enterPayloadCommand, loadUnitsCommand, loadBlocksCommand, unloadPayloadCommand; /** Name of UI icon (from Icon class). */ public final String icon; @@ -87,6 +87,11 @@ public class UnitCommand extends MappableContent{ drawTarget = true; resetTarget = false; }}; + enterPayloadCommand = new UnitCommand("enterPayload", "downOpen", Binding.unit_command_enter_payload, null){{ + switchToMove = false; + drawTarget = true; + resetTarget = false; + }}; loadUnitsCommand = new UnitCommand("loadUnits", "upload", Binding.unit_command_load_units, null){{ switchToMove = false; drawTarget = true; diff --git a/core/src/mindustry/ai/types/CommandAI.java b/core/src/mindustry/ai/types/CommandAI.java index bbf83b6e1f..84475dc23b 100644 --- a/core/src/mindustry/ai/types/CommandAI.java +++ b/core/src/mindustry/ai/types/CommandAI.java @@ -20,6 +20,7 @@ public class CommandAI extends AIController{ protected static final int maxCommandQueueSize = 50, avoidInterval = 10; protected static final Vec2 vecOut = new Vec2(), vecMovePos = new Vec2(); protected static final boolean[] noFound = {false}; + protected static final UnitPayload tmpPayload = new UnitPayload(null); public Seq commandQueue = new Seq<>(5); public @Nullable Vec2 targetPos; @@ -145,6 +146,15 @@ public class CommandAI extends AIController{ } } + if(!net.client() && command == UnitCommand.enterPayloadCommand && unit.buildOn() != null && (targetPos == null || (world.buildWorld(targetPos.x, targetPos.y) != null && world.buildWorld(targetPos.x, targetPos.y) == unit.buildOn()))){ + var build = unit.buildOn(); + tmpPayload.unit = unit; + if(build.team == unit.team && build.acceptPayload(build, tmpPayload)){ + Call.unitEnteredPayload(unit, build); + return; //no use updating after this, the unit is gone! + } + } + //acquiring naval targets isn't supported yet, so use the fallback dumb AI if(unit.team.isAI() && unit.team.rules().rtsAi && unit.type.naval){ if(fallback == null) fallback = new GroundAI(); @@ -198,7 +208,8 @@ public class CommandAI extends AIController{ vecOut.set(targetPos); vecMovePos.set(targetPos); - if(group != null && group.valid && groupIndex < group.units.size){ + //the enter payload command requires an exact position + if(group != null && group.valid && groupIndex < group.units.size && command != UnitCommand.enterPayloadCommand){ vecMovePos.add(group.positions[groupIndex * 2], group.positions[groupIndex * 2 + 1]); } @@ -295,6 +306,11 @@ public class CommandAI extends AIController{ } void finishPath(){ + //the enter payload command never finishes until they are actually accepted + if(command == UnitCommand.enterPayloadCommand && commandQueue.size == 0 && targetPos != null && world.buildWorld(targetPos.x, targetPos.y) != null && world.buildWorld(targetPos.x, targetPos.y).block.acceptsPayloads){ + return; + } + Vec2 prev = targetPos; targetPos = null; diff --git a/core/src/mindustry/input/Binding.java b/core/src/mindustry/input/Binding.java index 8cda01e789..039829ebd4 100644 --- a/core/src/mindustry/input/Binding.java +++ b/core/src/mindustry/input/Binding.java @@ -56,6 +56,7 @@ public enum Binding implements KeyBind{ unit_command_assist(KeyCode.unset), unit_command_mine(KeyCode.unset), unit_command_boost(KeyCode.unset), + unit_command_enter_payload(KeyCode.unset), unit_command_load_units(KeyCode.unset), unit_command_load_blocks(KeyCode.unset), unit_command_unload_payload(KeyCode.unset), diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 912b65e0ef..af04caa5c0 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -557,6 +557,31 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } } + @Remote(called = Loc.server) + public static void unitEnteredPayload(Unit unit, Building build){ + if(unit == null || build == null || unit.team != build.team) return; + + unit.remove(); + + //reset the enter command + if(unit.controller() instanceof CommandAI ai && ai.command == UnitCommand.enterPayloadCommand){ + ai.clearCommands(); + ai.command = UnitCommand.moveCommand; + } + + //clear removed state of unit so it can be synced + if(Vars.net.client()){ + Vars.netClient.clearRemovedEntity(unit.id); + } + + UnitPayload unitPay = new UnitPayload(unit); + + if(build.acceptPayload(build, unitPay)){ + Fx.unitDrop.at(build); + build.handlePayload(build, unitPay); + } + } + @Remote(targets = Loc.client, called = Loc.server) public static void dropItem(Player player, float angle){ if(player == null) return; diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 337bdbcb5f..44a39d9350 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -810,7 +810,7 @@ public class UnitType extends UnlockableContent implements Senseable{ if(commands.length == 0){ Seq cmds = new Seq<>(UnitCommand.class); - cmds.add(UnitCommand.moveCommand); + cmds.add(UnitCommand.moveCommand, UnitCommand.enterPayloadCommand); if(canBoost){ cmds.add(UnitCommand.boostCommand); diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index c1a87f510c..d1efde7d1d 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -57,6 +57,8 @@ public class Block extends UnlockableContent implements Senseable{ public boolean conductivePower = false; /** If true, this block can output payloads; affects blending. */ public boolean outputsPayload = false; + /** If true, this block can input payloads; affects unit payload enter behavior. */ + public boolean acceptsPayloads = false; /** If true, payloads will attempt to move into this block. */ public boolean acceptsPayload = false; /** Visual flag use for blending of certain transportation blocks. */ diff --git a/core/src/mindustry/world/blocks/payloads/BlockProducer.java b/core/src/mindustry/world/blocks/payloads/BlockProducer.java index fbedeb49b6..e5eccb570f 100644 --- a/core/src/mindustry/world/blocks/payloads/BlockProducer.java +++ b/core/src/mindustry/world/blocks/payloads/BlockProducer.java @@ -30,6 +30,7 @@ public abstract class BlockProducer extends PayloadBlock{ hasItems = true; solid = true; hasPower = true; + acceptsPayloads = false; rotate = true; regionRotated1 = 1; diff --git a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java index 3edb189a0f..1ecd627dc3 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java @@ -25,6 +25,7 @@ public class PayloadBlock extends Block{ update = true; sync = true; group = BlockGroup.payloads; + acceptsPayloads = true; envEnabled |= Env.space | Env.underwater; } diff --git a/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java b/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java index 94a0de3071..6fedce44a3 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadConveyor.java @@ -30,6 +30,7 @@ public class PayloadConveyor extends Block{ update = true; outputsPayload = true; noUpdateDisabled = true; + acceptsPayloads = true; priority = TargetPriority.transport; envEnabled |= Env.space | Env.underwater; sync = true; diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java index 8e90508e61..1354b9edc1 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java @@ -37,6 +37,7 @@ public class PayloadSource extends PayloadBlock{ noUpdateDisabled = true; clearOnDoubleTap = true; regionRotated1 = 1; + acceptsPayloads = false; commandable = true; config(Block.class, (PayloadSourceBuild build, Block block) -> {