From 0185b08ca766bfede446376f9de43bde7b98fd03 Mon Sep 17 00:00:00 2001 From: The4codeblocks <72419529+The4codeblocks@users.noreply.github.com> Date: Tue, 17 Jun 2025 11:36:42 -0500 Subject: [PATCH 1/2] canvas read/write + multiplayer overwrite bug fix (#10899) * stuff * Update CanvasBlock.java * canvas read/write * updated flag * dispose on every possible closing condition (back/cancel/ok) * arraycopy * hide listener * partial colons * fix updated and dedupe closing * typo? --- core/src/mindustry/logic/LExecutor.java | 5 ++ .../world/blocks/logic/CanvasBlock.java | 73 +++++++++++++++---- 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index 043dcc9f7c..8da4f9201f 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -25,6 +25,7 @@ import mindustry.ui.*; import mindustry.world.*; import mindustry.world.blocks.environment.*; import mindustry.world.blocks.logic.*; +import mindustry.world.blocks.logic.CanvasBlock.*; import mindustry.world.blocks.logic.LogicBlock.*; import mindustry.world.blocks.logic.LogicDisplay.*; import mindustry.world.blocks.logic.MemoryBlock.*; @@ -581,6 +582,8 @@ public class LExecutor{ } }else if(target.isobj && target.objval instanceof CharSequence str){ output.setnum(address < 0 || address >= str.length() ? Double.NaN : (int)str.charAt(address)); + }else if(from instanceof CanvasBuild canvas && (exec.privileged || (from.team == exec.team))){ + output.setnum(canvas.getPixel(address)); } } } @@ -611,6 +614,8 @@ public class LExecutor{ toVar.numval = value.numval; toVar.isobj = value.isobj; } + }else if(from instanceof CanvasBuild canvas && (exec.privileged || (from.team == exec.team))){ + canvas.setPixel(address, (int)(value.numval)); } } } diff --git a/core/src/mindustry/world/blocks/logic/CanvasBlock.java b/core/src/mindustry/world/blocks/logic/CanvasBlock.java index 9bab59a42a..5ec712dcb9 100644 --- a/core/src/mindustry/world/blocks/logic/CanvasBlock.java +++ b/core/src/mindustry/world/blocks/logic/CanvasBlock.java @@ -17,6 +17,7 @@ import mindustry.annotations.Annotations.*; import mindustry.entities.units.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.logic.*; import mindustry.ui.*; import mindustry.world.*; @@ -35,7 +36,7 @@ public class CanvasBlock extends Block{ public @Load("@-corner1") TextureRegion corner1; public @Load("@-corner2") TextureRegion corner2; - protected @Nullable Pixmap previewPixmap; + protected @Nullable Pixmap previewPixmap; // please use only for previews protected @Nullable Texture previewTexture; protected int tempBlend = 0; @@ -49,7 +50,7 @@ public class CanvasBlock extends Block{ config(byte[].class, (CanvasBuild build, byte[] bytes) -> { if(build.data.length == bytes.length){ - build.data = bytes; + System.arraycopy(bytes, 0, build.data, 0, bytes.length); build.updateTexture(); } }); @@ -65,13 +66,15 @@ public class CanvasBlock extends Block{ bitsPerPixel = Mathf.log2(Mathf.nextPowerOfTwo(palette.length)); clipSize = Math.max(clipSize, size * 8 - padding); + + previewPixmap = new Pixmap(canvasSize, canvasSize); } @Override public void drawPlanRegion(BuildPlan plan, Eachable list){ //only draw the preview in schematics, as it lags otherwise if(!plan.worldContext && plan.config instanceof byte[] data){ - Pixmap pix = makePixmap(data); + Pixmap pix = makePixmap(data, previewPixmap); if(previewTexture == null){ previewTexture = new Texture(pix); @@ -123,20 +126,15 @@ public class CanvasBlock extends Block{ } } - /** returns the same pixmap instance each time, use with care */ - public Pixmap makePixmap(byte[] data){ - if(previewPixmap == null){ - previewPixmap = new Pixmap(canvasSize, canvasSize); - } - + public Pixmap makePixmap(byte[] data, Pixmap target){ int bpp = bitsPerPixel; int pixels = canvasSize * canvasSize; for(int i = 0; i < pixels; i++){ int bitOffset = i * bpp; int pal = getByte(data, bitOffset); - previewPixmap.set(i % canvasSize, i / canvasSize, palette[pal]); + target.set(i % canvasSize, i / canvasSize, palette[pal]); } - return previewPixmap; + return target; } protected int getByte(byte[] data, int bitOffset){ @@ -152,11 +150,41 @@ public class CanvasBlock extends Block{ public @Nullable Texture texture; public byte[] data = new byte[Mathf.ceil(canvasSize * canvasSize * bitsPerPixel / 8f)]; public int blending; + + protected boolean updated = false; + + public void setPixel(int pos, int index){ + if(pos < canvasSize * canvasSize && pos >= 0 && index >= 0 && index < palette.length){ + setByte(data, pos * bitsPerPixel, index); + updated = true; + } + } + + public void setPixel(int x, int y, int index){ + if(x >= 0 && y >= 0 && x < canvasSize && y < canvasSize && index >= 0 && index < palette.length){ + setByte(data, (y * canvasSize + x) * bitsPerPixel, index); + updated = true; + } + } + + public int getPixel(int pos){ + if(pos >= 0 && pos < canvasSize * canvasSize){ + return getByte(data, pos * bitsPerPixel); + } + return 0; + } + + public int getPixel(int x, int y){ + if(x >= 0 && y >= 0 && x < canvasSize && y < canvasSize){ + return getByte(data, (y * canvasSize + x) * bitsPerPixel); + } + return 0; + } public void updateTexture(){ if(headless) return; - Pixmap pix = makePixmap(data); + Pixmap pix = makePixmap(data, previewPixmap); if(texture != null){ texture.draw(pix); }else{ @@ -214,7 +242,8 @@ public class CanvasBlock extends Block{ super.draw(); } - if(texture == null){ + if(texture == null || updated){ + updated = false; updateTexture(); } Tmp.tr1.set(texture); @@ -237,6 +266,14 @@ public class CanvasBlock extends Block{ } } } + + @Override + public double sense(LAccess sensor){ + return switch(sensor){ + case displayWidth, displayHeight -> canvasSize; + default -> super.sense(sensor); + }; + } @Override public void remove(){ @@ -252,12 +289,17 @@ public class CanvasBlock extends Block{ table.button(Icon.pencil, Styles.cleari, () -> { Dialog dialog = new Dialog(); - Pixmap pix = makePixmap(data); + Pixmap pix = makePixmap(data, new Pixmap(canvasSize, canvasSize)); Texture texture = new Texture(pix); int[] curColor = {palette[0]}; boolean[] modified = {false}; boolean[] fill = {false}; - + + dialog.hidden(() -> { + texture.dispose(); + pix.dispose(); + }); + dialog.resized(dialog::hide); dialog.cont.table(Tex.pane, body -> { @@ -395,7 +437,6 @@ public class CanvasBlock extends Block{ dialog.buttons.button("@ok", Icon.ok, () -> { if(modified[0]){ configure(packPixmap(pix)); - texture.dispose(); } dialog.hide(); }); From b73c85ff75f811a53efb5a067d5c8f76f4b7d508 Mon Sep 17 00:00:00 2001 From: Redstonneur1256 <29004178+Redstonneur1256@users.noreply.github.com> Date: Thu, 19 Jun 2025 01:05:08 +0200 Subject: [PATCH 2/2] Quad marker tweaks (#10787) * Don't clamp UV on repeat textures * Cleanup --- core/src/mindustry/game/MapObjectives.java | 37 +++++++++++++--------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/core/src/mindustry/game/MapObjectives.java b/core/src/mindustry/game/MapObjectives.java index 3371998af8..31fac3c1e0 100644 --- a/core/src/mindustry/game/MapObjectives.java +++ b/core/src/mindustry/game/MapObjectives.java @@ -3,6 +3,7 @@ package mindustry.game; import arc.*; import arc.func.*; import arc.graphics.*; +import arc.graphics.Texture.*; import arc.graphics.g2d.*; import arc.math.*; import arc.math.geom.*; @@ -98,7 +99,7 @@ public class MapObjectives implements Iterable, Eachable prov) { + public static void registerLegacyMarker(String name, Prov prov){ Class type = prov.get().getClass(); markerNameToType.put(name, prov); @@ -663,7 +664,7 @@ public class MapObjectives implements Iterable, Eachable, Eachable, Eachable ((int)p1 == 0 ? pos : (int)p1 == 1 ? endPos : Tmp.v1).x = (float)p2 * tilesize; case colori -> ((int)p1 == 0 ? color1 : (int)p1 == 1 ? color2 : Tmp.c1).fromDouble(p2); } @@ -1179,7 +1180,7 @@ public class MapObjectives implements Iterable, Eachable, Eachable, Eachable= 0 && i < 4){ if(!Double.isNaN(x)) vertices[i * 6] = (float)x * tilesize; @@ -1270,11 +1272,16 @@ public class MapObjectives implements Iterable, Eachable= 0 && i < 4){ if(fetchedRegion == null) setTexture(textureName); - if(!Double.isNaN(u)) vertices[i * 6 + 3] = Mathf.map(Mathf.clamp((float)u), fetchedRegion.u, fetchedRegion.u2); - if(!Double.isNaN(v)) vertices[i * 6 + 4] = Mathf.map(1 - Mathf.clamp((float)v), fetchedRegion.v, fetchedRegion.v2); + if(!Double.isNaN(u)){ + boolean clampU = fetchedRegion.texture.getUWrap() != TextureWrap.mirroredRepeat && fetchedRegion.texture.getUWrap() != TextureWrap.repeat; + vertices[i * 6 + 3] = Mathf.map(clampU ? Mathf.clamp((float)u) : (float)u, fetchedRegion.u, fetchedRegion.u2); + } + if(!Double.isNaN(v)){ + boolean clampV = fetchedRegion.texture.getVWrap() != TextureWrap.mirroredRepeat && fetchedRegion.texture.getVWrap() != TextureWrap.repeat; + vertices[i * 6 + 4] = Mathf.map(clampV ? 1 - Mathf.clamp((float)v) : 1 - (float)v, fetchedRegion.v, fetchedRegion.v2); + } } } - } private static void lookupRegion(String name, TextureRegion out){