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

@@ -229,7 +229,7 @@ public class EntityIO{
s(type.equals("boolean") ? "bool" : type.charAt(0) + "", field); s(type.equals("boolean") ? "bool" : type.charAt(0) + "", field);
}else if(instanceOf(type, "mindustry.ctype.Content") && !type.equals("mindustry.ai.UnitStance") && !type.equals("mindustry.ai.UnitCommand")){ }else if(instanceOf(type, "mindustry.ctype.Content") && !type.equals("mindustry.ai.UnitStance") && !type.equals("mindustry.ai.UnitCommand")){
if(write){ if(write){
s("s", field + ".id"); s("s", field + " == null ? -1 : " + field + ".id");
}else{ }else{
st(field + "mindustry.Vars.content.getByID(mindustry.ctype.ContentType.$L, read.s())", BaseProcessor.simpleName(type).toLowerCase().replace("type", "")); st(field + "mindustry.Vars.content.getByID(mindustry.ctype.ContentType.$L, read.s())", BaseProcessor.simpleName(type).toLowerCase().replace("type", ""));
} }

View File

@@ -13,6 +13,7 @@ import arc.util.serialization.*;
import arc.util.serialization.JsonValue.*; import arc.util.serialization.JsonValue.*;
import mindustry.*; import mindustry.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.core.GameState.*; import mindustry.core.GameState.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.game.EventType.*; 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, unit == null ? 0f : unit.vel.x, unit == null ? 0f : unit.vel.y,
dead ? null : unit.mineTile, dead ? null : unit.mineTile,
player.boosting, player.shooting, ui.chatfrag.shown(), control.input.isBuilding, 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.position.x, Core.camera.position.y,
Core.camera.width, Core.camera.height Core.camera.width, Core.camera.height
); );

View File

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

View File

@@ -21,6 +21,7 @@ import mindustry.net.Administration.*;
import mindustry.net.*; import mindustry.net.*;
import mindustry.net.Packets.*; import mindustry.net.Packets.*;
import mindustry.ui.*; import mindustry.ui.*;
import mindustry.world.*;
import mindustry.world.blocks.storage.*; import mindustry.world.blocks.storage.*;
import mindustry.world.blocks.storage.CoreBlock.*; import mindustry.world.blocks.storage.CoreBlock.*;
@@ -37,6 +38,8 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra
transient @Nullable NetConnection con; transient @Nullable NetConnection con;
@ReadOnly Team team = Team.sharded; @ReadOnly Team team = Team.sharded;
@SyncLocal boolean typing, shooting, boosting; @SyncLocal boolean typing, shooting, boosting;
@SyncLocal @Nullable Block selectedBlock;
@SyncLocal int selectedRotation;
@SyncLocal float mouseX, mouseY; @SyncLocal float mouseX, mouseY;
/** command the unit had before it was controlled. */ /** command the unit had before it was controlled. */
@Nullable @NoSync UnitCommand lastCommand; @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 mining -> mining() ? 1 : 0;
case mineX -> mining() ? mineTile.x : -1; case mineX -> mining() ? mineTile.x : -1;
case mineY -> mining() ? mineTile.y : -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 armor -> armorOverride >= 0f ? armorOverride : armor;
case flag -> flag; case flag -> flag;
case speed -> type.speed * 60f / tilesize * speedMultiplier; 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 payloadCapacity -> type.payloadCapacity / tilePayload;
case size -> hitSize / tilesize; case size -> hitSize / tilesize;
case color -> Color.toDoubleBits(team.color.r, team.color.g, team.color.b, 1f); 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; default -> Float.NaN;
}; };
} }
@@ -304,6 +307,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
(pay.payloads().isEmpty() ? null : (pay.payloads().isEmpty() ? null :
pay.payloads().peek() instanceof UnitPayload p1 ? p1.unit.type : pay.payloads().peek() instanceof UnitPayload p1 ? p1.unit.type :
pay.payloads().peek() instanceof BuildPayload p2 ? p2.block() : null) : null; 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; default -> noSensed;
}; };
} }

View File

@@ -944,6 +944,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
block = null; block = null;
} }
player.selectedBlock = block;
player.selectedRotation = rotation;
wasShooting = player.shooting; wasShooting = player.shooting;
//only reset the controlled type and control a unit after the timer runs out //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){ 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){ 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 */ /** @return the maximum acceptable amount of plans to send over the network */

View File

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

View File

@@ -212,8 +212,19 @@ public class ConstructBlock extends Block{
@Override @Override
public double sense(LAccess sensor){ public double sense(LAccess sensor){
if(sensor == LAccess.progress) return Mathf.clamp(progress); return switch(sensor){
return super.sense(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 @Override

View File

@@ -13,6 +13,7 @@ import mindustry.game.Teams.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.graphics.*; import mindustry.graphics.*;
import mindustry.io.*; import mindustry.io.*;
import mindustry.logic.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.ConstructBlock.*; 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);
};
}
} }
} }