Merge branch 'master' of https://github.com/Anuken/Mindustry into crux-floor

# Conflicts:
#	gradle.properties
This commit is contained in:
Anuken
2025-07-10 13:52:31 -04:00
96 changed files with 1256 additions and 501 deletions

View File

@@ -923,11 +923,16 @@ public class Block extends UnlockableContent implements Senseable{
}
public boolean isVisible(){
return !isHidden() && (state.rules.editor || (!state.rules.hideBannedBlocks || !state.rules.isBanned(this)));
return !isHidden() && (state.rules.editor || (!state.rules.hideBannedBlocks || !isBanned()));
}
public boolean isPlaceable(){
return isVisible() && (!state.rules.isBanned(this) || state.rules.editor) && supportsEnv(state.rules.env);
return isVisible() && (!isBanned() || state.rules.editor) && supportsEnv(state.rules.env);
}
@Override
public boolean isBanned(){
return state.rules.isBanned(this);
}
/** @return whether this block supports a specific environment. */

View File

@@ -94,7 +94,7 @@ public class LiquidTurret extends Turret{
var fire = Fires.get(x + tx, y + ty);
float dst = fire == null ? 0 : dst2(fire);
//do not extinguish fires on other team blocks
if(other != null && fire != null && Fires.has(other.x, other.y) && dst <= range * range && (result == null || dst < mindst) && (other.build == null || other.team() == team)){
if(other != null && fire != null && other.build != this && Fires.has(other.x, other.y) && dst <= range * range && (result == null || dst < mindst) && (other.build == null || other.team() == team)){
result = fire;
mindst = dst;
}

View File

@@ -96,8 +96,7 @@ public class DirectionalUnloader extends Block{
front.handleItem(this, item);
back.items.remove(item, 1);
back.itemTaken(item);
offset ++;
offset %= itemc;
offset = item.id + 1;
break;
}
}

View File

@@ -376,6 +376,11 @@ public class Floor extends Block{
return (other.realBlendId(otherTile) > realBlendId(tile) || edges(tile.x, tile.y) == null);
}
/** @return whether being on this floor can damage a unit */
public boolean damages(){
return damageTaken > 0f || (status != null && status.damage > 0f);
}
public static class UpdateRenderState{
public Tile tile;
public Floor floor;

View File

@@ -146,7 +146,7 @@ public class CanvasBlock extends Block{
return result;
}
public class CanvasBuild extends Building{
public class CanvasBuild extends Building implements LReadable, LWritable{
public @Nullable Texture texture;
public byte[] data = new byte[Mathf.ceil(canvasSize * canvasSize * bitsPerPixel / 8f)];
public int blending;
@@ -226,6 +226,25 @@ public class CanvasBlock extends Block{
}
}
public boolean readable(LExecutor exec){
return exec.privileged || this.team == exec.team;
}
@Override
public void read(LVar position, LVar output){
output.setnum(getPixel(position.numi()));
}
@Override
public boolean writable(LExecutor exec){
return exec.privileged || this.team == exec.team;
}
@Override
public void write(LVar position, LVar value){
setPixel(position.numi(), value.numi());
}
boolean blends(Tile other){
return other != null && other.build != null && other.build.block == block && other.build.tileX() == other.x && other.build.tileY() == other.y;
}

View File

@@ -82,17 +82,11 @@ public class LogicBlock extends Block{
int x = lbuild.tileX(), y = lbuild.tileY();
LogicLink link = entity.links.find(l -> l.x == x && l.y == y);
String bname = getLinkName(lbuild.block);
if(link != null){
link.active = !link.active;
//find a name when the base name differs (new block type)
if(!link.name.startsWith(bname)){
link.name = "";
link.name = entity.findLinkName(lbuild.block);
}
entity.links.remove(link);
//disable when unlinking
if(!link.active && lbuild.block.autoResetEnabled && lbuild.lastDisabler == entity){
if(lbuild.block.autoResetEnabled && lbuild.lastDisabler == entity){
lbuild.enabled = true;
}
}else{
@@ -148,12 +142,8 @@ public class LogicBlock extends Block{
stream.writeInt(bytes.length);
stream.write(bytes);
int actives = links.count(l -> l.active);
stream.writeInt(actives);
stream.writeInt(links.size);
for(LogicLink link : links){
if(!link.active) continue;
stream.writeUTF(link.name);
stream.writeShort(link.x);
stream.writeShort(link.y);
@@ -207,11 +197,7 @@ public class LogicBlock extends Block{
String name = stream.readUTF();
short x = stream.readShort(), y = stream.readShort();
Tmp.p2.set((int)(offset / (tilesize/2)), (int)(offset / (tilesize/2)));
transformer.get(Tmp.p1.set(x * 2, y * 2).sub(Tmp.p2));
Tmp.p1.add(Tmp.p2);
Tmp.p1.x /= 2;
Tmp.p1.y /= 2;
transformer.get(Tmp.p1.set(x, y));
links.add(new LogicLink(Tmp.p1.x, Tmp.p1.y, name, true));
}
@@ -224,7 +210,7 @@ public class LogicBlock extends Block{
}
public static class LogicLink{
public boolean active = true, valid;
public boolean valid;
public int x, y;
public String name;
public Building lastBuild;
@@ -237,13 +223,11 @@ public class LogicBlock extends Block{
}
public LogicLink copy(){
LogicLink out = new LogicLink(x, y, name, valid);
out.active = active;
return out;
return new LogicLink(x, y, name, valid);
}
}
public class LogicBuild extends Building implements Ranged{
public class LogicBuild extends Building implements Ranged, LReadable, LWritable{
/** logic "source code" as list of asm statements */
public String code = "";
public LExecutor executor = new LExecutor();
@@ -357,18 +341,19 @@ public class LogicBlock extends Block{
//store connections
for(LogicLink link : links){
if(link.active && (link.valid = validLink(world.build(link.x, link.y)))){
link.valid = validLink(world.build(link.x, link.y));
if(link.valid){
asm.putConst(link.name, world.build(link.x, link.y));
}
}
//store link objects
executor.links = new Building[links.count(l -> l.valid && l.active)];
executor.links = new Building[links.count(l -> l.valid)];
executor.linkIds.clear();
int index = 0;
for(LogicLink link : links){
if(link.active && link.valid){
if(link.valid){
Building build = world.build(link.x, link.y);
executor.links[index ++] = build;
if(build != null) executor.linkIds.add(build.id);
@@ -387,9 +372,7 @@ public class LogicBlock extends Block{
if(!var.constant){
LVar dest = asm.getVar(var.name);
if(dest != null && !dest.constant){
dest.isobj = var.isobj;
dest.objval = var.objval;
dest.numval = var.numval;
dest.set(var);
}
}
}
@@ -497,8 +480,6 @@ public class LogicBlock extends Block{
for(int i = 0; i < links.size; i++){
LogicLink l = links.get(i);
if(!l.active) continue;
var cur = world.build(l.x, l.y);
boolean valid = validLink(cur);
@@ -551,6 +532,38 @@ public class LogicBlock extends Block{
}
}
@Override
public boolean readable(LExecutor exec){
return exec.privileged || (this.team == exec.team && !this.block.privileged);
}
@Override
public void read(LVar position, LVar output){
if(position.isobj && position.objval instanceof String varName){
LVar ret = executor.optionalVar(varName);
if(ret == null){
output.setnum(Double.NaN);
return;
}
if(output.constant) return;
output.set(ret);
}
}
@Override
public boolean writable(LExecutor exec){
return exec.privileged || (this.team == exec.team && !this.block.privileged);
}
@Override
public void write(LVar position, LVar value){
if(position.isobj && position.objval instanceof String varName){
LVar at = executor.optionalVar(varName);
if(at == null || at.constant) return;
at.set(value);
}
}
@Override
public byte[] config(){
return compress(code, relativeConnections());
@@ -577,7 +590,7 @@ public class LogicBlock extends Block{
for(LogicLink l : links){
Building build = world.build(l.x, l.y);
if(l.active && validLink(build)){
if(validLink(build)){
Drawf.square(build.x, build.y, build.block.size * tilesize / 2f + 1f, Pal.place);
}
}
@@ -585,7 +598,7 @@ public class LogicBlock extends Block{
//draw top text on separate layer
for(LogicLink l : links){
Building build = world.build(l.x, l.y);
if(l.active && validLink(build)){
if(validLink(build)){
build.block.drawPlaceText(l.name, build.tileX(), build.tileY(), true);
}
}

View File

@@ -111,7 +111,7 @@ public class LogicDisplay extends Block{
public double sense(LAccess sensor){
return switch(sensor){
case displayWidth, displayHeight -> displaySize;
case bufferUsage -> commands.size;
case bufferSize -> commands.size;
case operations -> operations;
default -> super.sense(sensor);
};

View File

@@ -37,7 +37,7 @@ public class MemoryBlock extends Block{
return accessible();
}
public class MemoryBuild extends Building{
public class MemoryBuild extends Building implements LReadable, LWritable{
public double[] memory = new double[memoryCapacity];
//massive byte size means picking up causes sync issues
@@ -56,6 +56,29 @@ public class MemoryBlock extends Block{
return accessible();
}
public boolean readable(LExecutor exec){
return exec.privileged || (this.team == exec.team && !this.block.privileged);
}
@Override
public void read(LVar position, LVar output){
int address = position.numi();
//Return null when out of bounds. (instead of 0)
output.setnum(address < 0 || address >= memory.length ? Double.NaN : memory[address]);
}
@Override
public boolean writable(LExecutor exec){
return exec.privileged || (this.team == exec.team && !this.block.privileged);
}
@Override
public void write(LVar position, LVar value){
int address = position.numi();
if(address < 0 || address >= memory.length) return;
memory[address] = value.num();
}
@Override
public double sense(LAccess sensor){
return switch(sensor){

View File

@@ -14,6 +14,7 @@ import arc.util.io.*;
import arc.util.pooling.*;
import mindustry.core.*;
import mindustry.gen.*;
import mindustry.logic.*;
import mindustry.ui.*;
import mindustry.ui.dialogs.*;
import mindustry.world.*;
@@ -67,7 +68,7 @@ public class MessageBlock extends Block{
return accessible();
}
public class MessageBuild extends Building{
public class MessageBuild extends Building implements LReadable{
public StringBuilder message = new StringBuilder();
@Override
@@ -165,6 +166,25 @@ public class MessageBlock extends Block{
return !accessible() ? SystemCursor.arrow : super.getCursor();
}
@Override
public boolean readable(LExecutor exec){
return true;
}
@Override
public void read(LVar position, LVar output){
int address = position.numi();
output.setnum(address < 0 || address >= message.length() ? Double.NaN : message.charAt(address));
}
@Override
public double sense(LAccess sensor){
return switch(sensor){
case bufferSize -> message.length();
default -> super.sense(sensor);
};
}
@Override
public void damage(float damage){
if(privileged) return;

View File

@@ -228,7 +228,7 @@ public class PayloadLoader extends PayloadBlock{
return payload != null && (
exporting ||
(payload.block().hasLiquids && liquids.currentAmount() >= 0.1f && payload.build.liquids.currentAmount() >= payload.block().liquidCapacity - 0.001f) ||
(payload.block().hasItems && items.any() && payload.block().separateItemCapacity && content.items().contains(i -> payload.build.items.get(i) >= payload.block().itemCapacity)) ||
(payload.block().hasItems && items.any() && payload.block().separateItemCapacity && content.items().contains(i -> (payload.build.items.get(i) >= payload.block().itemCapacity) && items.has(i))) ||
(hasBattery() && payload.build.power.status >= 0.999999999f));
}

View File

@@ -246,7 +246,7 @@ public class Drill extends Block{
@Override
public boolean shouldConsume(){
return items.total() < itemCapacity && enabled;
return items.total() < itemCapacity && enabled && dominantItem != null;
}
@Override

View File

@@ -33,7 +33,7 @@ public class Incinerator extends Block{
@Override
public BlockStatus status(){
return heat > 0.5f ? BlockStatus.active : BlockStatus.noInput;
return !enabled ? BlockStatus.logicDisable : heat > 0.5f ? BlockStatus.active : BlockStatus.noInput;
}
@Override

View File

@@ -38,7 +38,7 @@ public class ItemIncinerator extends Block{
@Override
public BlockStatus status(){
return efficiency > 0 ? BlockStatus.active : BlockStatus.noInput;
return !enabled ? BlockStatus.logicDisable : efficiency > 0 ? BlockStatus.active : BlockStatus.noInput;
}
@Override

View File

@@ -220,6 +220,14 @@ public class UnitFactory extends UnitBlock{
}
}
@Override
public void drawSelect(){
super.drawSelect();
if(plans.size > 1 && currentPlan != -1 && currentPlan < plans.size){
drawItemSelection(plans.get(currentPlan).unit);
}
}
@Override
public Vec2 getCommandPosition(){
return commandPos;