Merge branch 'no-payload-conveyor-for-payenter' of https://github.com/EggleEgg/Mindustry into EggleEgg-no-payload-conveyor-for-payenter

This commit is contained in:
Anuken
2026-08-31 20:25:54 -04:00
12 changed files with 102 additions and 40 deletions
+1 -1
View File
@@ -1312,7 +1312,7 @@ bar.nevermelts = never melts
bar.heatamount = Heat: {0}
bar.heatpercent = Heat: {0} ({1}%)
bar.power = Power
bar.progress = Build Progress
bar.progress = Progress: {0}%
bar.loadprogress = Progress
bar.launchcooldown = Launch Cooldown
bar.input = Input
+27 -14
View File
@@ -17,12 +17,13 @@ import static mindustry.Vars.*;
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 Vec2 vecOut = new Vec2(), vecMovePos = new Vec2(), movePos = new Vec2();
protected static final UnitPayload tmpPayload = new UnitPayload(null);
protected static final int transferStateNone = 0, transferStateLoad = 1, transferStateUnload = 2;
public Seq<Position> commandQueue = new Seq<>(5);
public @Nullable Vec2 targetPos;
public @Nullable Building targetBuild;
public @Nullable Teamc attackTarget;
/** Group of units that were all commanded to reach the same point. */
public @Nullable UnitGroup group;
@@ -227,14 +228,14 @@ public class CommandAI extends AIController{
}
}
if(!net.client() && command == UnitCommand.enterPayloadCommand && unit.type.allowedInPayloads && 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!
if(!net.client() && command == UnitCommand.enterPayloadCommand && unit.type.allowedInPayloads && (targetPos == null ? unit.buildOn() != null : targetBuild != null)){
var build = targetPos == null ? unit.buildOn() : targetBuild;
if(build.canControlSelect(unit)){
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!
}
}
}
@@ -275,8 +276,19 @@ public class CommandAI extends AIController{
if(targetPos != null){
boolean move = true, isFinalPoint = commandQueue.size == 0;
vecOut.set(targetPos);
vecMovePos.set(targetPos);
//workaround to let ground units pathfind into targeted solid payenter blocks
boolean isSolidPayload = false;
movePos.set(targetPos);
targetBuild = world.buildWorld(targetPos.x, targetPos.y);
if(unit.isGrounded() && targetBuild != null && targetBuild.tile.solid() && targetBuild.block.acceptsUnitPayloads && unit.type.pathCostId != ControlPathfinder.costIdLegs && !ramming){
Tile best = targetBuild.findClosestEdge(unit, Tile::solid);
if(best != null){
movePos.set(best);
isSolidPayload = true;
}
}
vecOut.set(movePos);
vecMovePos.set(movePos);
//the enter payload command requires an exact position
if(group != null && group.valid && groupIndex < group.units.size && command != UnitCommand.enterPayloadCommand){
@@ -287,7 +299,7 @@ public class CommandAI extends AIController{
if(
(hasStance(UnitStance.patrol) && !hasStance(UnitStance.pursueTarget) && target != null && unit.within(target, unit.type.range - 2f) && !unit.type.circleTarget) ||
(command == UnitCommand.enterPayloadCommand && unit.within(targetPos, 4f) || (targetBuild != null && !unit.type.circleTarget && unit.within(targetBuild, targetBuild.block.size * tilesize/2f * 0.9f))) ||
(command == UnitCommand.enterPayloadCommand && unit.within(movePos, 4f) || (targetBuild != null && !unit.type.circleTarget && unit.within(targetBuild, targetBuild.block.size * tilesize/2f * 0.9f))) ||
(command == UnitCommand.loopPayloadCommand && unit.within(vecMovePos, 10f))
){
move = false;
@@ -329,9 +341,10 @@ public class CommandAI extends AIController{
move = true;
vecOut.set(vecMovePos);
}else{
var result = controlPath.getPathPosition(unit, vecMovePos, targetPos);
var result = controlPath.getPathPosition(unit, movePos, isSolidPayload ? movePos : targetPos);
unreachable = result.unreachable;
if(!isSolidPayload)
unreachable = result.unreachable;
move &= result.move && (!blockingUnit || timeSpentBlocked > maxBlockTime);
if(result.move) vecOut.set(result.dest);
@@ -813,6 +813,10 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
}
public void handlePayload(Building source, Payload payload){
handlePayload(source, payload, null);
}
public void handlePayload(Building source, Payload payload, @Nullable Unit unit){
}
+1 -1
View File
@@ -669,7 +669,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
if(build.acceptPayload(build, unitPay)){
Fx.unitDrop.at(build);
build.handlePayload(build, unitPay);
build.handlePayload(build, unitPay, unit);
}
}
+3 -1
View File
@@ -59,7 +59,7 @@ 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. */
/** If true, this block can input payloads. Affects unit payload enter and pathfinding behaviors. */
public boolean acceptsUnitPayloads = false;
/** If true, payloads will attempt to move into this block. */
public boolean acceptsPayload = false;
@@ -114,6 +114,8 @@ public class Block extends UnlockableContent implements Senseable{
public boolean solidifes;
/** if true, this counts as a non-solid block to this team. */
public boolean teamPassable;
/** if true, units will attempt to pathfind to this block even if its tile is normally impassable. */
public boolean pathfindTarget = false;
/** if true, this block cannot be hit by bullets unless explicitly targeted. */
public boolean underBullets;
/** whether this is rotatable */
@@ -1,5 +1,6 @@
package mindustry.world.blocks.payloads;
import arc.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.struct.*;
@@ -71,7 +72,11 @@ public abstract class BlockProducer extends PayloadBlock{
public void setBars(){
super.setBars();
addBar("progress", (BlockProducerBuild entity) -> new Bar("bar.progress", Pal.ammo, () -> entity.recipe() == null ? 0f : (entity.progress / entity.recipe().buildTime)));
addBar("progress", (BlockProducerBuild e) -> new Bar(
() -> Core.bundle.format("bar.progress", Strings.autoFixed(e.fraction() * 100f, 0)),
() -> Pal.ammo,
e::fraction
));
}
public abstract class BlockProducerBuild extends PayloadBlockBuild<BuildPayload>{
@@ -79,6 +84,10 @@ public abstract class BlockProducer extends PayloadBlock{
public abstract @Nullable Block recipe();
public float fraction(){
return recipe() == null ? 0f : (progress / recipe().buildTime);
}
@Override
public boolean acceptItem(Building source, Item item){
return items.get(item) < getMaximumAccepted(item);
@@ -15,7 +15,7 @@ import mindustry.world.meta.*;
import static mindustry.Vars.*;
public class PayloadBlock extends Block{
public float payloadSpeed = 0.7f, payloadRotateSpeed = 5f;
public float payloadSpeed = 0.7f, payloadRotateSpeed = 3f;
public String regionSuffix = "";
public TextureRegion topRegion, outRegion, inRegion;
@@ -101,7 +101,8 @@ public class PayloadBlock extends Block{
@Override
public boolean canControlSelect(Unit unit){
return !unit.spawnedByCore && unit.type.allowedInPayloads && this.payload == null && acceptUnitPayload(unit) && unit.tileOn() != null && unit.tileOn().build == this;
return !unit.spawnedByCore && unit.type.allowedInPayloads && this.payload == null && acceptUnitPayload(unit) &&
(unit.isGrounded() && !unit.type.allowLegStep && solid) ? unit.within(this, size * tilesize * 0.7f + unit.hitSize / 2f) : unit.tileOn() != null && unit.tileOn().build == this;
}
@Override
@@ -117,10 +118,15 @@ public class PayloadBlock extends Block{
return this.payload == null;
}
@Override
public void handlePayload(Building source, Payload payload){
public void handlePayload(Building source, Payload payload, @Nullable Unit unit){
if(unit != null){
float clampPos = size * tilesize * 0.7f + unit.hitSize / 2f;
this.payVector.set(unit.x, unit.y).sub(this).clamp(-clampPos, -clampPos, clampPos, clampPos);
}else{
this.payVector.set(source).sub(this).clamp(-size * tilesize / 2f, -size * tilesize / 2f, size * tilesize / 2f, size * tilesize / 2f);
}
this.payload = (T)payload;
this.payVector.set(source).sub(this).clamp(-size * tilesize / 2f, -size * tilesize / 2f, size * tilesize / 2f, size * tilesize / 2f);
this.payRotation = payload.rotation();
updatePayload();
@@ -1,5 +1,6 @@
package mindustry.world.blocks.payloads;
import arc.*;
import arc.graphics.g2d.*;
import arc.math.*;
import arc.util.*;
@@ -45,7 +46,11 @@ public class PayloadDeconstructor extends PayloadBlock{
public void setBars(){
super.setBars();
addBar("progress", (PayloadDeconstructorBuild e) -> new Bar("bar.progress", Pal.ammo, () -> e.progress));
addBar("progress", (PayloadDeconstructorBuild e) -> new Bar(
() -> Core.bundle.format("bar.progress", Strings.autoFixed(e.progress * 100f, 0)),
() -> Pal.ammo,
() -> e.progress
));
}
public class PayloadDeconstructorBuild extends PayloadBlockBuild<Payload>{
@@ -146,6 +146,11 @@ public class PayloadMassDriver extends PayloadBlock{
return waitingShooters.isEmpty() ? null : waitingShooters.first();
}
@Override
public boolean acceptUnitPayload(Unit unit){
return unit != null && unit.hitSize <= maxPayloadSize * tilesize;
}
@Override
public float buildRotation(){
return rotation;
@@ -68,7 +68,12 @@ public class Reconstructor extends UnitBlock{
public void setBars(){
super.setBars();
addBar("progress", (ReconstructorBuild entity) -> new Bar("bar.progress", Pal.ammo, entity::fraction));
addBar("progress", (ReconstructorBuild e) -> new Bar(
() -> Core.bundle.format("bar.progress", Strings.autoFixed(e.fraction() * 100f, 0)),
() -> Pal.ammo,
e::fraction
));
addBar("units", (ReconstructorBuild e) ->
new Bar(
() -> e.unit() == null ? "[lightgray]" + Iconc.cancel :
@@ -177,6 +182,12 @@ public class Reconstructor extends UnitBlock{
@Override
public void onCommand(Vec2 target){
commandPos = target;
if(command != null && command.snapToBuilding){
var build = world.buildWorld(target.x, target.y);
if(build != null && build.team == this.team){
commandPos.set(build);
}
}
}
@Override
@@ -186,7 +197,7 @@ public class Reconstructor extends UnitBlock{
public boolean canSetCommand(){
var output = unit();
return output != null && output.commands.size > 1 && output.allowChangeCommands;
return output == null || output.allowChangeCommands;
}
@Override
@@ -203,25 +214,20 @@ public class Reconstructor extends UnitBlock{
public void buildConfiguration(Table table){
var unit = unit();
if(unit == null){
deselect();
return;
}
var group = new ButtonGroup<ImageButton>();
group.setMinCheckCount(0);
int i = 0, columns = 4;
int i = 0, columns = 5;
table.background(Styles.black6);
var list = unit().commands;
var list = unit == null ? Vars.content.unitCommands().copy() : unit().commands;
for(var item : list){
ImageButton button = table.button(item.getIcon(), Styles.clearNoneTogglei, 40f, () -> {
ImageButton button = table.button(item.getIcon(), Styles.clearNoneTogglei, 44f, () -> {
configure(item);
deselect();
}).tooltip(item.localized()).group(group).get();
button.update(() -> button.setChecked(command == item || (command == null && unit.defaultCommand == item)));
button.update(() -> button.setChecked(command == item || (command == null && unit != null && unit.defaultCommand == item)));
if(++i % columns == 0){
table.row();
@@ -125,7 +125,11 @@ public class UnitAssembler extends PayloadBlock{
removeBar("liquid");
}
addBar("progress", (UnitAssemblerBuild e) -> new Bar("bar.progress", Pal.ammo, () -> e.progress));
addBar("progress", (UnitAssemblerBuild e) -> new Bar(
() -> Core.bundle.format("bar.progress", Strings.autoFixed(e.progress * 100f, 0)),
() -> Pal.ammo,
() -> e.progress
));
addBar("units", (UnitAssemblerBuild e) ->
new Bar(() ->
@@ -118,7 +118,11 @@ public class UnitFactory extends UnitBlock{
@Override
public void setBars(){
super.setBars();
addBar("progress", (UnitFactoryBuild e) -> new Bar("bar.progress", Pal.ammo, e::fraction));
addBar("progress", (UnitFactoryBuild e) -> new Bar(
() -> Core.bundle.format("bar.progress", Strings.autoFixed(e.fraction() * 100f, 0)),
() -> Pal.ammo,
e::fraction
));
addBar("units", (UnitFactoryBuild e) ->
new Bar(
@@ -229,9 +233,7 @@ public class UnitFactory extends UnitBlock{
public boolean canSetCommand(){
var output = unit();
return output != null && output.commands.size > 1 && output.allowChangeCommands &&
//to avoid cluttering UI, don't show command selection for "standard" units that only have two commands.
!(output.commands.size == 2 && output.commands.get(1) == UnitCommand.enterPayloadCommand);
return output != null && output.commands.size > 1 && output.allowChangeCommands;
}
@Override
@@ -258,6 +260,12 @@ public class UnitFactory extends UnitBlock{
@Override
public void onCommand(Vec2 target){
commandPos = target;
if(command != null && command.snapToBuilding){
var build = world.buildWorld(target.x, target.y);
if(build != null && build.team == this.team){
commandPos.set(build);
}
}
}
@Override