From a24dfedb68311ce44022cb34b9854a748bf947d4 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 8 Jan 2025 17:10:05 -0500 Subject: [PATCH] Tileable displays nobody asked for --- core/assets/icons/icons.properties | 1 + core/assets/logicids.dat | Bin 4694 -> 4714 bytes core/src/mindustry/content/Blocks.java | 6 +- core/src/mindustry/logic/LExecutor.java | 16 +- .../world/blocks/logic/LogicDisplay.java | 35 ++-- .../blocks/logic/TileableLogicDisplay.java | 149 ++++++++++++++++++ 6 files changed, 185 insertions(+), 22 deletions(-) create mode 100644 core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index 0767ed44da..31ea8113d5 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -592,3 +592,4 @@ 63090=remove-ore|block-remove-ore-ui 63089=small-heat-redirector|block-small-heat-redirector-ui 63088=large-cliff-crusher|block-large-cliff-crusher-ui +63087=tile-logic-display|block-tile-logic-display-ui diff --git a/core/assets/logicids.dat b/core/assets/logicids.dat index 2145ea1672e78ad50bebb8c008fadce2f92dc6f2..51d71438c065e3558ab6933ec1a4d9e3257a7afa 100644 GIT binary patch delta 36 rcmcbn@=Aq?k!d4SEx)i(NoG!}ZccuBX0mQdW^qAIV&&#K{u@jH+MW!U delta 16 XcmaE*a!rMak#QqaE&t}p{MVTPFgFEy diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 2c5f25b200..1f7960452b 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -158,7 +158,7 @@ public class Blocks{ payloadConveyor, payloadRouter, reinforcedPayloadConveyor, reinforcedPayloadRouter, payloadMassDriver, largePayloadMassDriver, smallDeconstructor, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader, //logic - message, switchBlock, microProcessor, logicProcessor, hyperProcessor, largeLogicDisplay, logicDisplay, memoryCell, memoryBank, + message, switchBlock, microProcessor, logicProcessor, hyperProcessor, largeLogicDisplay, logicDisplay, logicDisplayTile, memoryCell, memoryBank, canvas, reinforcedMessage, worldProcessor, worldCell, worldMessage, worldSwitch, @@ -6066,6 +6066,10 @@ public class Blocks{ size = 6; }}; + logicDisplayTile = new TileableLogicDisplay("tile-logic-display"){{ + requirements(Category.logic, with(Items.lead, 10, Items.silicon, 10, Items.metaglass, 10, Items.phaseFabric, 6)); + }}; + canvas = new CanvasBlock("canvas"){{ requirements(Category.logic, BuildVisibility.shown, with(Items.silicon, 10, Items.beryllium, 10)); diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index 2333fdc344..393fb6edfe 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -45,9 +45,9 @@ public class LExecutor{ public LInstruction[] instructions = {}; /** Non-constant variables used for network sync */ public LVar[] vars = {}; - + public LVar counter, unit, thisv, ipt; - + public int[] binds; public boolean yield; @@ -226,8 +226,8 @@ public class LExecutor{ cache.found = false; outFound.setnum(0); } - - if(res != null && res.build != null && + + if(res != null && res.build != null && (unit.within(res.build.x, res.build.y, Math.max(unit.range(), buildingRange)) || res.build.team == exec.team)){ cache.build = res.build; outBuild.setobj(res.build); @@ -935,11 +935,7 @@ public class LExecutor{ if(Vars.headless) return; if(target.building() instanceof LogicDisplayBuild d && (d.team == exec.team || exec.privileged)){ - if(d.commands.size + exec.graphicsBuffer.size < maxDisplayBuffer){ - for(int i = 0; i < exec.graphicsBuffer.size; i++){ - d.commands.addLast(exec.graphicsBuffer.items[i]); - } - } + d.flushCommands(exec.graphicsBuffer); exec.graphicsBuffer.clear(); } } @@ -1939,7 +1935,7 @@ public class LExecutor{ public void run(LExecutor exec){ Sound sound = Sounds.getSound(id.numi()); if(sound == null || sound == Sounds.swish) sound = Sounds.none; //no. - + if(positional){ sound.at(World.unconv(x.numf()), World.unconv(y.numf()), pitch.numf(), Math.min(volume.numf(), 2f), limit.bool()); }else{ diff --git a/core/src/mindustry/world/blocks/logic/LogicDisplay.java b/core/src/mindustry/world/blocks/logic/LogicDisplay.java index 1816245ad2..bb30c3bbff 100644 --- a/core/src/mindustry/world/blocks/logic/LogicDisplay.java +++ b/core/src/mindustry/world/blocks/logic/LogicDisplay.java @@ -13,6 +13,7 @@ import mindustry.annotations.Annotations.*; import mindustry.ctype.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.logic.*; import mindustry.ui.*; import mindustry.world.*; import mindustry.world.meta.*; @@ -65,7 +66,7 @@ public class LogicDisplay extends Block{ } public class LogicDisplayBuild extends Building{ - public FrameBuffer buffer; + public @Nullable FrameBuffer buffer; public float color = Color.whiteFloatBits; public float stroke = 1f; public LongQueue commands = new LongQueue(256); @@ -87,12 +88,32 @@ public class LogicDisplay extends Block{ } }); + processCommands(); + + Draw.blend(Blending.disabled); + Draw.draw(Draw.z(), () -> { + if(buffer != null){ + Draw.rect(Draw.wrap(buffer.getTexture()), x, y, buffer.getWidth() * scaleFactor * Draw.scl, -buffer.getHeight() * scaleFactor * Draw.scl); + } + }); + Draw.blend(); + } + + public void flushCommands(LongSeq graphicsBuffer){ + int added = Math.min(graphicsBuffer.size, LExecutor.maxDisplayBuffer - commands.size); + + for(int i = 0; i < added; i++){ + commands.addLast(graphicsBuffer.items[i]); + } + } + + public void processCommands(){ //don't bother processing commands if displays are off - if(!commands.isEmpty()){ + if(!commands.isEmpty() && buffer != null){ Draw.draw(Draw.z(), () -> { Tmp.m1.set(Draw.proj()); Tmp.m2.set(Draw.trans()); - Draw.proj(0, 0, displaySize, displaySize); + Draw.proj(0, 0, buffer.getWidth(), buffer.getHeight()); if(transform != null){ Draw.trans(transform); } @@ -148,14 +169,6 @@ public class LogicDisplay extends Block{ Draw.reset(); }); } - - Draw.blend(Blending.disabled); - Draw.draw(Draw.z(), () -> { - if(buffer != null){ - Draw.rect(Draw.wrap(buffer.getTexture()), x, y, buffer.getWidth() * scaleFactor * Draw.scl, -buffer.getHeight() * scaleFactor * Draw.scl); - } - }); - Draw.blend(); } @Override diff --git a/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java b/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java new file mode 100644 index 0000000000..6ca166553f --- /dev/null +++ b/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java @@ -0,0 +1,149 @@ +package mindustry.world.blocks.logic; + +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.graphics.gl.*; +import arc.struct.*; +import arc.util.*; +import mindustry.*; +import mindustry.graphics.*; + +import static mindustry.Vars.*; + +public class TileableLogicDisplay extends LogicDisplay{ + protected static final Seq queue = new Seq<>(); + protected static final Seq displays = new Seq<>(); + protected static final IntSet processed = new IntSet(); + + public TileableLogicDisplay(String name){ + super(name); + + displaySize = 32; + } + + public static void linkDisplays(TileableLogicDisplayBuild start){ + TileableLogicDisplayBuild root = null; + + int topX = start.tile.x, topY = start.tile.y, botX = start.tile.x, botY = start.tile.y; + + queue.clear(); + displays.clear(); + processed.clear(); + + queue.add(start); + displays.add(start); + + while(!queue.isEmpty()){ + var next = queue.pop(); + processed.add(next.id); + + //assign root based on bottom leftmost position + if(root == null || next.tile.x < root.tile.x || next.tile.y < root.tile.y){ + root = next; + } + + topX = Math.max(next.tile.x, topX); + topY = Math.max(next.tile.y, topY); + botX = Math.min(next.tile.x, botX); + botY = Math.min(next.tile.y, botY); + + for(var prox : next.proximity){ + if(prox instanceof TileableLogicDisplayBuild disp && processed.add(disp.id)){ + queue.add(disp); + displays.add(disp); + } + } + } + + int tilesWidth = topX - botX + 1, tilesHeight = topY - botY + 1; + + //the new root display has been assigned + for(var member : displays){ + member.rootDisplay = root; + member.tilesWidth = tilesWidth; + member.tilesHeight = tilesHeight; + member.originX = botX; + member.originY = botY; + + //TODO: preserve buffers later + if(member.buffer != null){ + member.buffer.dispose(); + member.buffer = null; + } + } + } + + public class TileableLogicDisplayBuild extends LogicDisplayBuild{ + //bottom left corner of display + public TileableLogicDisplayBuild rootDisplay = this; + //size of display area + public int tilesWidth = 1, tilesHeight = 1, originX, originY; + + @Override + public void draw(){ + Draw.rect(block.region, x, y); + + //don't even bother processing anything when displays are off. + if(!Vars.renderer.drawDisplays) return; + + if(isRoot()){ + Draw.draw(Draw.z(), () -> { + if(buffer == null){ + buffer = new FrameBuffer(32 * tilesWidth, 32 * tilesHeight); + Log.info("create " + buffer.getWidth() + " " + buffer.getHeight()); + //clear the buffer - some OSs leave garbage in it + buffer.begin(Pal.darkerMetal); + buffer.end(); + } + }); + + processCommands(); + } + + Draw.blend(Blending.disabled); + Draw.draw(Draw.z(), () -> { + if(rootDisplay.buffer != null){ + + int rtx = (tile.x - originX), rty = (tile.y - originY); + + Tmp.tr1.set(rootDisplay.buffer.getTexture(), rtx * 32, rty * 32, 32, 32); + Draw.rect(Tmp.tr1, x, y, tilesize, -tilesize); + } + }); + Draw.blend(); + } + + @Override + public void flushCommands(LongSeq graphicsBuffer){ + if(isRoot()){ + super.flushCommands(graphicsBuffer); + }else{ + rootDisplay.flushCommands(graphicsBuffer); + } + } + + @Override + public void onProximityAdded(){ + super.onProximityAdded(); + + linkDisplays(this); + } + + @Override + public void onProximityRemoved(){ + super.onProximityRemoved(); + + processed.clear(); + + for(var other : proximity){ + if(other instanceof TileableLogicDisplayBuild tl && !processed.contains(tl.id)){ + linkDisplays(tl); + } + } + } + + public boolean isRoot(){ + return rootDisplay == this; + } + } +}