Logic sensor (#10795)

* Add `selectedBlock` logic sensor

* Add `buildX`/`buildY`/`building` logic sensors

* Change `building` from boolean to the building

* `breaking`

* Make `breaking`/`building` more consistent

* Allow blocks/content to be null

* Change `selectedBlock` from air to null

* Change `selectedBlock` from air to null

* Make `selectedBlock` SyncLocal

* Add `selectedRotation`
This commit is contained in:
Redstonneur1256
2026-02-08 02:52:33 +01:00
committed by GitHub
parent b2a574eb66
commit 47d28c0d20
10 changed files with 57 additions and 7 deletions

View File

@@ -13,6 +13,7 @@ import arc.util.serialization.*;
import arc.util.serialization.JsonValue.*;
import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.GameState.*;
import mindustry.entities.*;
import mindustry.game.EventType.*;
@@ -699,7 +700,7 @@ public class NetClient implements ApplicationListener{
unit == null ? 0f : unit.vel.x, unit == null ? 0f : unit.vel.y,
dead ? null : unit.mineTile,
player.boosting, player.shooting, ui.chatfrag.shown(), control.input.isBuilding,
player.isBuilder() && unit != null ? unit.plans : null,
player.selectedBlock, player.selectedRotation, player.isBuilder() && unit != null ? unit.plans : null,
Core.camera.position.x, Core.camera.position.y,
Core.camera.width, Core.camera.height
);

View File

@@ -647,7 +647,7 @@ public class NetServer implements ApplicationListener{
float xVelocity, float yVelocity,
Tile mining,
boolean boosting, boolean shooting, boolean chatting, boolean building,
@Nullable Queue<BuildPlan> plans,
Block selectedBlock, int selectedRotation, @Nullable Queue<BuildPlan> plans,
float viewX, float viewY, float viewWidth, float viewHeight
){
NetConnection con = player.con;
@@ -686,6 +686,8 @@ public class NetServer implements ApplicationListener{
player.typing = chatting;
player.shooting = shooting;
player.boosting = boosting;
player.selectedBlock = selectedBlock;
player.selectedRotation = selectedRotation;
@Nullable var unit = player.unit();

View File

@@ -21,6 +21,7 @@ import mindustry.net.Administration.*;
import mindustry.net.*;
import mindustry.net.Packets.*;
import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.blocks.storage.*;
import mindustry.world.blocks.storage.CoreBlock.*;
@@ -37,6 +38,8 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
transient @Nullable NetConnection con;
@ReadOnly Team team = Team.sharded;
@SyncLocal boolean typing, shooting, boosting;
@SyncLocal @Nullable Block selectedBlock;
@SyncLocal int selectedRotation;
@SyncLocal float mouseX, mouseY;
/** command the unit had before it was controlled. */
@Nullable @NoSync UnitCommand lastCommand;

View File

@@ -276,6 +276,8 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
case mining -> mining() ? 1 : 0;
case mineX -> mining() ? mineTile.x : -1;
case mineY -> mining() ? mineTile.y : -1;
case buildX -> isBuilding() ? buildPlan().x : -1;
case buildY -> isBuilding() ? buildPlan().y : -1;
case armor -> armorOverride >= 0f ? armorOverride : armor;
case flag -> flag;
case speed -> type.speed * 60f / tilesize * speedMultiplier;
@@ -289,6 +291,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
case payloadCapacity -> type.payloadCapacity / tilePayload;
case size -> hitSize / tilesize;
case color -> Color.toDoubleBits(team.color.r, team.color.g, team.color.b, 1f);
case selectedRotation -> controller instanceof Player p ? p.selectedRotation : 0;
default -> Float.NaN;
};
}
@@ -304,6 +307,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
(pay.payloads().isEmpty() ? null :
pay.payloads().peek() instanceof UnitPayload p1 ? p1.unit.type :
pay.payloads().peek() instanceof BuildPayload p2 ? p2.block() : null) : null;
case building -> isBuilding() && !buildPlan().breaking ? buildPlan().tile().build : null;
case breaking -> isBuilding() && buildPlan().breaking ? buildPlan().tile().build : null;
case selectedBlock -> controller instanceof Player p ? p.selectedBlock : null;
default -> noSensed;
};
}

View File

@@ -944,6 +944,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
block = null;
}
player.selectedBlock = block;
player.selectedRotation = rotation;
wasShooting = player.shooting;
//only reset the controlled type and control a unit after the timer runs out

View File

@@ -392,11 +392,12 @@ public class TypeIO{
}
public static void writeBlock(Writes write, Block block){
write.s(block.id);
write.s(block == null ? -1 : block.id);
}
public static Block readBlock(Reads read){
return content.block(read.s());
short id = read.s();
return id == -1 ? null : content.block(id);
}
/** @return the maximum acceptable amount of plans to send over the network */

View File

@@ -51,6 +51,10 @@ public enum LAccess{
mineX,
mineY,
mining,
buildX,
buildY,
building,
breaking,
speed,
team,
type,
@@ -64,6 +68,8 @@ public enum LAccess{
payloadCapacity,
maxUnits,
id,
selectedBlock,
selectedRotation,
//values with parameters are considered controllable
enabled("to"), //"to" is standard for single parameter access

View File

@@ -212,8 +212,19 @@ public class ConstructBlock extends Block{
@Override
public double sense(LAccess sensor){
if(sensor == LAccess.progress) return Mathf.clamp(progress);
return super.sense(sensor);
return switch(sensor){
case progress -> Mathf.clamp(progress);
case breaking -> activeDeconstruct ? 1 : 0;
default -> super.sense(sensor);
};
}
@Override
public Object senseObject(LAccess sensor){
return switch(sensor){
case building -> current;
default -> super.senseObject(sensor);
};
}
@Override

View File

@@ -13,6 +13,7 @@ import mindustry.game.Teams.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.io.*;
import mindustry.logic.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.ConstructBlock.*;
@@ -264,5 +265,21 @@ public class BuildTurret extends BaseTurret{
}
}
}
@Override
public double sense(LAccess sensor){
return switch(sensor){
case buildX, buildY -> unit.sense(sensor);
default -> super.sense(sensor);
};
}
@Override
public Object senseObject(LAccess sensor){
return switch(sensor){
case building, breaking -> unit.senseObject(sensor);
default -> super.senseObject(sensor);
};
}
}
}