From 066e1b39abc038ec1f555af140bcd2e376cd0dab Mon Sep 17 00:00:00 2001 From: Arthur Schifano Date: Wed, 8 Apr 2026 17:40:03 +0200 Subject: [PATCH 01/42] Adding a map objective copy/paste through the JSON copy mechanism --- .../mindustry/editor/MapObjectivesCanvas.java | 10 ++++++++++ .../mindustry/editor/MapObjectivesDialog.java | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/core/src/mindustry/editor/MapObjectivesCanvas.java b/core/src/mindustry/editor/MapObjectivesCanvas.java index 48c424281b..f62456d949 100644 --- a/core/src/mindustry/editor/MapObjectivesCanvas.java +++ b/core/src/mindustry/editor/MapObjectivesCanvas.java @@ -29,6 +29,7 @@ public class MapObjectivesCanvas extends WidgetGroup{ public final float unitSize = Scl.scl(48f); public Seq objectives = new Seq<>(); + public int pasteX, pasteY; public ObjectiveTilemap tilemap; protected MapObjective query; @@ -314,6 +315,11 @@ public class MapObjectivesCanvas extends WidgetGroup{ public boolean moveTile(ObjectiveTile tile, int newX, int newY){ if(!validPlace(newX, newY, tile)) return false; + if(tile.obj.editorX == pasteX && tile.obj.editorY == pasteY){ + pasteX = newX; + pasteY = newY; + } + tile.pos(newX, newY); return true; @@ -381,6 +387,10 @@ public class MapObjectivesCanvas extends WidgetGroup{ dialog.addCloseButton(); dialog.show(); }); + b.button(Icon.copySmall, () -> { + pasteX = obj.editorX; + pasteY = obj.editorY; + }); // Object position can be used as an ID. b.button(Icon.trashSmall, () -> removeTile(this)); }).left().grow(); }).growX().height(unitSize / Scl.scl(1f) * 2).get().addCaptureListener(mover = new Mover()); diff --git a/core/src/mindustry/editor/MapObjectivesDialog.java b/core/src/mindustry/editor/MapObjectivesDialog.java index ae82444014..57d731dbf9 100644 --- a/core/src/mindustry/editor/MapObjectivesDialog.java +++ b/core/src/mindustry/editor/MapObjectivesDialog.java @@ -39,6 +39,8 @@ public class MapObjectivesDialog extends BaseDialog{ /** Maps annotation type with its field parsers. Non-annotated fields are mapped with {@link Override}. */ private static final ObjectMap, ObjectMap, FieldInterpreter>> interpreters = new ObjectMap<>(); + private MapObjective copy = null; + static{ // Default un-annotated field interpreters. setProvider(String.class, (type, cons) -> cons.get("")); @@ -486,6 +488,20 @@ public class MapObjectivesDialog extends BaseDialog{ buttons.defaults().size(160f, 64f).pad(2f); buttons.button("@back", Icon.left, MapObjectivesDialog.this::hide); buttons.button("@add", Icon.add, () -> getProvider(MapObjective.class).get(new TypeInfo(MapObjective.class), canvas::query)); + buttons.button("@mod.dependencies.download", Icon.paste, () -> { + Core.app.setClipboardText(JsonIO.write(new MapObjectives(canvas.objectives))); + for(var obj : JsonIO.read(MapObjectives.class, Core.app.getClipboardText()).all){ + if(obj.editorX == canvas.pasteX && obj.editorY == canvas.pasteY){ + copy = obj; + } + }; + if(copy == null){ + ui.showErrorMessage("@save.import.invalid"); + }else{ + canvas.tilemap.createTile(copy.editorX, copy.editorY, copy, true); + canvas.objectives.add(copy); + } + }); buttons.button("@waves.edit", Icon.edit, () -> { BaseDialog dialog = new BaseDialog("@waves.edit"); dialog.addCloseButton(); From fe5ca2614e17a20f67d38613c90533eba112cc11 Mon Sep 17 00:00:00 2001 From: Arthur Schifano Date: Wed, 8 Apr 2026 17:54:24 +0200 Subject: [PATCH 02/42] Adding myself as a contributor if my pr is good enough --- core/assets/contributors | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/assets/contributors b/core/assets/contributors index ce002e134b..b21d5b2632 100644 --- a/core/assets/contributors +++ b/core/assets/contributors @@ -190,4 +190,5 @@ buj Agzam4 ItsKirby69 TheCuber -Jovinull \ No newline at end of file +Jovinull +Adleanogare \ No newline at end of file From 02ce0bc8a56cd76397a8629e7b45cca3a7c09479 Mon Sep 17 00:00:00 2001 From: Arthur Schifano Date: Wed, 8 Apr 2026 18:35:43 +0200 Subject: [PATCH 03/42] Slight change to text --- core/assets/bundles/bundle.properties | 2 ++ core/src/mindustry/editor/MapObjectivesDialog.java | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 1e08297ceb..e125fe06e8 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -574,6 +574,7 @@ editor.randomize = Randomize editor.moveup = Move Up editor.movedown = Move Down editor.copy = Copy +editor.paste = Paste editor.apply = Apply editor.generate = Generate editor.sectorgenerate = Sector Generate @@ -802,6 +803,7 @@ error.io = Network I/O error. error.any = Unknown network error. error.bloom = Failed to initialize bloom.\nYour device may not support it. error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThis will not be fixed. There is no known workaround for this issue. +error.objectivecopy = No copied objective. weather.rain.name = Rain weather.snowing.name = Snow diff --git a/core/src/mindustry/editor/MapObjectivesDialog.java b/core/src/mindustry/editor/MapObjectivesDialog.java index 57d731dbf9..9277dca9da 100644 --- a/core/src/mindustry/editor/MapObjectivesDialog.java +++ b/core/src/mindustry/editor/MapObjectivesDialog.java @@ -488,7 +488,7 @@ public class MapObjectivesDialog extends BaseDialog{ buttons.defaults().size(160f, 64f).pad(2f); buttons.button("@back", Icon.left, MapObjectivesDialog.this::hide); buttons.button("@add", Icon.add, () -> getProvider(MapObjective.class).get(new TypeInfo(MapObjective.class), canvas::query)); - buttons.button("@mod.dependencies.download", Icon.paste, () -> { + buttons.button("@editor.paste", Icon.paste, () -> { Core.app.setClipboardText(JsonIO.write(new MapObjectives(canvas.objectives))); for(var obj : JsonIO.read(MapObjectives.class, Core.app.getClipboardText()).all){ if(obj.editorX == canvas.pasteX && obj.editorY == canvas.pasteY){ @@ -496,7 +496,7 @@ public class MapObjectivesDialog extends BaseDialog{ } }; if(copy == null){ - ui.showErrorMessage("@save.import.invalid"); + ui.showErrorMessage("@error.objectivecopy"); }else{ canvas.tilemap.createTile(copy.editorX, copy.editorY, copy, true); canvas.objectives.add(copy); From a5d076deccd415e6508b6685b754029bfb231148 Mon Sep 17 00:00:00 2001 From: Arthur Schifano Date: Mon, 13 Apr 2026 18:13:32 +0200 Subject: [PATCH 04/42] The copy blocks now only appear for mobile. (Stilled need to be compilled and tested, desktop ctrl-c ctrl-v will come soon.) --- .../mindustry/editor/MapObjectivesCanvas.java | 14 ++++++---- .../mindustry/editor/MapObjectivesDialog.java | 28 +++++++++---------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/core/src/mindustry/editor/MapObjectivesCanvas.java b/core/src/mindustry/editor/MapObjectivesCanvas.java index f62456d949..fa884c6abf 100644 --- a/core/src/mindustry/editor/MapObjectivesCanvas.java +++ b/core/src/mindustry/editor/MapObjectivesCanvas.java @@ -29,7 +29,7 @@ public class MapObjectivesCanvas extends WidgetGroup{ public final float unitSize = Scl.scl(48f); public Seq objectives = new Seq<>(); - public int pasteX, pasteY; + public int pasteX = -999, pasteY = -999; public ObjectiveTilemap tilemap; protected MapObjective query; @@ -387,10 +387,14 @@ public class MapObjectivesCanvas extends WidgetGroup{ dialog.addCloseButton(); dialog.show(); }); - b.button(Icon.copySmall, () -> { - pasteX = obj.editorX; - pasteY = obj.editorY; - }); // Object position can be used as an ID. + + if(mobile){ + b.button(Icon.copySmall, () -> { + pasteX = obj.editorX; + pasteY = obj.editorY; + }); // Object position can be used as an ID. + } + b.button(Icon.trashSmall, () -> removeTile(this)); }).left().grow(); }).growX().height(unitSize / Scl.scl(1f) * 2).get().addCaptureListener(mover = new Mover()); diff --git a/core/src/mindustry/editor/MapObjectivesDialog.java b/core/src/mindustry/editor/MapObjectivesDialog.java index 9277dca9da..bc239643cf 100644 --- a/core/src/mindustry/editor/MapObjectivesDialog.java +++ b/core/src/mindustry/editor/MapObjectivesDialog.java @@ -488,20 +488,6 @@ public class MapObjectivesDialog extends BaseDialog{ buttons.defaults().size(160f, 64f).pad(2f); buttons.button("@back", Icon.left, MapObjectivesDialog.this::hide); buttons.button("@add", Icon.add, () -> getProvider(MapObjective.class).get(new TypeInfo(MapObjective.class), canvas::query)); - buttons.button("@editor.paste", Icon.paste, () -> { - Core.app.setClipboardText(JsonIO.write(new MapObjectives(canvas.objectives))); - for(var obj : JsonIO.read(MapObjectives.class, Core.app.getClipboardText()).all){ - if(obj.editorX == canvas.pasteX && obj.editorY == canvas.pasteY){ - copy = obj; - } - }; - if(copy == null){ - ui.showErrorMessage("@error.objectivecopy"); - }else{ - canvas.tilemap.createTile(copy.editorX, copy.editorY, copy, true); - canvas.objectives.add(copy); - } - }); buttons.button("@waves.edit", Icon.edit, () -> { BaseDialog dialog = new BaseDialog("@waves.edit"); dialog.addCloseButton(); @@ -536,6 +522,20 @@ public class MapObjectivesDialog extends BaseDialog{ }); if(mobile){ + buttons.button("@editor.paste", Icon.paste, () -> { + Core.app.setClipboardText(JsonIO.write(new MapObjectives(canvas.objectives))); + for(var obj : JsonIO.read(MapObjectives.class, Core.app.getClipboardText()).all){ + if(obj.editorX == canvas.pasteX && obj.editorY == canvas.pasteY){ + copy = obj; + } + }; + if(copy == null){ + ui.showErrorMessage("@error.objectivecopy"); + }else{ + canvas.tilemap.createTile(copy.editorX, copy.editorY, copy, true); + canvas.objectives.add(copy); + } + }).visible(() -> copy != null || canvas.pasteX != -999 || canvas.pasteY != -999); buttons.button("@cancel", Icon.cancel, canvas::stopQuery).visible(() -> canvas.isQuerying()); buttons.button("@ok", Icon.ok, canvas::placeQuery).visible(() -> canvas.isQuerying()); } From 21d6494923972f91d27b7ff66a6bcb841dd5815e Mon Sep 17 00:00:00 2001 From: Arthur Schifano Date: Sat, 18 Apr 2026 16:20:25 +0200 Subject: [PATCH 05/42] Adding the ctrl-c ctrl-v copy for keyboard device. The behaviour changed in some small ways. --- core/assets/bundles/bundle.properties | 2 +- .../mindustry/editor/MapObjectivesDialog.java | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index e125fe06e8..fc82f9bfbd 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -803,7 +803,7 @@ error.io = Network I/O error. error.any = Unknown network error. error.bloom = Failed to initialize bloom.\nYour device may not support it. error.moddex = Mindustry is unable to load this mod.\nYour device is blocking import of Java mods due to recent changes in Android.\nThis will not be fixed. There is no known workaround for this issue. -error.objectivecopy = No copied objective. +error.objectivecopy = Invalid copy. weather.rain.name = Rain weather.snowing.name = Snow diff --git a/core/src/mindustry/editor/MapObjectivesDialog.java b/core/src/mindustry/editor/MapObjectivesDialog.java index bc239643cf..10bb2b2dbf 100644 --- a/core/src/mindustry/editor/MapObjectivesDialog.java +++ b/core/src/mindustry/editor/MapObjectivesDialog.java @@ -3,6 +3,8 @@ package mindustry.editor; import arc.*; import arc.func.*; import arc.graphics.*; +import arc.input.*; +import arc.math.*; import arc.math.geom.*; import arc.scene.event.*; import arc.scene.ui.*; @@ -14,6 +16,7 @@ import mindustry.content.*; import mindustry.ctype.*; import mindustry.game.*; import mindustry.game.MapObjectives.*; +import mindustry.editor.MapObjectivesCanvas.ObjectiveTilemap.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.io.*; @@ -554,6 +557,58 @@ public class MapObjectivesDialog extends BaseDialog{ out.get(canvas.objectives); out = arr -> {}; }); + + update(() -> { + if(hasKeyboard()){ + doInput(); + } + }); + } + + private void doInput(){ + if(Core.input.keyDown(KeyCode.controlLeft) || Core.input.keyDown(KeyCode.controlRight)){ + if(Core.input.keyTap(KeyCode.c)){ + Vec2 pos = screenToLocalCoordinates(Core.input.mouse()); + canvas.pasteX = Mathf.round((pos.x - canvas.objWidth * canvas.unitSize / 2f) / canvas.unitSize); + canvas.pasteY = Mathf.floor((pos.y - canvas.unitSize) / canvas.unitSize); + boolean copied = false; + Tmp.r1.set(canvas.pasteX, canvas.pasteY, 1, 1).grow(-0.001f); + for(var obj : canvas.objectives){ + if(Tmp.r2.set(obj.editorX - 2, obj.editorY - 1, canvas.objWidth, canvas.objHeight).overlaps(Tmp.r1)){ + copied = true; + canvas.pasteX = obj.editorX; + canvas.pasteY = obj.editorY; + } + } + + if(!copied){ + ui.showErrorMessage("@error.objectivecopy"); + } + } + } + + if(Core.input.keyDown(KeyCode.controlLeft) || Core.input.keyDown(KeyCode.controlRight)){ + if(Core.input.keyTap(KeyCode.v)){ + copy = null; + Core.app.setClipboardText(JsonIO.write(new MapObjectives(canvas.objectives))); + for(var obj : JsonIO.read(MapObjectives.class, Core.app.getClipboardText()).all){ + if(obj.editorX == canvas.pasteX && obj.editorY == canvas.pasteY){ + copy = obj; + } + }; + Vec2 pos = screenToLocalCoordinates(Core.input.mouse()); + int tx = Mathf.round((pos.x - canvas.objWidth * canvas.unitSize / 2f) / canvas.unitSize); + int ty = Mathf.floor((pos.y - canvas.unitSize) / canvas.unitSize); + if(copy == null || !canvas.tilemap.validPlace(tx, ty, null)){ + ui.showErrorMessage("@error.objectivecopy"); + }else{ + copy.editorX = tx; + copy.editorY = ty; + canvas.tilemap.createTile(tx, ty, copy, true); + canvas.objectives.add(copy); + } + } + } } public void show(Seq objectives, Cons> out){ From 3b4c78ca4ab4f973810dd0159e6886a076f728e4 Mon Sep 17 00:00:00 2001 From: Arthur Schifano Date: Sat, 18 Apr 2026 22:54:27 +0200 Subject: [PATCH 06/42] Patched a bug where when changing editor you could still copy a previous objective, leading to reference issue --- core/src/mindustry/editor/MapObjectivesDialog.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/editor/MapObjectivesDialog.java b/core/src/mindustry/editor/MapObjectivesDialog.java index 10bb2b2dbf..4cc001b987 100644 --- a/core/src/mindustry/editor/MapObjectivesDialog.java +++ b/core/src/mindustry/editor/MapObjectivesDialog.java @@ -42,8 +42,6 @@ public class MapObjectivesDialog extends BaseDialog{ /** Maps annotation type with its field parsers. Non-annotated fields are mapped with {@link Override}. */ private static final ObjectMap, ObjectMap, FieldInterpreter>> interpreters = new ObjectMap<>(); - private MapObjective copy = null; - static{ // Default un-annotated field interpreters. setProvider(String.class, (type, cons) -> cons.get("")); @@ -526,6 +524,7 @@ public class MapObjectivesDialog extends BaseDialog{ if(mobile){ buttons.button("@editor.paste", Icon.paste, () -> { + MapObjective copy = null; Core.app.setClipboardText(JsonIO.write(new MapObjectives(canvas.objectives))); for(var obj : JsonIO.read(MapObjectives.class, Core.app.getClipboardText()).all){ if(obj.editorX == canvas.pasteX && obj.editorY == canvas.pasteY){ @@ -589,7 +588,7 @@ public class MapObjectivesDialog extends BaseDialog{ if(Core.input.keyDown(KeyCode.controlLeft) || Core.input.keyDown(KeyCode.controlRight)){ if(Core.input.keyTap(KeyCode.v)){ - copy = null; + MapObjective copy = null; Core.app.setClipboardText(JsonIO.write(new MapObjectives(canvas.objectives))); for(var obj : JsonIO.read(MapObjectives.class, Core.app.getClipboardText()).all){ if(obj.editorX == canvas.pasteX && obj.editorY == canvas.pasteY){ From 7f7117187e1c97d3a310079bdf03a7ed53c3a06a Mon Sep 17 00:00:00 2001 From: Arthur Schifano Date: Sat, 18 Apr 2026 22:57:50 +0200 Subject: [PATCH 07/42] The global variable was still needed, for the button. --- core/src/mindustry/editor/MapObjectivesDialog.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/editor/MapObjectivesDialog.java b/core/src/mindustry/editor/MapObjectivesDialog.java index 4cc001b987..30264d5774 100644 --- a/core/src/mindustry/editor/MapObjectivesDialog.java +++ b/core/src/mindustry/editor/MapObjectivesDialog.java @@ -42,6 +42,8 @@ public class MapObjectivesDialog extends BaseDialog{ /** Maps annotation type with its field parsers. Non-annotated fields are mapped with {@link Override}. */ private static final ObjectMap, ObjectMap, FieldInterpreter>> interpreters = new ObjectMap<>(); + private MapObjective copy = null; + static{ // Default un-annotated field interpreters. setProvider(String.class, (type, cons) -> cons.get("")); @@ -524,7 +526,7 @@ public class MapObjectivesDialog extends BaseDialog{ if(mobile){ buttons.button("@editor.paste", Icon.paste, () -> { - MapObjective copy = null; + copy = null; Core.app.setClipboardText(JsonIO.write(new MapObjectives(canvas.objectives))); for(var obj : JsonIO.read(MapObjectives.class, Core.app.getClipboardText()).all){ if(obj.editorX == canvas.pasteX && obj.editorY == canvas.pasteY){ @@ -588,7 +590,7 @@ public class MapObjectivesDialog extends BaseDialog{ if(Core.input.keyDown(KeyCode.controlLeft) || Core.input.keyDown(KeyCode.controlRight)){ if(Core.input.keyTap(KeyCode.v)){ - MapObjective copy = null; + copy = null; Core.app.setClipboardText(JsonIO.write(new MapObjectives(canvas.objectives))); for(var obj : JsonIO.read(MapObjectives.class, Core.app.getClipboardText()).all){ if(obj.editorX == canvas.pasteX && obj.editorY == canvas.pasteY){ From 6ce1a323aba63c999fdde11c2b5fc805642f65c1 Mon Sep 17 00:00:00 2001 From: buthed010203 Date: Wed, 19 Aug 2026 12:45:07 -0400 Subject: [PATCH 08/42] Fix preview generation leaking buildings into world (#12511) This wasn't ever noticed before but now that world logic can do crazy stuff, it causes a lot of issues. --- core/src/mindustry/io/MapIO.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/io/MapIO.java b/core/src/mindustry/io/MapIO.java index aa1e1aab3e..03d5cb5ec3 100644 --- a/core/src/mindustry/io/MapIO.java +++ b/core/src/mindustry/io/MapIO.java @@ -97,7 +97,7 @@ public class MapIO{ public void setBlock(Block type){ //do not super.setBlock as that affects the current world this.block = type; - this.build = type.newBuilding().init(this, this.team(), block.update && !state.isEditor(), 0); + this.build = type.newBuilding().init(this, this.team(), false, 0); int c = colorFor(type, Blocks.air, Blocks.air, team()); if(c != black){ walls.setRaw(x, floors.height - 1 - y, c); From f5d06edefc6f0ed22d9e0ac6a08ebb6337961940 Mon Sep 17 00:00:00 2001 From: Kaleinova <160325865+Kaleinova@users.noreply.github.com> Date: Thu, 20 Aug 2026 00:45:23 +0800 Subject: [PATCH 09/42] Add armor value access to Block and BuildingComp (#12510) --- core/src/mindustry/entities/comp/BuildingComp.java | 1 + core/src/mindustry/world/Block.java | 1 + 2 files changed, 2 insertions(+) diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index bc69046b3c..5363fac8db 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -2121,6 +2121,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, case powerNetOut -> power == null ? 0 : power.graph.getLastScaledPowerOut() * 60; case powerNetStored -> power == null ? 0 : power.graph.getLastPowerStored(); case powerNetCapacity -> power == null ? 0 : power.graph.getLastCapacity(); + case armor -> block.armor; case enabled -> enabled ? 1 : 0; case controlled -> this instanceof ControlBlock c && c.isControlled() ? GlobalVars.ctrlPlayer : 0; case payloadCount -> (getPayloads() != null ? getPayloads().total() : 0) + (getPayload() != null ? 1 : 0); diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index 1da5264d6b..583d9532a8 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -1664,6 +1664,7 @@ public class Block extends UnlockableContent implements Senseable{ return switch(sensor){ case color -> mapColor.toDoubleBits(); case health, maxHealth -> health; + case armor -> armor; case solid -> solid ? 1 : 0; case size -> size; case itemCapacity -> itemCapacity; From 7517d89964710d350df1b965c337fb02aff16238 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 19 Aug 2026 18:48:54 +0200 Subject: [PATCH 10/42] Fixed #12509 --- core/src/mindustry/mod/DataPatcher.java | 3 +++ core/src/mindustry/world/blocks/payloads/PayloadSource.java | 4 ++-- core/src/mindustry/world/blocks/sandbox/ItemSource.java | 2 +- core/src/mindustry/world/blocks/sandbox/LiquidSource.java | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/core/src/mindustry/mod/DataPatcher.java b/core/src/mindustry/mod/DataPatcher.java index a5c3fb17b3..9b5a5e0041 100644 --- a/core/src/mindustry/mod/DataPatcher.java +++ b/core/src/mindustry/mod/DataPatcher.java @@ -327,6 +327,9 @@ public class DataPatcher{ for(var block : Vars.content.blocks()){ //don't waste time resizing arrays for blocks that can't use them if(!block.synthetic()) continue; + if(block.lastConfig instanceof Content c && c.removed){ + block.lastConfig = null; + } block.checkContentArrayCapacity(items, liquids); } diff --git a/core/src/mindustry/world/blocks/payloads/PayloadSource.java b/core/src/mindustry/world/blocks/payloads/PayloadSource.java index 8df89f7e03..3456152c4d 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadSource.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadSource.java @@ -87,11 +87,11 @@ public class PayloadSource extends PayloadBlock{ } public boolean canProduce(Block b){ - return b.isVisible() && b.size < size && !(b instanceof CoreBlock) && !state.rules.isBanned(b) && b.environmentBuildable(); + return !b.removed && b.isVisible() && b.size < size && !(b instanceof CoreBlock) && !state.rules.isBanned(b) && b.environmentBuildable(); } public boolean canProduce(UnitType t){ - return !t.isHidden() && !t.isBanned() && t.supportsEnv(state.rules.env); + return !t.removed && !t.isHidden() && !t.isBanned() && t.supportsEnv(state.rules.env); } public class PayloadSourceBuild extends PayloadBlockBuild{ diff --git a/core/src/mindustry/world/blocks/sandbox/ItemSource.java b/core/src/mindustry/world/blocks/sandbox/ItemSource.java index 9fd37b4d9f..59b006bb3e 100644 --- a/core/src/mindustry/world/blocks/sandbox/ItemSource.java +++ b/core/src/mindustry/world/blocks/sandbox/ItemSource.java @@ -31,7 +31,7 @@ public class ItemSource extends Block{ drawCached = true; drawDynamic = false; - config(Item.class, (ItemSourceBuild tile, Item item) -> tile.outputItem = item); + config(Item.class, (ItemSourceBuild tile, Item item) -> tile.outputItem = item.removed ? null : item); configClear((ItemSourceBuild tile) -> tile.outputItem = null); } diff --git a/core/src/mindustry/world/blocks/sandbox/LiquidSource.java b/core/src/mindustry/world/blocks/sandbox/LiquidSource.java index 224539af1e..fe2998d05f 100644 --- a/core/src/mindustry/world/blocks/sandbox/LiquidSource.java +++ b/core/src/mindustry/world/blocks/sandbox/LiquidSource.java @@ -34,7 +34,7 @@ public class LiquidSource extends Block{ envEnabled = Env.any; clearOnDoubleTap = true; - config(Liquid.class, (LiquidSourceBuild tile, Liquid l) -> tile.source = l); + config(Liquid.class, (LiquidSourceBuild tile, Liquid l) -> tile.source = l.removed ? null :l); configClear((LiquidSourceBuild tile) -> tile.source = null); } From 727dacf9bbe4267b86fa975dd195d643555625df Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 19 Aug 2026 21:13:42 +0200 Subject: [PATCH 11/42] Fixed #12512 --- core/src/mindustry/entities/comp/BuildingComp.java | 2 +- core/src/mindustry/type/UnitType.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 5363fac8db..6c62046eea 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1650,7 +1650,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, if(net.active() && lastAccessed != null){ table.row(); - table.add(Core.bundle.format("lastaccessed", lastAccessed)).growX().wrap().left(); + table.add(Core.bundle.format("lastaccessed", lastAccessed)).width(260f).wrap().left(); } table.marginBottom(-5); diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 90f9cfe1c4..6c9808d72d 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -740,11 +740,11 @@ public class UnitType extends UnlockableContent implements Senseable{ table.label(() -> Iconc.settings + " " + (long)unit.flag + "").color(Color.lightGray).growX().wrap().left(); if(net.active() && ai.controller != null && ai.controller.lastAccessed != null){ table.row(); - table.add(Core.bundle.format("lastaccessed", ai.controller.lastAccessed)).growX().wrap().left(); + table.add(Core.bundle.format("lastaccessed", ai.controller.lastAccessed)).width(260f).wrap().left(); } }else if(net.active() && unit.lastCommanded != null){ table.row(); - table.add(Core.bundle.format("lastcommanded", unit.lastCommanded)).growX().wrap().left(); + table.add(Core.bundle.format("lastcommanded", unit.lastCommanded)).width(260f).wrap().left(); } table.row(); From 872e967a1219cb043b4c55e80261d0570e1e64d6 Mon Sep 17 00:00:00 2001 From: buthed010203 Date: Thu, 20 Aug 2026 03:42:27 -0400 Subject: [PATCH 12/42] Fix PlacementFragment at large ui scales. (#12515) --- core/src/mindustry/ui/fragments/PlacementFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/ui/fragments/PlacementFragment.java b/core/src/mindustry/ui/fragments/PlacementFragment.java index 038ae010aa..164e4f61e3 100644 --- a/core/src/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/mindustry/ui/fragments/PlacementFragment.java @@ -691,7 +691,7 @@ public class PlacementFragment{ t.row(); control.input.buildPlacementUI(t); }).name("inputTable").growX(); - }).fillY().bottom().touchable(Touchable.enabled); + }).growX().fillY().bottom().touchable(Touchable.enabled); blockCatTable.table(categories -> { categories.bottom(); categories.add(new Image(Styles.black6){ From 3086ea6ecf1067ebdcf1ee51467c25bc07b6c6e2 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 20 Aug 2026 09:43:04 +0200 Subject: [PATCH 13/42] Fixed save load text wrapping --- core/src/mindustry/ui/dialogs/LoadDialog.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/mindustry/ui/dialogs/LoadDialog.java b/core/src/mindustry/ui/dialogs/LoadDialog.java index 0642c12f1a..aeaddaef2d 100644 --- a/core/src/mindustry/ui/dialogs/LoadDialog.java +++ b/core/src/mindustry/ui/dialogs/LoadDialog.java @@ -92,7 +92,7 @@ public class LoadDialog extends BaseDialog{ Seq array = control.saves.getSaveSlots(); array.sort((slot, other) -> -Long.compare(slot.getTimestamp(), other.getTimestamp())); - int maxwidth = Math.max((int)(Core.graphics.getWidth() / Scl.scl(470)), 1); + int cols = Math.max((int)(Core.graphics.getWidth() / Scl.scl(470)), 1); int i = 0; boolean any = false; @@ -166,7 +166,7 @@ public class LoadDialog extends BaseDialog{ button.table(meta -> { meta.left().top(); - meta.defaults().padBottom(-2).left().width(290f); + meta.defaults().padBottom(-2).left().width(280f); meta.row(); meta.labelWrap(Core.bundle.format("save.map", color + (slot.getMap() == null ? Core.bundle.get("unknown") : slot.getMap().name()))); meta.row(); @@ -178,12 +178,12 @@ public class LoadDialog extends BaseDialog{ meta.row(); meta.labelWrap(color + slot.getDate()); meta.row(); - }).left().growX().width(250f); + }).left().growX().width(260f); modifyButton(button, slot); slots.add(button).uniformX().fillX().pad(4).padRight(8f).margin(10f); - if(++i % maxwidth == 0){ + if(++i % cols == 0){ slots.row(); } } From 0194398a812dee4a35eae5e6da6726cc224fe302 Mon Sep 17 00:00:00 2001 From: Anuken Date: Sat, 22 Aug 2026 05:04:38 -0400 Subject: [PATCH 14/42] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 5e5f902a98..e713a10011 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -43,17 +43,17 @@ body: id: mods attributes: label: Mods used - description: The mod repositories or zip files that are related to the issue, if applicable. + description: The mod repositories or zip files that are related to the issue, if applicable. If you are positive that you have none enabled, write 'none'. validations: - required: false + required: true - type: textarea id: save-file attributes: label: Save file description: The (zipped) save file you were playing on when the bug happened. If this happened in the campaign, specify the sector, and attach the file you get from Settings -> Game Data -> Export Data. For custom games, attach the .msav file exported from the save dialog, zipped. - placeholder: THIS IS REQUIRED FOR ANY ISSUE HAPPENING IN-GAME OR IN MULTIPLAYER, REGARDLESS OF WHETHER YOU THINK IT HAPPENS EVERYWHERE. DO NOT OMIT THIS LINE UNLESS YOU ARE SURE THAT THE ISSUE DOES NOT HAPPEN IN-GAME. IF YOU DO NOT HAVE A SAVE, DON'T WASTE TIME OPENING THIS ISSUE. + placeholder: THIS IS REQUIRED FOR ANY IN-GAME ISSUE. IF YOU DO NOT HAVE A SAVE, DO NOT WASTE TIME OPENING THIS ISSUE. validations: - required: false + required: true - type: textarea id: logs attributes: @@ -72,5 +72,9 @@ body: required: true - label: I have searched the closed and open issues to make sure that this problem has not already been reported. required: true - - label: "I am not using Foo's Client, and have made sure the bug is not caused by mods I have installed." + - label: "I am not using Foo's Client." + required: true + - label: "This issue occurs with no mods enabled." + required: true + - label: "I have attached a valid save file." required: true From 27ba9d7cd22fc70dc0d4fe41fdfd24e909c6466c Mon Sep 17 00:00:00 2001 From: MCxzfwq Date: Mon, 24 Aug 2026 15:10:18 +0800 Subject: [PATCH 15/42] Call afterDestroyed method on build in destroyed() (#12525) --- core/src/mindustry/world/blocks/payloads/BuildPayload.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/mindustry/world/blocks/payloads/BuildPayload.java b/core/src/mindustry/world/blocks/payloads/BuildPayload.java index 9cf0c9e830..22d1b21bff 100644 --- a/core/src/mindustry/world/blocks/payloads/BuildPayload.java +++ b/core/src/mindustry/world/blocks/payloads/BuildPayload.java @@ -60,6 +60,7 @@ public class BuildPayload implements Payload{ public void destroyed(){ build.dead = true; build.onDestroyed(); + build.afterDestroyed(); } @Override From 82ac6a98a5fc43b11b7719bec5af3196c7c83c62 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 26 Aug 2026 09:36:24 -0400 Subject: [PATCH 16/42] Fixed 'escelating' objective typo in existing saves --- core/src/mindustry/game/MapObjectives.java | 4 +++- gradle.properties | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/mindustry/game/MapObjectives.java b/core/src/mindustry/game/MapObjectives.java index b4b6313b36..901456cda9 100644 --- a/core/src/mindustry/game/MapObjectives.java +++ b/core/src/mindustry/game/MapObjectives.java @@ -563,7 +563,9 @@ public class MapObjectives implements Iterable, Eachable Date: Wed, 26 Aug 2026 15:00:48 -0400 Subject: [PATCH 17/42] Removed camera sensors from non-privileged logic --- core/src/mindustry/logic/LAccess.java | 9 ++++++++- core/src/mindustry/logic/LExecutor.java | 3 +-- core/src/mindustry/logic/LStatements.java | 3 ++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/core/src/mindustry/logic/LAccess.java b/core/src/mindustry/logic/LAccess.java index 4173784ef2..cbd7d55eb8 100644 --- a/core/src/mindustry/logic/LAccess.java +++ b/core/src/mindustry/logic/LAccess.java @@ -87,12 +87,19 @@ public enum LAccess{ public final String[] params; public final boolean isObj; + public static final EnumSet privilegedAccess = EnumSet.of(cameraX, cameraY, cameraWidth, cameraHeight); + public static final LAccess[] all = values(), - senseable = Seq.select(all, t -> t.params.length <= 1).toArray(LAccess.class), + senseable = Seq.select(all, t -> t.params.length <= 1 && !t.isPrivileged()).toArray(LAccess.class), + senseablePrivileged = Seq.select(all, t -> t.params.length <= 1).toArray(LAccess.class), controls = Seq.select(all, t -> t.params.length > 0).toArray(LAccess.class), settable = {x, y, velocityX, velocityY, rotation, speed, armor, health, shield, team, flag, totalPower, payloadType, bulletTime, bulletLifetime}; + public boolean isPrivileged(){ + return privilegedAccess.contains(this); + } + LAccess(String... params){ this.params = params; isObj = false; diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index 52531cdbe5..f841393981 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -31,7 +31,6 @@ import mindustry.world.blocks.environment.*; import mindustry.world.blocks.logic.*; import mindustry.world.blocks.logic.LogicBlock.*; import mindustry.world.blocks.logic.LogicDisplay.*; -import mindustry.world.blocks.logic.MessageBlock.*; import mindustry.world.blocks.payloads.*; import mindustry.world.meta.*; @@ -694,7 +693,7 @@ public class LExecutor{ if(sense instanceof Content co){ to.setnum(se.sense(co)); return; - }else if(sense instanceof LAccess la){ + }else if(sense instanceof LAccess la && (exec.privileged || !la.isPrivileged())){ Object objOut = se.senseObject(la); if(objOut == Senseable.noSensed){ diff --git a/core/src/mindustry/logic/LStatements.java b/core/src/mindustry/logic/LStatements.java index 3681c2e08c..ae20899d5c 100644 --- a/core/src/mindustry/logic/LStatements.java +++ b/core/src/mindustry/logic/LStatements.java @@ -629,7 +629,8 @@ public class LStatements{ }), //sensors new Table(i -> { - for(LAccess sensor : LAccess.senseable){ + boolean currentPrivileged = ui.logic.isShown() && ui.logic.privileged; + for(LAccess sensor : (currentPrivileged ? LAccess.senseablePrivileged : LAccess.senseable)){ i.button(sensor.name(), Styles.flatt, () -> { stype("@" + sensor.name()); hide.run(); From 7ecd2f424940ee2fd77676a2d40324be242fd007 Mon Sep 17 00:00:00 2001 From: EggleEgg <125359838+EggleEgg@users.noreply.github.com> Date: Wed, 26 Aug 2026 21:06:22 +0200 Subject: [PATCH 18/42] Qol: .info descriptions to unit weapons (#12527) --- core/src/mindustry/world/meta/StatValues.java | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/core/src/mindustry/world/meta/StatValues.java b/core/src/mindustry/world/meta/StatValues.java index 2c6598cf48..451c0b909d 100644 --- a/core/src/mindustry/world/meta/StatValues.java +++ b/core/src/mindustry/world/meta/StatValues.java @@ -559,6 +559,7 @@ public class StatValues{ return table -> { table.row(); for(int i = 0; i < weapons.size; i++){ + int index = i; Weapon weapon = weapons.get(i); if(weapon.flipSprite || !weapon.hasStats(unit)){ @@ -572,6 +573,7 @@ public class StatValues{ w.left().top().defaults().padRight(3).left(); if(region != null && region.found() && weapon.showStatSprite) w.image(region).size(60).scaling(Scaling.bounded).left().top(); w.row(); + tableInfo(w, "unit." + unit.name + ".weapon." + index + ".info"); weapon.addStats(unit, w); }).growX().pad(5).margin(10); @@ -655,17 +657,7 @@ public class StatValues{ if(blockName != null && t instanceof UnlockableContent){ UnlockableContent content = (UnlockableContent) t; - String key = "block." + blockName + "." + content.name + ".info"; - if(Core.bundle.has(key) && !Vars.headless){ - bt.table(desc -> { - desc.image(Icon.info.getRegion()).size(20).color(Color.lightGray).scaling(Scaling.fit).padRight(8).padLeft(12); - desc.add("[lightgray]" + Core.bundle.get(key)); - }); - - bt.row(); - bt.add().height(10f); - bt.row(); - } + tableInfo(bt, "block." + blockName + "." + content.name + ".info"); } if(type.damage > 0 && (type.collides || type.splashDamage <= 0)){ @@ -862,13 +854,18 @@ public class StatValues{ }; } - //for AmmoListValue - private static Cell sep(Table table, String text){ - table.row(); - return table.add(text); + /** Adds an info table with an icon and description key from the bundle */ + private static Cell tableInfo(Table table, String key){ + return table.table(t -> { + if(Core.bundle.has(key) && !Vars.headless){ + t.image(Icon.info.getRegion()).size(20).color(Color.lightGray).scaling(Scaling.fit).padRight(8).padLeft(12); + t.add("[lightgray]" + Core.bundle.get(key)); + t.row().add().height(10f).row(); + } + }); } - //add a note under a value + /** Adds a note under a value */ private static Cell note(Table table, String text){ table.row(); return table.table(t -> { @@ -877,6 +874,12 @@ public class StatValues{ }); } + //for AmmoListValue + private static Cell sep(Table table, String text){ + table.row(); + return table.add(text); + } + //for AmmoListValue private static String ammoStat(float val){ return (val > 0 ? "[stat]+" : "[negstat]") + Strings.autoFixed(val, 1); From d69229a33332946c55f0401cc0a479f274082d30 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 26 Aug 2026 15:17:01 -0400 Subject: [PATCH 19/42] Fixed #12531 --- core/src/mindustry/entities/comp/PayloadComp.java | 15 ++++++++++----- core/src/mindustry/input/InputHandler.java | 3 +++ core/src/mindustry/input/MobileInput.java | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/core/src/mindustry/entities/comp/PayloadComp.java b/core/src/mindustry/entities/comp/PayloadComp.java index 524f72bf4e..0fedb3054b 100644 --- a/core/src/mindustry/entities/comp/PayloadComp.java +++ b/core/src/mindustry/entities/comp/PayloadComp.java @@ -144,6 +144,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{ if(on != null && on.build != null && on.build.team == team && on.build.acceptPayload(on.build, payload)){ Fx.unitDrop.at(on.build); on.build.handlePayload(on.build, payload); + playPayloadDropSound(payload); return true; } @@ -200,12 +201,8 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{ if(!u.isAdded()) u.team.data().updateCount(u.type, -1); u.add(); u.unloaded(); - Sound dropSound = - payload.size() <= 12f ? Sounds.payloadDrop1 : - payload.size() <= 20f ? Sounds.payloadDrop2 : - Sounds.payloadDrop3; - dropSound.at(self(), Mathf.random(0.9f, 1.1f)); Events.fire(new PayloadDropEvent(self(), u)); + playPayloadDropSound(payload); return true; } @@ -232,6 +229,14 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{ return false; } + void playPayloadDropSound(Payload payload){ + Sound dropSound = + payload.size() <= 12f ? Sounds.payloadDrop1 : + payload.size() <= 20f ? Sounds.payloadDrop2 : + Sounds.payloadDrop3; + dropSound.at(self(), Mathf.random(0.9f, 1.1f)); + } + void contentInfo(Table table, float itemSize, float width){ table.clear(); table.top().left(); diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 69b926dba7..f313298f50 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -594,6 +594,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ if(build.block.buildVisibility != BuildVisibility.hidden && build.canPickup() && pay.canPickup(build)){ pay.pickup(build); }else{ + Sounds.payloadPickup.at(unit, Mathf.random(0.9f, 1.1f)); Fx.unitPickup.at(build); build.tile.remove(); } @@ -602,6 +603,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ if(current != null && pay.canPickupPayload(current)){ Payload taken = build.takePayload(); if(taken != null){ + Sounds.payloadPickup.at(unit, Mathf.random(0.9f, 1.1f)); pay.addPayload(taken); Fx.unitPickup.at(build); } @@ -609,6 +611,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } }else if(build != null && onGround){ + Sounds.payloadPickup.at(unit, Mathf.random(0.9f, 1.1f)); Fx.unitPickup.at(build); build.tile.remove(); } diff --git a/core/src/mindustry/input/MobileInput.java b/core/src/mindustry/input/MobileInput.java index 2eee3ca745..5c640c3e17 100644 --- a/core/src/mindustry/input/MobileInput.java +++ b/core/src/mindustry/input/MobileInput.java @@ -1046,7 +1046,7 @@ public class MobileInput extends InputHandler implements GestureListener{ attractDst = 0f; if(unit.within(payloadTarget, 3f * Time.delta)){ - if(payloadTarget instanceof Vec2 && pay.hasPayload()){ + if(pay.hasPayload() && (payloadTarget instanceof Vec2 || (payloadTarget instanceof Building b && b.team == player.team() && b.acceptPayload(b, pay.payloads().peek())))){ //vec -> dropping something tryDropPayload(); }else if(payloadTarget instanceof Building build && build.team == unit.team){ From 7efe3b2ea72003b6848dd5a5f423898a5fb5954f Mon Sep 17 00:00:00 2001 From: DeterMination Date: Fri, 28 Aug 2026 00:12:27 +0800 Subject: [PATCH 20/42] Increase map editor undo history limit (#12536) --- core/src/mindustry/editor/OperationStack.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/mindustry/editor/OperationStack.java b/core/src/mindustry/editor/OperationStack.java index 91bb183457..d971317942 100755 --- a/core/src/mindustry/editor/OperationStack.java +++ b/core/src/mindustry/editor/OperationStack.java @@ -3,7 +3,7 @@ package mindustry.editor; import arc.struct.*; public class OperationStack{ - private static final int maxSize = 10; + private static final int maxSize = 30; private Seq stack = new Seq<>(); private int index = 0; From 428785494d73eb307dfdf219fd3da3a67fd2b360 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 27 Aug 2026 12:31:04 -0400 Subject: [PATCH 21/42] Fixed input handler switch not updating quadtrees --- core/src/mindustry/input/InputHandler.java | 18 ++++++++++-------- gradle.properties | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index f313298f50..e2187aaf03 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -144,15 +144,15 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } }); - Events.on(WorldLoadEvent.class, e -> { - playerPlanTree = new QuadTree<>(new Rect(0f, 0f, world.unitWidth(), world.unitHeight())); - selectPlanTree = new QuadTree<>(new Rect(0f, 0f, world.unitWidth(), world.unitHeight())); - createPlanLists(); - }); + Events.on(WorldLoadEvent.class, e -> initQuadtrees()); - Events.on(ResetEvent.class, e -> { - reset(); - }); + Events.on(ResetEvent.class, e -> reset()); + } + + protected void initQuadtrees(){ + playerPlanTree = new QuadTree<>(new Rect(0f, 0f, world.unitWidth(), world.unitHeight())); + selectPlanTree = new QuadTree<>(new Rect(0f, 0f, world.unitWidth(), world.unitHeight())); + createPlanLists(); } //methods to override @@ -2262,6 +2262,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ config.build(group); planConfig.build(group); } + + initQuadtrees(); } public boolean canShoot(){ diff --git a/gradle.properties b/gradle.properties index 12e92304a0..83956f605c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,4 +26,4 @@ org.gradle.caching=true org.gradle.internal.http.socketTimeout=100000 org.gradle.internal.http.connectionTimeout=100000 android.enableR8.fullMode=false -archash=70e8ffaf30 +archash=42010d0cc4 From b05d9a11f129aba14ee39acb7b4dab83722b010a Mon Sep 17 00:00:00 2001 From: Rylid-Umil <81439905+rylid-umil@users.noreply.github.com> Date: Thu, 27 Aug 2026 09:34:23 -0700 Subject: [PATCH 22/42] Add lifeRnd and extraLife for Weapons and more (#11477) * lifeRnd and extraLife like velocityRnd and extraVelocity but with bullet lifetimes. random is applied before the scaling with scaleLife. * Update contributors * particle aspect ratio system * fix bug * seperate fin and color fin * Update ParticleEffect.java * New Triangle effect i'm trying my best bro * ok i found the bug and i fixed it * bug squashed 2 * addede extraLife and lifeRnd, and extraVelocity for turrets * Okay okay, one last change. --------- Co-authored-by: Anuken --- core/assets/contributors | 5 +- .../entities/effect/ParticleEffect.java | 28 +++++++- .../entities/effect/TriangleEffect.java | 72 +++++++++++++++++++ core/src/mindustry/type/Weapon.java | 13 +++- .../world/blocks/defense/turrets/Turret.java | 13 +++- 5 files changed, 121 insertions(+), 10 deletions(-) create mode 100644 core/src/mindustry/entities/effect/TriangleEffect.java diff --git a/core/assets/contributors b/core/assets/contributors index 3963cd528b..594e62e91b 100644 --- a/core/assets/contributors +++ b/core/assets/contributors @@ -194,8 +194,9 @@ Jovinull Alon 硫缺铅/PyratiteNoLead Space -DeterMination +rylid-umil NeilGreenFly +DeterMination Sunky.MP3G jhonnata.andre -Zaxerf1234 \ No newline at end of file +Zaxerf1234 diff --git a/core/src/mindustry/entities/effect/ParticleEffect.java b/core/src/mindustry/entities/effect/ParticleEffect.java index 66c61b3329..77335fb5b4 100644 --- a/core/src/mindustry/entities/effect/ParticleEffect.java +++ b/core/src/mindustry/entities/effect/ParticleEffect.java @@ -14,8 +14,11 @@ public class ParticleEffect extends Effect{ private static final Rand rand = new Rand(); private static final Vec2 rv = new Vec2(); + /** Particle color. */ public Color colorFrom = Color.white.cpy(), colorTo = Color.white.cpy(); + /** Number of particles created. */ public int particles = 6; + /** If true, the particle's length is set in a random range from 0 to length. */ public boolean randLength = true; /** Gives the effect flipping compatability like casing effects. */ public boolean casingFlip; @@ -24,8 +27,13 @@ public class ParticleEffect extends Effect{ public Interp interp = Interp.linear; /** Particle size interpolation. Null to use interp. */ public @Nullable Interp sizeInterp = null; + /** Particle color interpolation. Null to use interp. */ + public @Nullable Interp colorInterp = null; + /** Offset position of the particle. */ public float offsetX, offsetY; + /** Particle light properties. */ public float lightScl = 2f, lightOpacity = 0.6f; + /** Color of the light each particle emits. */ public @Nullable Color lightColor; //region only @@ -36,12 +44,22 @@ public class ParticleEffect extends Effect{ public float sizeFrom = 2f, sizeTo = 0f; /** Controls the amount of ticks the effect waits before changing size. */ public float sizeChangeStart = 0f; + /** Controls the amount of ticks the effect waits before changing width. */ + public float widthChangeStart = 0f; + /** Controls the amount of ticks the effect waits before changing height. */ + public float heightChangeStart = 0f; /** Whether the rotation adds with the parent */ public boolean useRotation = true; /** Rotation offset. */ public float offset = 0; /** Sprite to draw. */ public String region = "circle"; + /** Particle width and height properties as a ratio of its radius. Does nothing to line particles. */ + public float widthFrom = 1f, widthTo = 1f, heightFrom = 1f, heightTo = 1f; + /** Particle width interpolation. Null to use sizeInterp. */ + public @Nullable Interp widthInterp = null; + /** Particle height interpolation. Null to use sizeInterp. */ + public @Nullable Interp heightInterp = null; //line only public boolean line; @@ -55,6 +73,9 @@ public class ParticleEffect extends Effect{ clip = Math.max(clip, length + Math.max(sizeFrom, sizeTo)); sizeChangeStart = Mathf.clamp(sizeChangeStart, 0f, lifetime); if(sizeInterp == null) sizeInterp = interp; + if(widthInterp == null) widthInterp = sizeInterp; + if(heightInterp == null) heightInterp = sizeInterp; + if(colorInterp == null) colorInterp = interp; } @Override @@ -65,10 +86,13 @@ public class ParticleEffect extends Effect{ int flip = casingFlip ? -Mathf.sign(e.rotation) : 1; float rawfin = e.fin(); float fin = e.fin(interp); + float colFin = e.fin(colorInterp); float rad = sizeInterp.apply(sizeFrom, sizeTo, Mathf.curve(rawfin, sizeChangeStart / lifetime, 1f)) * 2; + float width = rad * (widthInterp.apply(widthFrom, widthTo, Mathf.curve(rawfin, widthChangeStart / lifetime, 1f)) * 2); + float height = rad * (heightInterp.apply(heightFrom, heightTo, Mathf.curve(rawfin, heightChangeStart / lifetime, 1f)) * 2); float ox = e.x + Angles.trnsx(realRotation, offsetX * flip, offsetY), oy = e.y + Angles.trnsy(realRotation, offsetX * flip, offsetY); - Draw.color(colorFrom, colorTo, fin); + Draw.color(colorFrom, colorTo, colFin); Color lightColor = this.lightColor == null ? Draw.getColor() : this.lightColor; if(line){ @@ -91,7 +115,7 @@ public class ParticleEffect extends Effect{ rv.trns(realRotation + rand.range(cone), !randLength ? l : rand.random(l)); float x = rv.x, y = rv.y; - Draw.rect(tex, ox + x, oy + y, rad, rad / tex.ratio(), realRotation + offset + e.time * spin); + Draw.rect(tex, ox + x, oy + y, width, height / tex.ratio(), realRotation + offset + e.time * spin); Drawf.light(ox + x, oy + y, rad * lightScl, lightColor, lightOpacity * Draw.getColorAlpha()); } } diff --git a/core/src/mindustry/entities/effect/TriangleEffect.java b/core/src/mindustry/entities/effect/TriangleEffect.java new file mode 100644 index 0000000000..87e7b1a246 --- /dev/null +++ b/core/src/mindustry/entities/effect/TriangleEffect.java @@ -0,0 +1,72 @@ +package mindustry.entities.effect; + +import arc.*; +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import arc.math.geom.*; +import arc.util.*; +import mindustry.entities.*; +import mindustry.graphics.*; + +/** Creates a triangle with heavily customizable parameters. */ +public class TriangleEffect extends Effect{ + private static final Rand rand = new Rand(); + + /** Triangle color. */ + public Color colorFrom = Color.white.cpy(), colorTo = Color.white.cpy(); + /** Gives the effect flipping compatability like casing effects. */ + public boolean flippable; + /** Triangle position interpolation. Also used as a fallback.*/ + public Interp interp = Interp.linear; + /** Width interpolation. Null to use interp. */ + public @Nullable Interp widthInterp = null; + /** Height interpolation. Null to use interp. */ + public @Nullable Interp heightInterp = null; + /** Triangle color interpolation. Null to use interp. */ + public @Nullable Interp colorInterp = null; + /** Controls the starting and ending positions of the triangle. */ + public float startX = 0, startY = 0, endX = 0, endY = 0; + /** Triangle light properties. */ + public float lightScl = 8f, lightOpacityFrom = 0.6f, lightOpacityTo = 0f; + /** Color of the light the triangle emits. */ + public @Nullable Color lightColor; + + /** Controls the initial and final positions of each point on the triangle. */ + public float widthFrom = 4f, widthTo = 0f, heightFrom = 4f, heightTo = 4f; + /** Whether the rotation adds with the parent */ + public boolean useRotation = true; + /** Spin in degrees/tick. */ + public int spin = 0; + /** Rotation offset. */ + public float offset = 0; + + @Override + public void init(){ + if(widthInterp == null) widthInterp = interp; + if(heightInterp == null) heightInterp = interp; + if(colorInterp == null) colorInterp = interp; + } + + @Override + public void render(EffectContainer e){ + float realRotation = (useRotation ? (flippable ? Math.abs(e.rotation) : e.rotation) : baseRotation); + int flip = flippable ? -Mathf.sign(e.rotation) : 1; + float rawfin = e.fin(); + float colFin = e.fin(interp); + float width = widthInterp.apply(widthFrom, widthTo, Mathf.curve(rawfin, 0, 1f)); + float height = heightInterp.apply(heightFrom, heightTo, Mathf.curve(rawfin, 0, 1f)); + float lightOpac = colorInterp.apply(lightOpacityFrom, lightOpacityTo, Mathf.curve(rawfin, 0, 1f)); + + float cx = interp.apply(startX, endX, Mathf.curve(rawfin, 0, 1f)); + float cy = interp.apply(startY, endY, Mathf.curve(rawfin, 0, 1f)); + Vec2 pos = new Vec2(cx, cy); + pos.rotate(realRotation); + + Draw.color(colorFrom, colorTo, colFin); + Color lightColor = this.lightColor == null ? Draw.getColor() : this.lightColor; + + Drawf.tri(pos.x + e.x, pos.y + e.y, width, height, realRotation + offset + e.time * spin); + Drawf.light(pos.x + e.x, pos.y + e.y, lightScl, lightColor, lightOpac * Draw.getColorAlpha()); + } +} diff --git a/core/src/mindustry/type/Weapon.java b/core/src/mindustry/type/Weapon.java index 04723af66f..9bdd7540fa 100644 --- a/core/src/mindustry/type/Weapon.java +++ b/core/src/mindustry/type/Weapon.java @@ -101,6 +101,10 @@ public class Weapon implements Cloneable{ public float velocityRnd = 0f; /** extra velocity that is added as a fraction */ public float extraVelocity = 0f; + /** fraction of lifetime that is random */ + public float lifeRnd = 0f; + /** extra lifetime that is added as a fraction */ + public float extraLife = 0f; /** The half-radius of the cone in which shooting will start. */ public float shootCone = 5f; /** Cone in which the weapon can rotate relative to its mount. */ @@ -117,8 +121,10 @@ public class Weapon implements Cloneable{ public boolean ignoreRotation = false; /** If true, this weapon cannot be used to attack targets. */ public boolean noAttack = false; - /** min velocity required for this weapon to shoot */ + /** min velocity required for this weapon to shoot. -1 to disable the limit. */ public float minShootVelocity = -1f; + /** max velocity at which this weapon to shoot. -1 to disable the limit. */ + public float maxShootVelocity = -1f; /** should the shoot effects follow the unit (effects need followParent set to true for this to work) */ public boolean parentizeEffects; /** internal value used for alternation - do not change! */ @@ -434,7 +440,7 @@ public class Weapon implements Cloneable{ !(bullet.killShooter && mount.totalShots > 0) && //if the bullet kills the shooter, you should only ever be able to shoot once (!alternate || wasFlipped == flipSprite) && mount.warmup >= minWarmup && //must be warmed up - velLen >= minShootVelocity && //check velocity requirements + velLen >= minShootVelocity && (maxShootVelocity == -1 || velLen <= maxShootVelocity) && //check velocity requirements (mount.reload <= 0.0001f || (alwaysContinuous && mount.bullet == null)) && //reload has to be 0, or it has to be an always-continuous weapon (alwaysShooting || Angles.within(rotate ? mount.rotation : unit.rotation + baseRotation, mount.targetRotation, shootCone)) //has to be within the cone ){ @@ -497,7 +503,8 @@ public class Weapon implements Cloneable{ bulletX = mountX + Angles.trnsx(weaponRotation, this.shootX + xOffset + xSpread, this.shootY + yOffset + ySpread), bulletY = mountY + Angles.trnsy(weaponRotation, this.shootX + xOffset + xSpread, this.shootY + yOffset + ySpread), shootAngle = bulletRotation(unit, mount, bulletX, bulletY) + angleOffset, - lifeScl = bullet.scaleLife ? Mathf.clamp(Mathf.dst(bulletX, bulletY, mount.aimX, mount.aimY) / bullet.range) : 1f, + baseLife = (1f - lifeRnd) + Mathf.random(lifeRnd) + extraLife, + lifeScl = bullet.scaleLife ? baseLife * Mathf.clamp(Mathf.dst(bulletX, bulletY, mount.aimX, mount.aimY) / bullet.range) : baseLife, angle = shootAngle + Mathf.range(inaccuracy + bullet.inaccuracy); Entityc shooter = unit.controller() instanceof MissileAI ai ? ai.shooter : unit; //Pass the missile's shooter down to its bullets diff --git a/core/src/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/mindustry/world/blocks/defense/turrets/Turret.java index c1515b3e38..e48aba0dbe 100644 --- a/core/src/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/mindustry/world/blocks/defense/turrets/Turret.java @@ -58,6 +58,12 @@ public class Turret extends ReloadTurret{ public float inaccuracy = 0f; /** Fraction of bullet velocity that is random. */ public float velocityRnd = 0f; + /** extra velocity that is added as a fraction */ + public float extraVelocity = 0f; + /** fraction of lifetime that is random */ + public float lifeRnd = 0f; + /** extra lifetime that is added as a fraction */ + public float extraLife = 0f; /** Fraction of lifetime that is added to bullets with lifeScale. */ public float scaleLifetimeOffset = 0f; /** Maximum angle difference in degrees at which turret will still try to shoot. */ @@ -785,11 +791,12 @@ public class Turret extends ReloadTurret{ bulletX = x + Angles.trnsx(rotation - 90, shootX + xOffset + xSpread, shootY + yOffset), bulletY = y + Angles.trnsy(rotation - 90, shootX + xOffset + xSpread, shootY + yOffset), shootAngle = rotation + angleOffset + Mathf.range(inaccuracy + type.inaccuracy); - - float lifeScl = type.scaleLife ? Mathf.clamp((1 + scaleLifetimeOffset) * Mathf.dst(bulletX, bulletY, targetPos.x, targetPos.y) / type.range, minRange() / type.range, range() / type.range) : 1f; + + float baseLife = (1f - lifeRnd) + Mathf.random(lifeRnd) + extraLife, + lifeScl = type.scaleLife ? Mathf.clamp((baseLife + scaleLifetimeOffset) * Mathf.dst(bulletX, bulletY, targetPos.x, targetPos.y) / type.range, minRange() / type.range, range() / type.range) : baseLife; //TODO aimX / aimY for multi shot turrets? - handleBullet(type.create(this, team, bulletX, bulletY, shootAngle, -1f, (1f - velocityRnd) + Mathf.random(velocityRnd), lifeScl, null, mover, targetPos.x, targetPos.y), xOffset, yOffset, shootAngle - rotation); + handleBullet(type.create(this, team, bulletX, bulletY, shootAngle, -1f, (1f - velocityRnd) + Mathf.random(velocityRnd) + extraVelocity, lifeScl, null, mover, targetPos.x, targetPos.y), xOffset, yOffset, shootAngle - rotation); (shootEffect == null ? type.shootEffect : shootEffect).at(bulletX, bulletY, rotation + angleOffset, type.hitColor); (smokeEffect == null ? type.smokeEffect : smokeEffect).at(bulletX, bulletY, rotation + angleOffset, type.hitColor); From 2ebd5481703db7c28ffce70c6ba9c1af01f651d8 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Thu, 27 Aug 2026 16:37:22 +0000 Subject: [PATCH 23/42] Automatic class mapping and map name update --- core/src/mindustry/mod/ClassMap.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/mindustry/mod/ClassMap.java b/core/src/mindustry/mod/ClassMap.java index 9c769e8378..1cfd5058dd 100644 --- a/core/src/mindustry/mod/ClassMap.java +++ b/core/src/mindustry/mod/ClassMap.java @@ -73,6 +73,7 @@ public class ClassMap{ classes.put("RadialEffect", mindustry.entities.effect.RadialEffect.class); classes.put("SeqEffect", mindustry.entities.effect.SeqEffect.class); classes.put("SoundEffect", mindustry.entities.effect.SoundEffect.class); + classes.put("TriangleEffect", mindustry.entities.effect.TriangleEffect.class); classes.put("WaveEffect", mindustry.entities.effect.WaveEffect.class); classes.put("WrapEffect", mindustry.entities.effect.WrapEffect.class); classes.put("DrawPart", mindustry.entities.part.DrawPart.class); From 0699ae305e24176247126d0bdc9c5b196203c1ff Mon Sep 17 00:00:00 2001 From: WMF <87574232+WMF-Industries@users.noreply.github.com> Date: Thu, 27 Aug 2026 18:44:21 +0200 Subject: [PATCH 24/42] new event:tm: (#11827) --- core/src/mindustry/core/Control.java | 3 +++ core/src/mindustry/core/World.java | 5 +++++ core/src/mindustry/game/EventType.java | 16 ++++++++++++++++ core/src/mindustry/io/SaveIO.java | 5 +++++ .../maps/generators/FileMapGenerator.java | 5 ----- server/src/mindustry/server/ServerControl.java | 2 ++ 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index d8b44c6933..f60f4bf336 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -407,6 +407,7 @@ public class Control implements ApplicationListener, Loadable{ if(playtest) state.playtestingMap = map; state.rules.sector = null; state.rules.editor = false; + Events.fire(new RulesLoadEvent(state.rules)); logic.play(); if(settings.getBool("savecreate") && !world.isInvalidMap() && !playtest){ control.saves.addSave(map.name() + " " + new SimpleDateFormat("MMM dd h:mm", Locale.getDefault()).format(new Date())); @@ -546,6 +547,7 @@ public class Control implements ApplicationListener, Loadable{ }); } }else{ + Events.fire(new RulesLoadEvent(state.rules, true)); state.set(State.playing); reloader.end(); } @@ -580,6 +582,7 @@ public class Control implements ApplicationListener, Loadable{ beforePlay.run(); } + Events.fire(new RulesLoadEvent(state.rules)); logic.play(); control.saves.saveSector(sector); Events.fire(new SectorLaunchEvent(sector)); diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index 306dd569ad..d6dacd1431 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -644,6 +644,11 @@ public class World{ super.end(); } + @Override + public boolean isMap(){ + return true; + } + public void applyFilters(){ Seq filters = map.filters(); diff --git a/core/src/mindustry/game/EventType.java b/core/src/mindustry/game/EventType.java index b10d39748f..5df96c79d0 100644 --- a/core/src/mindustry/game/EventType.java +++ b/core/src/mindustry/game/EventType.java @@ -519,6 +519,22 @@ public class EventType{ } } + /** Called when all rules of the current map are loaded. */ + public static class RulesLoadEvent{ + public final Rules rules; + public final boolean fromSave; + + public RulesLoadEvent(Rules rules){ + this.rules = rules; + this.fromSave = false; + } + + public RulesLoadEvent(Rules rules, boolean fromSave){ + this.rules = rules; + this.fromSave = fromSave; + } + } + /** * Called when block building begins by placing down the ConstructBlock. * The tile's block will nearly always be a ConstructBlock. diff --git a/core/src/mindustry/io/SaveIO.java b/core/src/mindustry/io/SaveIO.java index 8aec7acaef..aac5f642c2 100644 --- a/core/src/mindustry/io/SaveIO.java +++ b/core/src/mindustry/io/SaveIO.java @@ -171,6 +171,11 @@ public class SaveIO{ ver.read(stream, counter, new SaveReadState(context)); Events.fire(new SaveLoadEvent(context.isMap())); + + //this gets handled elsewhere when starting a new game or loading a sector + if(!context.isMap() && !state.isCampaign()){ + Events.fire(new RulesLoadEvent(state.rules, true)); + } }catch(Throwable e){ throw new SaveException(e); }finally{ diff --git a/core/src/mindustry/maps/generators/FileMapGenerator.java b/core/src/mindustry/maps/generators/FileMapGenerator.java index 368ade888e..e9804dd94c 100644 --- a/core/src/mindustry/maps/generators/FileMapGenerator.java +++ b/core/src/mindustry/maps/generators/FileMapGenerator.java @@ -79,11 +79,6 @@ public class FileMapGenerator implements WorldGenerator{ applyFilters(); //no super.end(), don't call world load event twice } - - @Override - public boolean isMap(){ - return true; - } }); world.setGenerating(true); diff --git a/server/src/mindustry/server/ServerControl.java b/server/src/mindustry/server/ServerControl.java index 33a1943f2c..fed3150b81 100644 --- a/server/src/mindustry/server/ServerControl.java +++ b/server/src/mindustry/server/ServerControl.java @@ -552,6 +552,7 @@ public class ServerControl implements ApplicationListener{ try{ world.loadMap(result, result.applyRules(lastMode)); state.rules = result.applyRules(preset); + Events.fire(new RulesLoadEvent(state.rules)); logic.play(); info("Map loaded."); @@ -1386,6 +1387,7 @@ public class ServerControl implements ApplicationListener{ run.run(); state.rules = state.map.applyRules(lastMode); + Events.fire(new RulesLoadEvent(state.rules)); logic.play(); reloader.end(); From e981ce8faf7f250c70b42fb04d59d5cf9e609aef Mon Sep 17 00:00:00 2001 From: Vladislav Suchkov <20380250+murolem@users.noreply.github.com> Date: Fri, 28 Aug 2026 02:44:54 +1000 Subject: [PATCH 25/42] Add more spacing to map objectives (#11790) * add spacing * more line break --------- Co-authored-by: Anuken --- core/src/mindustry/game/MapObjectives.java | 16 ++++++++-------- core/src/mindustry/ui/fragments/HudFragment.java | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/src/mindustry/game/MapObjectives.java b/core/src/mindustry/game/MapObjectives.java index 901456cda9..db871aa96c 100644 --- a/core/src/mindustry/game/MapObjectives.java +++ b/core/src/mindustry/game/MapObjectives.java @@ -309,7 +309,7 @@ public class MapObjectives implements Iterable, Eachable, Eachable, Eachable, Eachable, Eachable, Eachable, Eachable, Eachable Date: Thu, 27 Aug 2026 16:46:49 +0000 Subject: [PATCH 26/42] Automatic class mapping and map name update --- core/assets/scripts/global.js | 1 + 1 file changed, 1 insertion(+) diff --git a/core/assets/scripts/global.js b/core/assets/scripts/global.js index ddc0386510..12280b5098 100755 --- a/core/assets/scripts/global.js +++ b/core/assets/scripts/global.js @@ -172,6 +172,7 @@ const BuildSelectEvent = Packages.mindustry.game.EventType.BuildSelectEvent const BuildRotateEvent = Packages.mindustry.game.EventType.BuildRotateEvent const BlockBuildEndEvent = Packages.mindustry.game.EventType.BlockBuildEndEvent const BlockBuildBeginEvent = Packages.mindustry.game.EventType.BlockBuildBeginEvent +const RulesLoadEvent = Packages.mindustry.game.EventType.RulesLoadEvent const ResearchEvent = Packages.mindustry.game.EventType.ResearchEvent const UnlockEvent = Packages.mindustry.game.EventType.UnlockEvent const StateChangeEvent = Packages.mindustry.game.EventType.StateChangeEvent From 02dea62c26597f4559a30de2ceb17d82a1c29f8e Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 27 Aug 2026 18:45:38 -0400 Subject: [PATCH 27/42] Fixed #12539 --- core/src/mindustry/world/meta/StatValues.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/core/src/mindustry/world/meta/StatValues.java b/core/src/mindustry/world/meta/StatValues.java index 451c0b909d..4c47305ed6 100644 --- a/core/src/mindustry/world/meta/StatValues.java +++ b/core/src/mindustry/world/meta/StatValues.java @@ -7,7 +7,6 @@ import arc.graphics.g2d.*; import arc.math.*; import arc.scene.*; import arc.scene.event.*; -import arc.scene.style.*; import arc.scene.ui.*; import arc.scene.ui.Tooltip.*; import arc.scene.ui.layout.*; @@ -655,13 +654,13 @@ public class StatValues{ bt.row(); } - if(blockName != null && t instanceof UnlockableContent){ - UnlockableContent content = (UnlockableContent) t; - tableInfo(bt, "block." + blockName + "." + content.name + ".info"); + if(blockName != null && t != null){ + tableInfo(bt, "block." + blockName + "." + t.name + ".info"); + bt.row(); } if(type.damage > 0 && (type.collides || type.splashDamage <= 0)){ - bt.add(Core.bundle.format("bullet.damage", type.damage) + (type.continuousDamage() > 0 ? + bt.add(Core.bundle.format("bullet.damage", type.damage) + (type.continuousDamage() > 0 ? "[lightgray] ~ [stat]" + Core.bundle.format("bullet.damage", type.continuousDamage()) + StatUnit.perSecond.localized() : "")); } @@ -732,7 +731,7 @@ public class StatValues{ Strings.autoFixed(b.timeDuration / 60f, 1)) + " " + StatUnit.seconds.localized()); } if(b.timeDuration > 0f && b.powerSclDecrease < 1f){ - sep(bt, Core.bundle.format("bullet.empslowdown", + sep(bt, Core.bundle.format("bullet.empslowdown", (b.powerSclDecrease < 1f ? "[negstat]" : "") + Strings.autoFixed((b.powerSclDecrease - 1f) * 100f, 2), Strings.autoFixed(b.timeDuration / 60f, 1)) + " " + StatUnit.seconds.localized()); } From 77e2ce727453c3d7abf7d0310a55abef15b73bca Mon Sep 17 00:00:00 2001 From: ZenthXSin <13437823821@163.com> Date: Sat, 29 Aug 2026 04:50:14 +0800 Subject: [PATCH 28/42] Fix mod browser null listing crash (#12546) * Fix mod browser null listing crash * Fix lambda capture after null list fallback --- core/src/mindustry/ui/dialogs/ModBrowserDialog.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/ui/dialogs/ModBrowserDialog.java b/core/src/mindustry/ui/dialogs/ModBrowserDialog.java index 523393780f..a4362700c8 100644 --- a/core/src/mindustry/ui/dialogs/ModBrowserDialog.java +++ b/core/src/mindustry/ui/dialogs/ModBrowserDialog.java @@ -93,7 +93,8 @@ public class ModBrowserDialog extends BaseDialog{ String strResult = response.getResultAsString(); try{ - Seq mods = json.fromJson(Seq.class, ModListing.class, strResult); + Seq parsed = json.fromJson(Seq.class, ModListing.class, strResult); + Seq mods = parsed == null ? new Seq<>() : parsed; var d = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); Func parser = text -> { From 332cd6d118926ec1ef0eb468083dc45acf39a8b3 Mon Sep 17 00:00:00 2001 From: EggleEgg <125359838+EggleEgg@users.noreply.github.com> Date: Fri, 28 Aug 2026 22:50:32 +0200 Subject: [PATCH 29/42] some adjustments for #12527 just in case (#12540) --- core/src/mindustry/world/meta/StatValues.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/core/src/mindustry/world/meta/StatValues.java b/core/src/mindustry/world/meta/StatValues.java index 4c47305ed6..07b991c067 100644 --- a/core/src/mindustry/world/meta/StatValues.java +++ b/core/src/mindustry/world/meta/StatValues.java @@ -855,12 +855,10 @@ public class StatValues{ /** Adds an info table with an icon and description key from the bundle */ private static Cell tableInfo(Table table, String key){ + if(!Core.bundle.has(key)) return null; return table.table(t -> { - if(Core.bundle.has(key) && !Vars.headless){ - t.image(Icon.info.getRegion()).size(20).color(Color.lightGray).scaling(Scaling.fit).padRight(8).padLeft(12); - t.add("[lightgray]" + Core.bundle.get(key)); - t.row().add().height(10f).row(); - } + if(!Vars.headless) t.image(Icon.info.getRegion()).size(20).color(Color.lightGray).scaling(Scaling.fit).padRight(8).padLeft(12); + t.add("[lightgray]" + Core.bundle.get(key)).padBottom(10f); }); } From 84b3c3d8094d0599d8082a013a3bf100ea4abf68 Mon Sep 17 00:00:00 2001 From: EggleEgg <125359838+EggleEgg@users.noreply.github.com> Date: Fri, 28 Aug 2026 22:50:57 +0200 Subject: [PATCH 30/42] Account for liquid heat when extinguishing + more (#11664) * Account for liquid heat when extinguishing + more * always keep at least 1 * use a gamerule instead * team changer gamerule * typo + rename * use baseteams e340'ri3490turgw4 --- core/assets/bundles/bundle.properties | 2 + .../entities/abilities/ShieldArcAbility.java | 4 +- .../entities/bullet/LiquidBulletType.java | 2 +- core/src/mindustry/game/Rules.java | 2 + .../ui/dialogs/CustomRulesDialog.java | 1 + .../world/blocks/storage/CoreBlock.java | 60 ++++++++++++++++++- 6 files changed, 66 insertions(+), 5 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index ed67f3a7de..af2bac4ec7 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1611,6 +1611,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reactor Explosions rules.coreincinerates = Core Incinerates Overflow +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Disable World Processors rules.schematic = Schematics Allowed rules.wavetimer = Wave Timer diff --git a/core/src/mindustry/entities/abilities/ShieldArcAbility.java b/core/src/mindustry/entities/abilities/ShieldArcAbility.java index 188783f6e7..7da8364473 100644 --- a/core/src/mindustry/entities/abilities/ShieldArcAbility.java +++ b/core/src/mindustry/entities/abilities/ShieldArcAbility.java @@ -95,7 +95,7 @@ public class ShieldArcAbility extends Ability{ paramField.data -= unit.health() * paramField.missileUnitMultiplier * Vars.state.rules.unitDamage(unit.team); paramField.alpha = 1f; - }else if(paramField.pushUnits && !(!unit.isFlying() && paramUnit.isFlying())){ + }else if(paramField.pushUnits && (paramField.pushDiffLayer || paramUnit.isFlying() == unit.isFlying())){ float reach = paramField.radius + paramField.width; float overlapDst = reach - unit.dst(paramPos); @@ -158,6 +158,8 @@ public class ShieldArcAbility extends Ability{ public boolean offsetRegion = false; /** If true, enemy units are pushed out. */ public boolean pushUnits = true; + /** If pushUnits is true, allow ground units to push air or air units to push ground */ + public boolean pushDiffLayer = true; public Effect pushEffect = Fx.circleColorSpark; /** State. */ diff --git a/core/src/mindustry/entities/bullet/LiquidBulletType.java b/core/src/mindustry/entities/bullet/LiquidBulletType.java index 98769d4a11..eabcfbd3f9 100644 --- a/core/src/mindustry/entities/bullet/LiquidBulletType.java +++ b/core/src/mindustry/entities/bullet/LiquidBulletType.java @@ -96,7 +96,7 @@ public class LiquidBulletType extends BulletType{ Puddles.deposit(world.tileWorld(hitx, hity), liquid, puddleSize); if(liquid.temperature <= 0.5f && liquid.flammability < 0.3f){ - float intensity = 400f * puddleSize/6f; + float intensity = 400f * (liquid.heatCapacity / 0.4f) * (puddleSize / 6f); Fires.extinguish(world.tileWorld(hitx, hity), intensity); for(Point2 p : Geometry.d4){ Fires.extinguish(world.tileWorld(hitx + p.x * tilesize, hity + p.y * tilesize), intensity); diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index ba9ffcaa83..4cb2dc0397 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -25,6 +25,8 @@ public class Rules{ public boolean allowEditRules = false; /** Sandbox mode: Enables infinite resources, build range and build speed. */ public boolean infiniteResources; + /** Allow building and deconstructing cores anywhere, as well as showing ui to change teams */ + public boolean coreBuildAndConfig = false; /** Team-specific rules. */ public TeamRules teams = new TeamRules(); /** Whether the waves come automatically on a timer. If not, waves come when the play button is pressed. */ diff --git a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java index 5185927536..4de9925fcf 100644 --- a/core/src/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/mindustry/ui/dialogs/CustomRulesDialog.java @@ -164,6 +164,7 @@ public class CustomRulesDialog extends BaseDialog{ category("resourcesbuilding"); check("@rules.alloweditworldprocessors", b -> rules.allowEditWorldProcessors = b, () -> rules.allowEditWorldProcessors); check("@rules.infiniteresources", b -> rules.infiniteResources = b, () -> rules.infiniteResources); + check("@rules.corebuildandconfig", b -> rules.coreBuildAndConfig = b, () -> rules.coreBuildAndConfig); check("@rules.onlydepositcore", b -> rules.onlyDepositCore = b, () -> rules.onlyDepositCore); check("@rules.coreunloaders", b -> rules.allowCoreUnloaders = b, () -> rules.allowCoreUnloaders); check("@rules.derelictrepair", b -> rules.derelictRepair = b, () -> rules.derelictRepair); diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 19ff222da8..0c726491e4 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -171,7 +171,8 @@ public class CoreBlock extends StorageBlock{ @Override public boolean canBreak(Tile tile){ - return state.isEditor(); + //always keep at least 1 core to not lose the save + return state.isEditor() || (state.rules.coreBuildAndConfig && tile.block() instanceof CoreBlock && state.teams.cores(tile.team()).size > 1); } @Override @@ -183,8 +184,8 @@ public class CoreBlock extends StorageBlock{ @Override public boolean canPlaceOn(Tile tile, Team team, int rotation){ if(tile == null) return false; - //in the editor, you can place them anywhere for convenience - if(state.isEditor()) return true; + //in the editor or with gamerule, you can place them anywhere for convenience + if(state.isEditor() || state.rules.coreBuildAndConfig) return true; CoreBuild core = team.core(); @@ -283,6 +284,57 @@ public class CoreBlock extends StorageBlock{ return block.unloadable && state.rules.allowCoreUnloaders; } + @Override + public void buildConfiguration(Table table){ + if(!state.rules.coreBuildAndConfig) return; + + ButtonGroup group = new ButtonGroup<>(); + group.setMinCheckCount(0); + Table cont = new Table(); + cont.defaults().size(32f); + + int i = 0; + for(Team team : Team.baseTeams){ + ImageButton button = cont.button(Tex.whiteui, Styles.clearTogglei, 24f, () -> { + }).group(group).get(); + button.changed(() -> { + if(button.isChecked()){ + configure(team.id); + } + }); + button.getStyle().imageUpColor = team.color; + button.update(() -> button.setChecked(this.team == team)); + + if(i++ % 3 == 2){ + cont.row(); + } + } + + ScrollPane pane = new ScrollPane(cont, Styles.smallPane); + pane.setScrollingDisabled(true, false); + pane.setOverscroll(false, false); + table.add(pane).maxHeight(Scl.scl(40f * 2f)).left(); + table.row(); + } + + @Override + public void configured(@Nullable Unit builder, @Nullable Object value){ + super.configured(builder, value); + if(!state.rules.coreBuildAndConfig || !(value instanceof Integer)) return; + + Team next = Team.get((int)value); + if(builder != null && builder.isPlayer()){ + builder.team(next); + builder.getPlayer().team(next); + } + changeTeam(next); + } + + @Override + public boolean shouldHideConfigure(Player player){ + return !state.rules.coreBuildAndConfig; + } + @Override public void draw(){ //draw thrusters when just landed @@ -532,6 +584,7 @@ public class CoreBlock extends StorageBlock{ @Override public void created(){ super.created(); + block.configurable = state.rules.coreBuildAndConfig; Events.fire(new CoreChangeEvent(this)); } @@ -591,6 +644,7 @@ public class CoreBlock extends StorageBlock{ @Override public void updateTile(){ + block.configurable = state.rules.coreBuildAndConfig; iframes -= Time.delta; thrusterTime -= Time.delta/90f; } From 756439ce660bd7dbca5188ea81831bef3f3630b0 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Fri, 28 Aug 2026 20:51:52 +0000 Subject: [PATCH 31/42] Automatic bundle update --- core/assets/bundles/bundle_be.properties | 2 ++ core/assets/bundles/bundle_bg.properties | 2 ++ core/assets/bundles/bundle_ca.properties | 2 ++ core/assets/bundles/bundle_cs.properties | 2 ++ core/assets/bundles/bundle_da.properties | 2 ++ core/assets/bundles/bundle_de.properties | 2 ++ core/assets/bundles/bundle_es.properties | 2 ++ core/assets/bundles/bundle_et.properties | 2 ++ core/assets/bundles/bundle_eu.properties | 2 ++ core/assets/bundles/bundle_fi.properties | 2 ++ core/assets/bundles/bundle_fil.properties | 2 ++ core/assets/bundles/bundle_fr.properties | 2 ++ core/assets/bundles/bundle_hu.properties | 2 ++ core/assets/bundles/bundle_id_ID.properties | 2 ++ core/assets/bundles/bundle_it.properties | 2 ++ core/assets/bundles/bundle_ja.properties | 2 ++ core/assets/bundles/bundle_ko.properties | 2 ++ core/assets/bundles/bundle_lt.properties | 2 ++ core/assets/bundles/bundle_nl.properties | 2 ++ core/assets/bundles/bundle_nl_BE.properties | 2 ++ core/assets/bundles/bundle_pl.properties | 2 ++ core/assets/bundles/bundle_pt_BR.properties | 2 ++ core/assets/bundles/bundle_pt_PT.properties | 2 ++ core/assets/bundles/bundle_ro.properties | 2 ++ core/assets/bundles/bundle_ru.properties | 2 ++ core/assets/bundles/bundle_sr.properties | 2 ++ core/assets/bundles/bundle_sv.properties | 2 ++ core/assets/bundles/bundle_th.properties | 2 ++ core/assets/bundles/bundle_tk.properties | 2 ++ core/assets/bundles/bundle_tr.properties | 2 ++ core/assets/bundles/bundle_uk_UA.properties | 2 ++ core/assets/bundles/bundle_vi.properties | 2 ++ core/assets/bundles/bundle_zh_CN.properties | 2 ++ core/assets/bundles/bundle_zh_TW.properties | 2 ++ 34 files changed, 68 insertions(+) diff --git a/core/assets/bundles/bundle_be.properties b/core/assets/bundles/bundle_be.properties index d876f1a24f..c25d6ae4c3 100644 --- a/core/assets/bundles/bundle_be.properties +++ b/core/assets/bundles/bundle_be.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Калі ўключана, разгрузчыкі з rules.derelictrepair = Дазволіць рамантаваць пакінутыя блокі rules.reactorexplosions = Выбухі рэактараў rules.coreincinerates = Ядро Спальвае Рэсурсы +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Адключыць сусветныя працэсары rules.schematic = Схемы Дазволены rules.wavetimer = Інтэрвал хваляў diff --git a/core/assets/bundles/bundle_bg.properties b/core/assets/bundles/bundle_bg.properties index 9725ecd569..bd834e5f82 100644 --- a/core/assets/bundles/bundle_bg.properties +++ b/core/assets/bundles/bundle_bg.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Когато е включено, разтоварв rules.derelictrepair = Разрешете поправянето на изоставени блокове rules.reactorexplosions = Експлозивни реактори rules.coreincinerates = Унищожаване на ресурси при преливане +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Изключване на процесорите за света rules.schematic = Позволена употребата на схеми rules.wavetimer = Таймер за Вълни diff --git a/core/assets/bundles/bundle_ca.properties b/core/assets/bundles/bundle_ca.properties index a2ff91149c..b30bf548eb 100644 --- a/core/assets/bundles/bundle_ca.properties +++ b/core/assets/bundles/bundle_ca.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Si s’activa, els descarregadors de Serpulo podran t rules.derelictrepair = Permet la reparació dels blocs en ruïnes rules.reactorexplosions = Explosions als reactors rules.coreincinerates = El nucli incinera els excedents +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Desactiva els processadors integrats rules.schematic = Permetre l’ús d’esquemes rules.wavetimer = Temporitzador d’onades diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index 2b0886e15f..9969e95d8b 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Pokud je zapnuto, vykladače na Serpulu mohou brát p rules.derelictrepair = Povolit opravu opuštěných bloků rules.reactorexplosions = Výbuch reaktoru rules.coreincinerates = Jádro Spaluje Nadbytečné Suroviny +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Zakázat Světové Procesory rules.schematic = Šablony povoleny rules.wavetimer = Časovač vln diff --git a/core/assets/bundles/bundle_da.properties b/core/assets/bundles/bundle_da.properties index e3955a1d69..c29e18e5a6 100644 --- a/core/assets/bundles/bundle_da.properties +++ b/core/assets/bundles/bundle_da.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reaktor-eksplosioner rules.coreincinerates = Core Incinerates Overflow +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Disable World Processors rules.schematic = Skabeloner tilladt rules.wavetimer = Bølge-æggeur diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index 126e784519..d2763c1ebe 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reaktor-Explosionen rules.coreincinerates = Kern verbrennt überflüssige Materialien +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Deaktiviere Weltprozessoren rules.schematic = Entwürfe erlaubt rules.wavetimer = Wellen-Timer diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index 1915cc493a..a8551d838a 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Cuando está activado, Los descargadores de Serpulo p rules.derelictrepair = Permitir reparar bloques abandonados rules.reactorexplosions = Explosiones de reactores rules.coreincinerates = Incinerar exceso de recursos en el núcleo +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Desactivar procesadores estáticos rules.schematic = Permitir esquemas rules.wavetimer = Temporizador de oleadas diff --git a/core/assets/bundles/bundle_et.properties b/core/assets/bundles/bundle_et.properties index 7d1af41ce2..ffa3e0cac3 100644 --- a/core/assets/bundles/bundle_et.properties +++ b/core/assets/bundles/bundle_et.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reactor Explosions rules.coreincinerates = Core Incinerates Overflow +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Disable World Processors rules.schematic = Schematics Allowed rules.wavetimer = Kasuta taimerit diff --git a/core/assets/bundles/bundle_eu.properties b/core/assets/bundles/bundle_eu.properties index 49fa09b9bf..4884b19833 100644 --- a/core/assets/bundles/bundle_eu.properties +++ b/core/assets/bundles/bundle_eu.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Baimendu bloke abandonatuen konponketa rules.reactorexplosions = Erreaktorearen eztandak rules.coreincinerates = Nukleoen erraustegien gainezkatzea +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Munduko prozesadoreak desgaitu rules.schematic = Onartutako eskemak rules.wavetimer = Boladen denboragailua diff --git a/core/assets/bundles/bundle_fi.properties b/core/assets/bundles/bundle_fi.properties index 9c356ac094..d7bf29cb84 100644 --- a/core/assets/bundles/bundle_fi.properties +++ b/core/assets/bundles/bundle_fi.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reaktorien räjähtäminen rules.coreincinerates = Ydin höyrystää ylivuodon +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Poista maailmaprosessorit käytöstä rules.schematic = Salli kaaviot rules.wavetimer = Tasojen aikaraja diff --git a/core/assets/bundles/bundle_fil.properties b/core/assets/bundles/bundle_fil.properties index 4c0666bb4e..d95665e2df 100644 --- a/core/assets/bundles/bundle_fil.properties +++ b/core/assets/bundles/bundle_fil.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reactor Explosions rules.coreincinerates = Core Incinerates Overflow +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Disable World Processors rules.schematic = Schematics Allowed rules.wavetimer = Wave Timer diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index a2d2ad5449..65231a9ddb 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Lorsque cette option est activée, les déchargeurs d rules.derelictrepair = Autoriser la réparation des structures abandonnées rules.reactorexplosions = Explosion des Réacteurs rules.coreincinerates = Incinération des surplus du Noyau +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Désactiver les Processeurs Globaux rules.schematic = Schémas autorisés rules.wavetimer = Compte à rebours des vagues diff --git a/core/assets/bundles/bundle_hu.properties b/core/assets/bundles/bundle_hu.properties index db33e236c0..50e13d100b 100644 --- a/core/assets/bundles/bundle_hu.properties +++ b/core/assets/bundles/bundle_hu.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Ha engedélyezve van, akkor a Serpulo kirakodói nyer rules.derelictrepair = Elhagyatott épületek javításának engedélyezése rules.reactorexplosions = Reaktorrobbanások rules.coreincinerates = Többletnyersanyagok megsemmisítése a támaszpontban +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Világprocesszorok letiltása rules.schematic = Vázlatok engedélyezése rules.wavetimer = Hullámok időzítése diff --git a/core/assets/bundles/bundle_id_ID.properties b/core/assets/bundles/bundle_id_ID.properties index ded42ddc12..1c03b0450b 100644 --- a/core/assets/bundles/bundle_id_ID.properties +++ b/core/assets/bundles/bundle_id_ID.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Saat diaktifkan, pembongkar Serpulo dapat membongkar rules.derelictrepair = Izinkan Perbaikan Blok Derelik rules.reactorexplosions = Ledakan Reaktor rules.coreincinerates = Penghangusan Luapan Inti +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Nonaktifkan Prosesor Dunia rules.schematic = Skematik Diperbolehkan rules.wavetimer = Pengaturan Waktu Gelombang diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index ae915b85cc..c1d0292bc3 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Esplosioni Reattore rules.coreincinerates = Core Incinerates Overflow +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Disabilita processori rules.schematic = Schematiche Consentite rules.wavetimer = Timer Ondate diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties index 4a207a130f..2418813099 100644 --- a/core/assets/bundles/bundle_ja.properties +++ b/core/assets/bundles/bundle_ja.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = 有効にすると、セルプロの搬出機がコ rules.derelictrepair = 廃墟修復可能 rules.reactorexplosions = リアクターの爆発 rules.coreincinerates = 余剰アイテムの焼却 +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = ワールドプロセッサーを無効にする rules.schematic = 設計図を許可 rules.wavetimer = ウェーブの自動進行 diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 78a4a3c297..e7c6008d66 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = 이 기능을 활성화하면, 세르풀로 언로더 rules.derelictrepair = 잔해 블록 수리 허용 rules.reactorexplosions = 원자로 폭발 허용 rules.coreincinerates = 코어에 특정 자원량 초과 시 자동 소각 허용 +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = 월드 프로세서 비활성화 rules.schematic = 설계도 허용 rules.wavetimer = 시간 제한이 있는 단계 diff --git a/core/assets/bundles/bundle_lt.properties b/core/assets/bundles/bundle_lt.properties index a0f6646485..e41d0b850a 100644 --- a/core/assets/bundles/bundle_lt.properties +++ b/core/assets/bundles/bundle_lt.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reaktorių Sprogimai rules.coreincinerates = Core Incinerates Overflow +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Disable World Processors rules.schematic = Schematics Allowed rules.wavetimer = Bangų Laikmatis diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties index eff578c70d..22bf93b96a 100644 --- a/core/assets/bundles/bundle_nl.properties +++ b/core/assets/bundles/bundle_nl.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Ontploffende Reactors rules.coreincinerates = Core verbrandt overvloed aan materialen. +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Zet Wereld-Processors Uit. rules.schematic = Ontwerpen Toegestaan rules.wavetimer = Vijandelijke Golven Timer diff --git a/core/assets/bundles/bundle_nl_BE.properties b/core/assets/bundles/bundle_nl_BE.properties index 8319a9d499..b945d116de 100644 --- a/core/assets/bundles/bundle_nl_BE.properties +++ b/core/assets/bundles/bundle_nl_BE.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reactor Explosions rules.coreincinerates = Core Incinerates Overflow +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Disable World Processors rules.schematic = Schematics Allowed rules.wavetimer = Wave Timer diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index 344ee771bb..7bdb93e1e7 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Gdy włączone, rozładowywacze Serpulo mogą pobiera rules.derelictrepair = Zezwól na naprawę opuszczonego bloku rules.reactorexplosions = Eksplozje Reaktorów rules.coreincinerates = Rdzeń Spala Nadmiarowe Przedmioty +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Wyłącz Procesor Świata rules.schematic = Zezwalaj na schematy rules.wavetimer = Zegar Fal diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index 0cc61cd07b..dcd7284488 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Quando ativado, descarregadores de Serpulo podem tira rules.derelictrepair = Permitir Reparo de Blocos Abandonados rules.reactorexplosions = Reatores explodem rules.coreincinerates = Núcleo incinera itens em excesso +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Desativar processadores mundiais rules.schematic = Permitir Esquemas rules.wavetimer = Tempo de horda diff --git a/core/assets/bundles/bundle_pt_PT.properties b/core/assets/bundles/bundle_pt_PT.properties index 239d6f4304..b2a3aaeb31 100644 --- a/core/assets/bundles/bundle_pt_PT.properties +++ b/core/assets/bundles/bundle_pt_PT.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Permitir Reparação de Blocos Derelict rules.reactorexplosions = Esploções de Reatores rules.coreincinerates = Núcleo destrói Itens em Excesso +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Desativar Processadores Globais rules.schematic = Esquemas Permitidos rules.wavetimer = Tempo de Horda diff --git a/core/assets/bundles/bundle_ro.properties b/core/assets/bundles/bundle_ro.properties index 720d157cc7..e40eb80383 100644 --- a/core/assets/bundles/bundle_ro.properties +++ b/core/assets/bundles/bundle_ro.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reactoarele Explodează rules.coreincinerates = Nucleul Incinerează Resursele în Plus +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Disable World Processors rules.schematic = Se Pot Folosi Scheme rules.wavetimer = Valuri pe Timp diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index e8051e46b2..029d1ffe57 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = При включении, разгрузчики н rules.derelictrepair = Разрешить починку покинутых построек rules.reactorexplosions = Взрывы реакторов rules.coreincinerates = Ядро сжигает избыток ресурсов +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Отключить мировые процессоры rules.schematic = Разрешить схемы rules.wavetimer = Интервал волн diff --git a/core/assets/bundles/bundle_sr.properties b/core/assets/bundles/bundle_sr.properties index 80ea09311b..f70c4ecc59 100644 --- a/core/assets/bundles/bundle_sr.properties +++ b/core/assets/bundles/bundle_sr.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Eksplozije Reaktora rules.coreincinerates = Core Incinerates Overflow +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Onesposobi Svetovne Procesore rules.schematic = Šeme Su Dozvoljene rules.wavetimer = Talasna Štoperica diff --git a/core/assets/bundles/bundle_sv.properties b/core/assets/bundles/bundle_sv.properties index af2f14fe24..feaaf5d87c 100644 --- a/core/assets/bundles/bundle_sv.properties +++ b/core/assets/bundles/bundle_sv.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reactor Explosions rules.coreincinerates = Core Incinerates Overflow +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Disable World Processors rules.schematic = Schematics Allowed rules.wavetimer = Vågtimer diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties index ba8497325a..a58165f364 100644 --- a/core/assets/bundles/bundle_th.properties +++ b/core/assets/bundles/bundle_th.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = เมื่อเปิดใช้งาน ตั rules.derelictrepair = อนุญาตการซ่อมแซมบล็อกทิ้งร้าง rules.reactorexplosions = เปิดการระเบิดของเตาปฏิกร rules.coreincinerates = แกนกลางเผาทรัพยากรส่วนเกิน +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = ปิดการทำงานของตัวประมวลผลโลก rules.schematic = อนุญาตให้ใช้แผนผัง rules.wavetimer = นับถอยหลังการปล่อยคลื่น diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index 25560f64a5..fb27359a0f 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = When enabled, Serpulo unloaders can take items from t rules.derelictrepair = Allow Derelict Block Repair rules.reactorexplosions = Reactor Explosions rules.coreincinerates = Core Incinerates Overflow +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Disable World Processors rules.schematic = Schematics Allowed rules.wavetimer = Wave Timer diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 2abe5bb221..1c781be1ef 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Aktifken, Serpulo Boşaltıcıları Merkezden malzeme rules.derelictrepair = Kalıntıları Tamir Etmeye İzin Ver rules.reactorexplosions = Reaktör Patlamaları rules.coreincinerates = Merkez Taşanları Eritir +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Evrensel İşlemcileri Devredışı Bırak rules.schematic = Şema Kullanılabilir rules.wavetimer = Dalga Zamanlayıcısı diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index d3d2dd9b80..27124d4484 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Якщо увімкнено, розвантажува rules.derelictrepair = Дозволити відновлення будівель Переможених rules.reactorexplosions = Вибухи реактора rules.coreincinerates = Ядро спалює надлишкові предмети +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Вимкнути світові процесори rules.schematic = Використання схем дозволено rules.wavetimer = Таймер для хвиль diff --git a/core/assets/bundles/bundle_vi.properties b/core/assets/bundles/bundle_vi.properties index 1d3db8035f..2f8d46d020 100644 --- a/core/assets/bundles/bundle_vi.properties +++ b/core/assets/bundles/bundle_vi.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = Khi bật, điểm dỡ hàng của Serpulo có thể rules.derelictrepair = Cho Phép Sửa Khối Bỏ Hoang rules.reactorexplosions = Nổ Nò Phản Ứng rules.coreincinerates = Hủy Vật Phẩm Khi Lõi Đầy +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = Vô Hiệu Hoá Bộ Xử Lý Thế Giới rules.schematic = Cho Phép Dùng Bản Thiết Kế rules.wavetimer = Đếm Ngược Đợt diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index 2dc46579a4..a87eaf80ef 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = 当启用时,塞普罗的装卸器可以从核心 rules.derelictrepair = 允许修复残骸建筑 rules.reactorexplosions = 允许反应堆爆炸 rules.coreincinerates = 核心焚烧溢出资源 +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = 禁用世界处理器 rules.schematic = 允许使用蓝图 rules.wavetimer = 波次计时器 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index 4582cc34c8..0850ad4de0 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -1606,6 +1606,8 @@ rules.coreunloaders.info = 開啟後,裝卸器可從核心提取物資。\n不 rules.derelictrepair = 允許修復殘骸建築 rules.reactorexplosions = 反應爐爆炸 rules.coreincinerates = 核心銷毀物品 +rules.corebuildandconfig = Deconstruct And Configure Cores +rules.corebuildandconfig.info = Allows building and deconstructing cores anywhere, not just on core zones.\nAlso shows ui on cores to change player team. rules.disableworldprocessors = 停用世界處理器 rules.schematic = 允許使用藍圖 rules.wavetimer = 波次時間 From e6b66673a35379968ff910cdd3fbe46568d390d6 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 28 Aug 2026 16:54:22 -0400 Subject: [PATCH 32/42] Fixed #12543 --- core/src/mindustry/entities/comp/BuildingComp.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 6c62046eea..9854892781 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1836,6 +1836,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, if(was){ indexer.addIndex(tile); Events.fire(teamChangeEvent.set(last, self())); + pathfinder.updateTile(tile); } checkAllowUpdate(); From 3f65bdd38302a9454aefb74716fa72f93d6fdd32 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 28 Aug 2026 17:04:22 -0400 Subject: [PATCH 33/42] Fixed #12541 --- core/src/mindustry/core/World.java | 24 ++++++++++++++++++++++++ core/src/mindustry/entities/Damage.java | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index d6dacd1431..47a3b46ab4 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -555,6 +555,30 @@ public class World{ } } + public static void raycastEachNoDiagonalWorld(float x0, float y0, float x1, float y1, Raycaster cons){ + raycastEachNoDiagonal(toTile(x0), toTile(y0), toTile(x1), toTile(y1), cons); + } + + public static void raycastEachNoDiagonal(int startX, int startY, int endX, int endY, Raycaster cons){ + int xDist = Math.abs(endX - startX); + int yDist = -Math.abs(endY - startY); + int xStep = (startX < endX ? +1 : -1); + int yStep = (startY < endY ? +1 : -1); + int error = xDist + yDist; + + while(true){ + if(cons.accept(startX, startY) || (startX == endX && startY == endY)) break; + + if(2 * error - yDist > xDist - 2 * error){ + error += yDist; + startX += xStep; + }else{ + error += xDist; + startY += yStep; + } + } + } + public static boolean raycast(int x1, int y1, int x2, int y2, Raycaster cons){ int x = x1, dx = Math.abs(x2 - x), sx = x < x2 ? 1 : -1; int y = y1, dy = Math.abs(y2 - y), sy = y < y2 ? 1 : -1; diff --git a/core/src/mindustry/entities/Damage.java b/core/src/mindustry/entities/Damage.java index 61bc01c95a..c836cdc58a 100644 --- a/core/src/mindustry/entities/Damage.java +++ b/core/src/mindustry/entities/Damage.java @@ -263,7 +263,7 @@ public class Damage{ if(hitter.type.collidesGround && hitter.type.collidesTiles){ seg1.set(x, y); seg2.set(seg1).add(vec); - World.raycastEachWorld(x, y, seg2.x, seg2.y, (cx, cy) -> { + World.raycastEachNoDiagonalWorld(x, y, seg2.x, seg2.y, (cx, cy) -> { Building tile = world.build(cx, cy); boolean collide = tile != null && tile.collide(hitter) && hitter.checkUnderBuild(tile, cx * tilesize, cy * tilesize) && ((tile.team != team && tile.collide(hitter)) || hitter.type.testCollision(hitter, tile)) && collidedBlocks.add(tile.pos()); From e2cecffec3d1eae80f8f88832a4c44d8c0446d43 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 28 Aug 2026 17:18:43 -0400 Subject: [PATCH 34/42] Fixed #12544 --- core/src/mindustry/entities/comp/BuildingComp.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 9854892781..d12460c799 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -1837,6 +1837,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, indexer.addIndex(tile); Events.fire(teamChangeEvent.set(last, self())); pathfinder.updateTile(tile); + updateProximity(); } checkAllowUpdate(); From 5112fb9a0e079f9b98e2dd0681d53b0b59c10cd9 Mon Sep 17 00:00:00 2001 From: Pyratite No Lead <62745850+woodjecket@users.noreply.github.com> Date: Sat, 29 Aug 2026 05:19:08 +0800 Subject: [PATCH 35/42] Update Simplified Chinese Translation (#12545) * Update Simplified Chinese Translation * Fix typo * Update Simplified Chinese Translation * Update Simplified Chinese Translation * Update Simplified Chinese Translation --- core/assets/bundles/bundle_zh_CN.properties | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index a87eaf80ef..b3381086d1 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -1833,8 +1833,8 @@ unit.renale.name = Renale block.parallax.name = 差扰 block.cliff.name = 悬崖 -block.sand-boulder.name = 砂岩 -block.basalt-boulder.name = 玄武岩石块 +block.sand-boulder.name = 砂岩块 +block.basalt-boulder.name = 玄武岩块 block.grass.name = 草地 block.molten-slag.name = 矿渣液 block.pooled-cryofluid.name = 冷冻液 @@ -1847,10 +1847,10 @@ block.sand-wall.name = 沙墙 block.spore-pine.name = 孢子树 block.spore-wall.name = 孢子墙 block.boulder.name = 石块 -block.snow-boulder.name = 雪石块 +block.snow-boulder.name = 雪岩块 block.snow-pine.name = 雪树 block.shale.name = 页岩地 -block.shale-boulder.name = 页岩石块 +block.shale-boulder.name = 页岩块 block.moss.name = 苔藓地 block.shrubs.name = 灌木丛 block.spore-moss.name = 孢子苔藓地 @@ -1888,7 +1888,7 @@ block.char.name = 焦土 block.dacite.name = 安山岩 block.rhyolite.name = 流纹岩 block.dacite-wall.name = 安山岩墙 -block.dacite-boulder.name = 安山石块 +block.dacite-boulder.name = 安山岩块 block.ice-snow.name = 冰雪地 block.stone-wall.name = 石墙 block.ice-wall.name = 冰墙 @@ -2385,7 +2385,7 @@ onset.enemies = 敌人来袭,准备防御。 onset.defenses = [accent]建立防御:[lightgray] {0} onset.attack = 敌军基地十分脆弱。发动反攻。 onset.cores = 你可以在[accent]核心地块[]上建造新的核心。\n新核心的功能类似于前沿基地,且与其他核心共享资源仓库。\n放置一个 :core-bastion: 核心。 -onset.detect = 敌军将在两分钟内发现你。\n设立防御,挖掘矿物,并建造生产设施。 +onset.detect = 两分钟后敌人来袭。\n设立防御,挖掘矿物,并建造生产设施。 onset.commandmode = 按住[accent]shift[]键进入[accent]指挥模式[]。\n按住[accent]鼠标左键[]框选单位。\n[accent]右键[]指挥所选单位移动或攻击。 onset.commandmode.mobile = 点击左下角的[accent]指挥[]进入[accent]指挥模式[]。\n按住屏幕,[accent]拖动[]框选单位。\n[accent]点击[]指挥所选单位移动或攻击。 aegis.tungsten = 钨可以使用[accent]冲击钻[]进行开采。\n该结构需要[accent]水[]和[accent]电力[]。 From a1975a40b690a23e6b09ef645ac1f65fcffd095a Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 28 Aug 2026 17:20:40 -0400 Subject: [PATCH 36/42] Do not kill GL context on uiMode Android change --- android/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 78c3080541..874faea21a 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -26,7 +26,7 @@ android:screenOrientation="user" android:exported="true" android:launchMode="singleTask" - android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout"> + android:configChanges="uiMode|keyboard|keyboardHidden|orientation|screenSize|screenLayout"> From db54e4f350e0b50f9083b1930708b141af89feb6 Mon Sep 17 00:00:00 2001 From: EggleEgg <125359838+EggleEgg@users.noreply.github.com> Date: Fri, 28 Aug 2026 23:24:32 +0200 Subject: [PATCH 37/42] requested. Whoever wants this change fight for it. Good luck. (#11846) --- core/src/mindustry/content/Blocks.java | 2 ++ core/src/mindustry/world/blocks/distribution/ItemBridge.java | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 6a9b34de99..400b77ffbd 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -2379,6 +2379,7 @@ public class Blocks{ hasPower = false; liquidCapacity = 100f; explosivenessScale = flammabilityScale = 20f/100f; + noAcceptDisabled = true; }}; phaseConduit = new LiquidBridge("phase-conduit"){{ @@ -2392,6 +2393,7 @@ public class Blocks{ pulse = true; explosivenessScale = flammabilityScale = 20f/100f; liquidCapacity = 100f; + noAcceptDisabled = true; consumePower(0.30f); }}; diff --git a/core/src/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/mindustry/world/blocks/distribution/ItemBridge.java index c13e6f8826..4bfb20e2f0 100644 --- a/core/src/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/mindustry/world/blocks/distribution/ItemBridge.java @@ -36,6 +36,7 @@ public class ItemBridge extends Block{ public float arrowSpacing = 4f, arrowOffset = 2f, arrowPeriod = 0.4f; public float arrowTimeScl = 6.2f; public float bridgeWidth = 6.5f; + public boolean noAcceptDisabled = false; //for autolink public @Nullable ItemBridgeBuild lastBuild; @@ -433,7 +434,7 @@ public class ItemBridge extends Block{ @Override public boolean acceptLiquid(Building source, Liquid liquid){ return - hasLiquids && team == source.team && + hasLiquids && team == source.team && (!noAcceptDisabled || enabled) && (liquids.current() == liquid || liquids.get(liquids.current()) < 0.2f) && checkAccept(source, world.tile(link)); } From c1c4781f229fe703ece83b6fc13b98e35123d236 Mon Sep 17 00:00:00 2001 From: DinoWattz <116862698+DinoWattz@users.noreply.github.com> Date: Fri, 28 Aug 2026 18:25:23 -0300 Subject: [PATCH 38/42] Add missing store localization for Brazilian Portuguese (#11743) * Add steam translations * Add google play translations * Fix typo in achievement's name --- .../android/pt-BR/full_description.txt | 34 ++++ .../android/pt-BR/short_description.txt | 1 + fastlane/metadata/android/pt-BR/summary.txt | 1 + fastlane/metadata/android/pt-BR/title.txt | 1 + .../metadata/steam/brazilian/achievements.vdf | 183 ++++++++++++++++++ .../metadata/steam/brazilian/description.txt | 62 ++++++ .../steam/brazilian/short-description.txt | 1 + 7 files changed, 283 insertions(+) create mode 100644 fastlane/metadata/android/pt-BR/full_description.txt create mode 100644 fastlane/metadata/android/pt-BR/short_description.txt create mode 100644 fastlane/metadata/android/pt-BR/summary.txt create mode 100644 fastlane/metadata/android/pt-BR/title.txt create mode 100644 fastlane/metadata/steam/brazilian/achievements.vdf create mode 100644 fastlane/metadata/steam/brazilian/description.txt create mode 100644 fastlane/metadata/steam/brazilian/short-description.txt diff --git a/fastlane/metadata/android/pt-BR/full_description.txt b/fastlane/metadata/android/pt-BR/full_description.txt new file mode 100644 index 0000000000..5a22fc0619 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/full_description.txt @@ -0,0 +1,34 @@ +Mindustry é um jogo de construção de fábricas com elementos de defesa de torres e estratégia em tempo real. Crie cadeias de suprimento elaboradas para alimentar suas torres com munição, produza materiais para construir e fabricar unidades. Comande tropas para capturar bases inimigas e expanda sua produção. Defenda seu núcleo contra hordas de inimigos. + +

Recursos de Jogabilidade

+ +- Use blocos de produção para criar uma grande variedade de materiais avançados +- Defenda suas estruturas contra hordas de inimigos +- Jogue com seus amigos em partidas cooperativas multijogador entre plataformas ou desafie-os em confrontos PvP por equipes +- Distribua líquidos e enfrente desafios constantes, como incêndios ou ataques de unidades aéreas inimigas +- Tire o máximo da sua produção fornecendo refrigeramento e lubrificante opcionais +- Produza uma ampla variedade de unidades para gerenciar automaticamente sua base ou atacar bases inimigas +- Configure linhas de montagem para construir exércitos de unidades mecanizadas +- Use suas tropas para enfrentar bases inimigas totalmente funcionais + + +

Campanha

+ +- Conquiste os planetas Serpulo e Erekir avançando por 35 mapas feitos à mão e mais de 250 setores gerados proceduralmente +- Capture território e instale fábricas para produzir recursos enquanto joga em outros setores +- Defenda seus setores contra invasões periódicas +- Coordene a distribuição de recursos entre setores por meio de plataformas de lançamento +- Pesquise novos blocos para impulsionar o progresso +- Convide seus amigos para completar missões juntos +- Mais de 250 blocos tecnológicos para dominar +- Mais de 50 tipos diferentes de drones, mechs e naves + + +

Jogos Personalizados e Multijogador Entre Plataformas

+ +- Mais de 16 mapas integrados para jogos personalizados, além de duas campanhas completas +- Jogue em modo cooperativo, PvP ou sandbox +- Entre em um servidor dedicado público ou convide amigos para sua própria sessão privada +- Regras de jogo personalizáveis: altere custos de blocos, estatísticas de inimigos, itens iniciais, tempo das hordas e muito mais +- Editor de mapas totalmente funcional com suporte a scripts +- Navegador de mods integrado e suporte completo a modificações diff --git a/fastlane/metadata/android/pt-BR/short_description.txt b/fastlane/metadata/android/pt-BR/short_description.txt new file mode 100644 index 0000000000..e862d6a550 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/short_description.txt @@ -0,0 +1 @@ +Construa fábricas e defenda seu núcleo com estratégia em tempo real. diff --git a/fastlane/metadata/android/pt-BR/summary.txt b/fastlane/metadata/android/pt-BR/summary.txt new file mode 100644 index 0000000000..e862d6a550 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/summary.txt @@ -0,0 +1 @@ +Construa fábricas e defenda seu núcleo com estratégia em tempo real. diff --git a/fastlane/metadata/android/pt-BR/title.txt b/fastlane/metadata/android/pt-BR/title.txt new file mode 100644 index 0000000000..e2842b447a --- /dev/null +++ b/fastlane/metadata/android/pt-BR/title.txt @@ -0,0 +1 @@ +Mindustry diff --git a/fastlane/metadata/steam/brazilian/achievements.vdf b/fastlane/metadata/steam/brazilian/achievements.vdf new file mode 100644 index 0000000000..f3ca2a8b44 --- /dev/null +++ b/fastlane/metadata/steam/brazilian/achievements.vdf @@ -0,0 +1,183 @@ +"lang" +{ + "Language" "brazilian" + "Tokens" + { + "NEW_ACHIEVEMENT_20_1_NAME" "Sucateiro" + "NEW_ACHIEVEMENT_20_1_DESC" "Destrua 1000 unidades inimigas." + "NEW_ACHIEVEMENT_20_2_NAME" "Expurgação" + "NEW_ACHIEVEMENT_20_2_DESC" "Destrua 100.000 unidades inimigas." + "NEW_ACHIEVEMENT_20_5_NAME" "Transportes Sem Fim" + "NEW_ACHIEVEMENT_20_5_DESC" "Lance 100.000 itens no total." + "NEW_ACHIEVEMENT_20_6_NAME" "Conquistador" + "NEW_ACHIEVEMENT_20_6_DESC" "Vença 10 partidas no modo de ataque." + "NEW_ACHIEVEMENT_20_7_NAME" "Campeão" + "NEW_ACHIEVEMENT_20_7_DESC" "Vença 10 partidas PvP em multijogador." + "NEW_ACHIEVEMENT_20_8_NAME" "Blitz" + "NEW_ACHIEVEMENT_20_8_DESC" "Destrua o núcleo inimigo na zona de ataque em 5 hordas ou menos." + "NEW_ACHIEVEMENT_20_9_NAME" "Chuva de Núcleos" + "NEW_ACHIEVEMENT_20_9_DESC" "Lance seu núcleo 30 vezes." + "NEW_ACHIEVEMENT_20_10_NAME" "Persistente" + "NEW_ACHIEVEMENT_20_10_DESC" "Sobreviva 100 hordas." + "NEW_ACHIEVEMENT_20_12_NAME" "Pesquisador" + "NEW_ACHIEVEMENT_20_12_DESC" "Pesquise tudo." + "NEW_ACHIEVEMENT_20_14_NAME" "Sobrecarga" + "NEW_ACHIEVEMENT_20_14_DESC" "Atinja um inimigo coberto de água com eletricidade." + "NEW_ACHIEVEMENT_20_15_NAME" "Deflexão" + "NEW_ACHIEVEMENT_20_15_DESC" "Destrua uma unidade com sua própria bala refletida." + "NEW_ACHIEVEMENT_20_17_NAME" "Um Erro Grave" + "NEW_ACHIEVEMENT_20_17_DESC" "Pesquise o Roteador." + "NEW_ACHIEVEMENT_20_18_NAME" "Criação" + "NEW_ACHIEVEMENT_20_18_DESC" "Coloque 10.000 blocos." + "NEW_ACHIEVEMENT_20_19_NAME" "Arraso" + "NEW_ACHIEVEMENT_20_19_DESC" "Destrua 1.000 blocos inimigos." + "NEW_ACHIEVEMENT_20_20_NAME" "Um Desastre Espetacular" + "NEW_ACHIEVEMENT_20_20_DESC" "Faça com que um Reator de Tório sobreaqueça e exploda." + "NEW_ACHIEVEMENT_20_21_NAME" "Mapeador" + "NEW_ACHIEVEMENT_20_21_DESC" "Crie um novo mapa 10 vezes." + "NEW_ACHIEVEMENT_20_22_NAME" "Navegador" + "NEW_ACHIEVEMENT_20_22_DESC" "Faça o download de um mapa da Oficina." + "NEW_ACHIEVEMENT_20_23_NAME" "Criador" + "NEW_ACHIEVEMENT_20_23_DESC" "Publique um mapa na Oficina." + "NEW_ACHIEVEMENT_20_24_NAME" "Exterminador" + "NEW_ACHIEVEMENT_20_24_DESC" "Derrote um chefe." + "NEW_ACHIEVEMENT_20_29_NAME" "Material II" + "NEW_ACHIEVEMENT_20_29_DESC" "Desbloqueie Tório." + "NEW_ACHIEVEMENT_20_31_NAME" "Material I" + "NEW_ACHIEVEMENT_20_31_DESC" "Desbloqueie Titânio." + "NEW_ACHIEVEMENT_21_0_NAME" "Kamikaze" + "NEW_ACHIEVEMENT_21_0_DESC" "Encha qualquer unidade, exceto núcleos, com materiais explosivos e morra." + "NEW_ACHIEVEMENT_21_1_NAME" "Assim Começa" + "NEW_ACHIEVEMENT_21_1_DESC" "Construa uma fábrica de unidades terrestres." + "NEW_ACHIEVEMENT_21_2_NAME" "Ofensiva Direta" + "NEW_ACHIEVEMENT_21_2_DESC" "Ordene que qualquer unidade ataque um alvo." + "NEW_ACHIEVEMENT_21_3_NAME" "Enxame" + "NEW_ACHIEVEMENT_21_3_DESC" "Tenha 100 unidades ativas ao mesmo tempo." + "NEW_ACHIEVEMENT_21_4_NAME" "Rebanho" + "NEW_ACHIEVEMENT_21_4_DESC" "Tenha 10 drones Poly ativos ao mesmo tempo." + "NEW_ACHIEVEMENT_21_5_NAME" "Roboticista" + "NEW_ACHIEVEMENT_21_5_DESC" "Construa todos os tipos de unidades." + "NEW_ACHIEVEMENT_21_6_NAME" "Legiões" + "NEW_ACHIEVEMENT_21_6_DESC" "Construa 1000 unidades no total." + "NEW_ACHIEVEMENT_21_9_NAME" "Você Devia Ter Escutado" + "NEW_ACHIEVEMENT_21_9_DESC" "Morra na zona de exclusão do ponto de queda." + "NEW_ACHIEVEMENT_21_10_NAME" "Há Unidades Navais para Isso" + "NEW_ACHIEVEMENT_21_10_DESC" "Afogue." + "NEW_ACHIEVEMENT_21_11_NAME" "Colecionador" + "NEW_ACHIEVEMENT_21_11_DESC" "Encha o núcleo até a capacidade máxima com todos os tipos de materiais." + "NEW_ACHIEVEMENT_21_12_NAME" "Multidão" + "NEW_ACHIEVEMENT_21_12_DESC" "Hospede um servidor com 10 jogadores nele." + "NEW_ACHIEVEMENT_21_13_NAME" "Invulnerável" + "NEW_ACHIEVEMENT_21_13_DESC" "Construa o Meltdown, Spectre e Foreshadow." + "NEW_ACHIEVEMENT_21_14_NAME" "Decolagem" + "NEW_ACHIEVEMENT_21_14_DESC" "Use a Plataforma de Lançamento." + "NEW_ACHIEVEMENT_21_16_NAME" "Heresia" + "NEW_ACHIEVEMENT_21_16_DESC" "Construa dois roteadores próximos um do outro." + "NEW_ACHIEVEMENT_21_17_NAME" "Guardião Solitário" + "NEW_ACHIEVEMENT_21_17_DESC" "Sobreviva 10 hordas em qualquer zona sem colocar qualquer bloco." + "NEW_ACHIEVEMENT_21_18_NAME" "Incineração" + "NEW_ACHIEVEMENT_21_18_DESC" "Use Piratita em qualquer torreta." + "NEW_ACHIEVEMENT_21_19_NAME" "Eficiência" + "NEW_ACHIEVEMENT_21_19_DESC" "Refrigere uma torreta com água ou criofluido." + "NEW_ACHIEVEMENT_21_20_NAME" "Modo Clássico" + "NEW_ACHIEVEMENT_21_20_DESC" "Habilite pixelização." + "NEW_ACHIEVEMENT_21_21_NAME" "Estudioso" + "NEW_ACHIEVEMENT_21_21_DESC" "Abra a Wiki através do jogo." + "NEW_ACHIEVEMENT_21_22_NAME" "Vantagem Inicial" + "NEW_ACHIEVEMENT_21_22_DESC" "Lance-se em uma zona com 10.000 ou mais itens configurados." + "NEW_ACHIEVEMENT_21_23_NAME" "Ignição" + "NEW_ACHIEVEMENT_21_23_DESC" "Ligue um Reator de Impacto." + "NEW_ACHIEVEMENT_21_25_NAME" "A Espiral" + "NEW_ACHIEVEMENT_21_25_DESC" "Gira, gira sem parar..." + "NEW_ACHIEVEMENT_21_26_NAME" "Escalação" + "NEW_ACHIEVEMENT_21_26_DESC" "Construa uma unidade de Tier 5." + "NEW_ACHIEVEMENT_21_27_NAME" "Arquiteto" + "NEW_ACHIEVEMENT_21_27_DESC" "Crie 20 esquemas." + "NEW_ACHIEVEMENT_21_28_NAME" "Dominação Global" + "NEW_ACHIEVEMENT_21_28_DESC" "Capture todos os setores em Serpulo." + "NEW_ACHIEVEMENT_21_29_NAME" "Transporte Aéreo" + "NEW_ACHIEVEMENT_21_29_DESC" "Pegue uma unidade T5 em uma unidade de carga Oct." + "NEW_ACHIEVEMENT_21_30_NAME" "A Forma de Vida Suprema" + "NEW_ACHIEVEMENT_21_30_DESC" "Junte-se a eles." + "NEW_ACHIEVEMENT_21_31_NAME" "Produção I" + "NEW_ACHIEVEMENT_21_31_DESC" "Atinga uma taxa de produção total de 5.000 itens por minuto na campanha." + "NEW_ACHIEVEMENT_26_0_NAME" "Produção II" + "NEW_ACHIEVEMENT_26_0_DESC" "Atinga uma taxa de produção total de 50.000 itens por minuto na campanha." + "NEW_ACHIEVEMENT_26_1_NAME" "Vitória Assegurada" + "NEW_ACHIEVEMENT_26_1_DESC" "Capture um setor enquanto joga em outro." + "NEW_ACHIEVEMENT_26_2_NAME" "Pequeno Império" + "NEW_ACHIEVEMENT_26_2_DESC" "Controle 10 setores de uma vez." + "NEW_ACHIEVEMENT_26_3_NAME" "Designer" + "NEW_ACHIEVEMENT_26_3_DESC" "Crie 500 esquemas." + "NEW_ACHIEVEMENT_26_4_NAME" "Mestre da Distribuição" + "NEW_ACHIEVEMENT_26_4_DESC" "Use todos blocos de transporte (de um planeta) em um único mapa." + "NEW_ACHIEVEMENT_26_5_NAME" "Potência Máxima" + "NEW_ACHIEVEMENT_26_5_DESC" "Construa um Projetor de Sobrecarga." + "NEW_ACHIEVEMENT_26_6_NAME" "Remendo" + "NEW_ACHIEVEMENT_26_6_DESC" "Construa um Projetor de Reparo." + "NEW_ACHIEVEMENT_26_7_NAME" "Ineficiência" + "NEW_ACHIEVEMENT_26_7_DESC" "Construa um Extrator de Água sobre a água, em vez de usar uma bomba." + "NEW_ACHIEVEMENT_26_8_NAME" "Estoque" + "NEW_ACHIEVEMENT_26_8_DESC" "Colete um total de 10 milhões de itens na campanha." + "NEW_ACHIEVEMENT_26_9_NAME" "Contra Tudo e Contra Todos" + "NEW_ACHIEVEMENT_26_9_DESC" "Desfira o golpe final em uma unidade Eclipse com uma torreta Duo." + "NEW_ACHIEVEMENT_26_10_NAME" "Conclusão de Erekir" + "NEW_ACHIEVEMENT_26_10_DESC" "Capture o setor final em Erekir." + "NEW_ACHIEVEMENT_26_11_NAME" "Conclusão de Serpulo" + "NEW_ACHIEVEMENT_26_11_DESC" "Capture o setor final em Serpulo." + "NEW_ACHIEVEMENT_26_12_NAME" "Arsenal" + "NEW_ACHIEVEMENT_26_12_DESC" "Lance-se com um esquema de núcleo personalizado em Serpulo." + "NEW_ACHIEVEMENT_26_13_NAME" "Preparado ao Extremo" + "NEW_ACHIEVEMENT_26_13_DESC" "Aprimore o núcleo em Marco Zero para um Centro do Núcleo." + "NEW_ACHIEVEMENT_26_14_NAME" "Surto" + "NEW_ACHIEVEMENT_26_14_DESC" "Faça neoplasma se espalhar para qualquer bloco que contenha água." + "NEW_ACHIEVEMENT_26_15_NAME" "Quebradiço" + "NEW_ACHIEVEMENT_26_15_DESC" "Cause dano explosivo adicional a uma unidade com o efeito de status Congelamento." + "NEW_ACHIEVEMENT_26_16_NAME" "Maestria em Estruturas de Serpulo" + "NEW_ACHIEVEMENT_26_16_DESC" "Construa todos blocos disponíveis em Serpulo." + "NEW_ACHIEVEMENT_26_17_NAME" "Maestria em Estruturas de Erekir" + "NEW_ACHIEVEMENT_26_17_DESC" "Construa todos blocos disponíveis em Erekir." + "NEW_ACHIEVEMENT_26_18_NAME" "Defesas Rompidas" + "NEW_ACHIEVEMENT_26_18_DESC" "Quebre o escudo de um Projetor de Campo de Força inimigo." + "NEW_ACHIEVEMENT_26_19_NAME" "Onde Está o Manual?" + "NEW_ACHIEVEMENT_26_19_DESC" "Pesquise o microprocessador." + "NEW_ACHIEVEMENT_26_20_NAME" "Apagão" + "NEW_ACHIEVEMENT_26_20_DESC" "Atinga -10.000 de energia por segundo em uma rede." + "NEW_ACHIEVEMENT_26_21_NAME" "Pico de Energia" + "NEW_ACHIEVEMENT_26_21_DESC" "Atinga 100.000 de energia por segundo." + "NEW_ACHIEVEMENT_26_22_NAME" "Alta Capacidade" + "NEW_ACHIEVEMENT_26_22_DESC" "Tenha 1 milhão de energia armazenada em baterias em uma rede." + "NEW_ACHIEVEMENT_26_23_NAME" "Má Ideia" + "NEW_ACHIEVEMENT_26_23_DESC" "Insira composto explosivo em um gerador a combustão." + "NEW_ACHIEVEMENT_26_24_NAME" "Contaminação" + "NEW_ACHIEVEMENT_26_24_DESC" "Faça um Reator de Neoplasia explodir devido ao acúmulo de neoplasma." + "NEW_ACHIEVEMENT_26_25_NAME" "Modificado" + "NEW_ACHIEVEMENT_26_25_DESC" "Instale um mod." + "NEW_ACHIEVEMENT_26_26_NAME" "roteador" + "NEW_ACHIEVEMENT_26_26_DESC" "roteador" + "NEW_ACHIEVEMENT_26_27_NAME" "A Experiência Completa" + "NEW_ACHIEVEMENT_26_27_DESC" "Junte-se a um servidor da comunidade." + "NEW_ACHIEVEMENT_26_28_NAME" "Hackerman" + "NEW_ACHIEVEMENT_26_28_DESC" "Abra o console de scripts." + "NEW_ACHIEVEMENT_26_29_NAME" "Controle Direto" + "NEW_ACHIEVEMENT_26_29_DESC" "Comande manualmente uma torre." + "NEW_ACHIEVEMENT_26_30_NAME" "Em Campo Hostil" + "NEW_ACHIEVEMENT_26_30_DESC" "Ponha unidades dentro da zona proibida de construção do núcleo inimigo." + "NEW_ACHIEVEMENT_26_31_NAME" "Vingança" + "NEW_ACHIEVEMENT_26_31_DESC" "Destrua uma torreta Scatter usando uma unidade Flare." + "NEW_ACHIEVEMENT_29_0_NAME" "Em Voo" + "NEW_ACHIEVEMENT_29_0_DESC" "Use a função de impulso de uma unidade terrestre." + "NEW_ACHIEVEMENT_29_1_NAME" "Aerobarco" + "NEW_ACHIEVEMENT_29_1_DESC" "Use uma unidade Elude para atravessar um líquido." + "NEW_ACHIEVEMENT_29_2_NAME" "Lugar Certo, Hora Certa" + "NEW_ACHIEVEMENT_29_2_DESC" "Aumente a eficiência de uma estrutura ao colocá-la em terrenos específicos." + "NEW_ACHIEVEMENT_29_3_NAME" "Limpeza" + "NEW_ACHIEVEMENT_29_3_DESC" "Quebre 100 rochedos." + "NEW_ACHIEVEMENT_29_4_NAME" "A Faxina Global" + "NEW_ACHIEVEMENT_29_4_DESC" "Quebre 10.000 rochedos." + "NEW_ACHIEVEMENT_29_5_NAME" "Neutralizado" + "NEW_ACHIEVEMENT_29_5_DESC" "Use uma Torre de Onda de Choque para absorver projéteis inimigos." + "NEW_ACHIEVEMENT_29_6_NAME" "Infelizmente," + "NEW_ACHIEVEMENT_29_6_DESC" "Use o emoji :alphachan: no chat multijogador. Ou não, a escolha é sua." + } +} diff --git a/fastlane/metadata/steam/brazilian/description.txt b/fastlane/metadata/steam/brazilian/description.txt new file mode 100644 index 0000000000..88b75052ee --- /dev/null +++ b/fastlane/metadata/steam/brazilian/description.txt @@ -0,0 +1,62 @@ +Mindustry é um jogo de construção de fábricas com elementos de defesa de torres e estratégia em tempo real. Crie cadeias de suprimento elaboradas para alimentar suas torres com munição, produza materiais para construir e fabricar unidades. Comande tropas para capturar bases inimigas e expanda sua produção. Defenda seu núcleo contra hordas de inimigos. + +Jogue a campanha sozinho ou com seus amigos em modo cooperativo multijogador entre plataformas e desafie-os em partidas PvP por equipes. + +[img]{STEAM_APP_IMAGE}/extras/factory.gif[/img] + +[h2]Construção de Fábricas[/h2] + +[list] +[*] Crie cadeias de suprimento elaboradas com esteiras para alimentar suas torretas com munição e produzir materiais para construção +[*] Use blocos de produção para criar uma grande variedade de materiais avançados +[*] Distribua líquidos e enfrente desafios constantes, como surtos de fogo ou ataques de unidades aéreas inimigas +[*] Tire o máximo da sua produção fornecendo refrigeramento e lubrificante opcionais +[*] Produza uma ampla variedade de unidades para gerenciar automaticamente sua base ou atacar bases inimigas +[/list] + +[h2]Defesa de Torres[/h2] + +[list] +[*] Defenda suas estruturas contra hordas de inimigos +[*] Posicione estrategicamente suas torretas para destruí-los antes que alcancem o núcleo +[*] Abasteça suas torretas com munição, refrigeramento e energia +[*] Reforce suas defesas com escudos energizados, projetores de regeneração e outras construções de suporte +[/list] + +[img]{STEAM_APP_IMAGE}/extras/rts3.png[/img] + +[h2]Estratégia em Tempo Real[/h2] + +[list] +[*] Configure linhas de montagem para construir exércitos de unidades mecanizadas +[*] Use suas unidades para enfrentar bases inimigas totalmente funcionais +[*] Capture mais território para instalar novos núcleos e obter acesso a recursos adicionais para expansão +[/list] + +[h2]Campanha[/h2] + +[list] +[*] Jogue duas campanhas planetárias distintas +[*] Conquiste os planetas Serpulo e Erekir avançando por 35 mapas feitos à mão e mais de 250 setores gerados proceduralmente +[*] Capture território e instale fábricas para produzir recursos enquanto joga em outros setores +[*] Defenda seus setores contra invasões periódicas +[*] Coordene a distribuição de recursos entre setores por meio de plataformas de lançamento +[*] Pesquise novos blocos para impulsionar o progresso +[*] Convide seus amigos para completar missões juntos +[*] Mais de 250 blocos tecnológicos para dominar +[*] Mais de 50 tipos diferentes de drones, mechs e naves +[*] Mais de 80 conquistas para completar +[/list] + +[h2]Comunidade e Modding[/h2] + +[list] +[*] Use a Oficina Steam para navegar por mapas e esquemas criados pela comunidade +[*] Junte-se a servidores públicos para jogar com outros jogadores em diferentes plataformas +[*] Jogue em modo cooperativo, PvP ou sandbox +[*] Servidores da comunidade suportam plugins para mapas e modos de jogo personalizados +[*] Crie seu servidor dedicado público ou convide amigos para sua própria sessão privada +[*] Regras de jogo personalizáveis: altere custos de blocos, estatísticas de inimigos, itens iniciais, tempo das hordas e muito mais +[*] O editor de mapas integrado permite criar seus próprios mapas para jogar e compartilhar com a comunidade +[*] Explore mods feitos pela comunidade para adicionar ou remixar ainda mais conteúdo +[/list] diff --git a/fastlane/metadata/steam/brazilian/short-description.txt b/fastlane/metadata/steam/brazilian/short-description.txt new file mode 100644 index 0000000000..b17e5f4625 --- /dev/null +++ b/fastlane/metadata/steam/brazilian/short-description.txt @@ -0,0 +1 @@ +Um jogo de construção e gerenciamento de fábricas com liberdade total, misturando estratégia em tempo real e defesa de torres. From 19186c677c6d79d0b11c4e3e708f5f7bcdc567db Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 28 Aug 2026 17:46:02 -0400 Subject: [PATCH 39/42] Closes #12173 --- core/assets/bundles/bundle.properties | 2 ++ core/src/mindustry/ctype/UnlockableContent.java | 16 ++++++++++------ .../mindustry/ui/dialogs/ContentInfoDialog.java | 15 +++++++-------- core/src/mindustry/world/Block.java | 4 ++-- .../world/blocks/power/NuclearReactor.java | 8 ++++++++ core/src/mindustry/world/meta/Stats.java | 3 ++- tests/src/test/java/PatcherTests.java | 3 +-- 7 files changed, 32 insertions(+), 19 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index af2bac4ec7..eff39d53db 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1319,6 +1319,7 @@ bar.strength = [stat]{0}[lightgray]x strength bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Processor Controlled @@ -1370,6 +1371,7 @@ unit.liquidunits = liquid units unit.powerunits = power units unit.powerequilibrium = power equilibrium unit.heatunits = heat units +unit.heatunitsperside = heat units per side unit.degrees = degrees unit.seconds = seconds unit.minutes = mins diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java index 620fad3a69..d68b4e1ad1 100644 --- a/core/src/mindustry/ctype/UnlockableContent.java +++ b/core/src/mindustry/ctype/UnlockableContent.java @@ -141,18 +141,22 @@ public abstract class UnlockableContent extends MappableContent{ return minfo.mod == null || isPatchContent() ? description : description + "\n" + Core.bundle.format("mod.display", minfo.mod.meta.displayName); } - /** Checks stat initialization state. Call before displaying stats. */ + /** @deprecated just call computeStats() every time, there's no reason to cache it. This will be removed in v9. */ + @Deprecated public void checkStats(){ - if(!stats.intialized){ - setStats(); - stats.intialized = true; - } + computeStats(); } - /** Initializes stats on demand. Should only be called once. Only called before something is displayed. */ + /** Initializes stats on demand. Called every time the block stats are shown. */ public void setStats(){ } + public Stats computeStats(){ + this.stats = new Stats(); + setStats(); + return this.stats; + } + /** Display any extra info after details. */ public void displayExtra(Table table){ diff --git a/core/src/mindustry/ui/dialogs/ContentInfoDialog.java b/core/src/mindustry/ui/dialogs/ContentInfoDialog.java index 061214ea1a..227a4a1461 100644 --- a/core/src/mindustry/ui/dialogs/ContentInfoDialog.java +++ b/core/src/mindustry/ui/dialogs/ContentInfoDialog.java @@ -38,8 +38,9 @@ public class ContentInfoDialog extends BaseDialog{ Table table = new Table(); table.margin(10); - //initialize stats if they haven't been yet - content.checkStats(); + //compute stats every time + var stats = content.computeStats(); + var statMap = stats.toMap(); table.table(title1 -> { title1.image(content.uiIcon).size(iconXLarge).scaling(Scaling.fit); @@ -58,7 +59,7 @@ public class ContentInfoDialog extends BaseDialog{ } if(content.description != null){ - var any = content.stats.toMap().size > 0; + var any = statMap.size > 0; if(any){ table.add("@category.purpose").color(Pal.accent).fillX().padTop(10); @@ -68,16 +69,14 @@ public class ContentInfoDialog extends BaseDialog{ table.add("[lightgray]" + UI.formatIcons(content.displayDescription())).wrap().fillX().padLeft(any ? 10 : 0).width(500f).padTop(any ? 0 : 10).left(); table.row(); - if(!content.stats.useCategories && any){ + if(!stats.useCategories && any){ table.add("@category.general").fillX().color(Pal.accent); table.row(); } } - Stats stats = content.stats; - - for(StatCat cat : stats.toMap().keys()){ - OrderedMap> map = stats.toMap().get(cat); + for(StatCat cat : statMap.keys()){ + var map = statMap.get(cat); if(map.size == 0) continue; diff --git a/core/src/mindustry/world/Block.java b/core/src/mindustry/world/Block.java index 583d9532a8..182f434ec4 100644 --- a/core/src/mindustry/world/Block.java +++ b/core/src/mindustry/world/Block.java @@ -637,6 +637,8 @@ public class Block extends UnlockableContent implements Senseable{ public void setStats(){ super.setStats(); + stats.useCategories = true; + stats.add(Stat.size, "@x@", size, size); if(synthetic()){ @@ -1464,8 +1466,6 @@ public class Block extends UnlockableContent implements Senseable{ setBars(); - stats.useCategories = true; - //TODO check for double power consumption if(!logicConfigurable){ diff --git a/core/src/mindustry/world/blocks/power/NuclearReactor.java b/core/src/mindustry/world/blocks/power/NuclearReactor.java index 7ec3f4c5f8..7bbaaa58d7 100644 --- a/core/src/mindustry/world/blocks/power/NuclearReactor.java +++ b/core/src/mindustry/world/blocks/power/NuclearReactor.java @@ -90,6 +90,14 @@ public class NuclearReactor extends PowerGenerator{ if(hasItems){ stats.add(Stat.productionTime, itemDuration / 60f, StatUnit.seconds); } + if(heatOutput > 0f && (ui.planet.isShown() ? ui.planet.state.planet : state.isGame() ? state.getPlanet() : null) == Planets.erekir){ + stats.add(Stat.output, table -> { + //using StatUnit.localized() strips the icon + String unit = "[red]" + Iconc.waves + "[] " + Strings.fixed(heatOutput, 0) + " " + Core.bundle.get("unit.heatunitsperside"); + + table.add(Core.bundle.format("bar.upto", unit)); + }); + } } @Override diff --git a/core/src/mindustry/world/meta/Stats.java b/core/src/mindustry/world/meta/Stats.java index 5f7ce8f08e..8a1bd0d5da 100644 --- a/core/src/mindustry/world/meta/Stats.java +++ b/core/src/mindustry/world/meta/Stats.java @@ -15,7 +15,8 @@ import java.util.*; public class Stats{ /** Whether to display stats with categories. If false, categories are completely ignored during display. */ public boolean useCategories = false; - /** Whether these stats are initialized yet. */ + /** @deprecated does nothing, will be removed in v9 */ + @Deprecated public boolean intialized = false; /** Production time period in ticks. Used for crafters. **/ public float timePeriod = -1; diff --git a/tests/src/test/java/PatcherTests.java b/tests/src/test/java/PatcherTests.java index 846dcb9e7a..c2c5bd281c 100644 --- a/tests/src/test/java/PatcherTests.java +++ b/tests/src/test/java/PatcherTests.java @@ -173,7 +173,6 @@ public class PatcherTests{ @Test void unitWeapons() throws Exception{ - UnitTypes.dagger.checkStats(); UnitTypes.dagger.stats.add(Stat.charge, 999); assertNotNull(UnitTypes.dagger.stats.toMap().get(StatCat.general).get(Stat.charge)); @@ -195,7 +194,7 @@ public class PatcherTests{ Vars.logic.reset(); - UnitTypes.dagger.checkStats(); + UnitTypes.dagger.computeStats(); assertNull(UnitTypes.dagger.stats.toMap().get(StatCat.general).get(Stat.charge)); } From 456adc6a4f4dd6425fada6778cb9cc77a7cc87f3 Mon Sep 17 00:00:00 2001 From: Github Actions Date: Fri, 28 Aug 2026 21:46:47 +0000 Subject: [PATCH 40/42] Automatic bundle update --- core/assets/bundles/bundle_be.properties | 2 ++ core/assets/bundles/bundle_bg.properties | 2 ++ core/assets/bundles/bundle_ca.properties | 2 ++ core/assets/bundles/bundle_cs.properties | 2 ++ core/assets/bundles/bundle_da.properties | 2 ++ core/assets/bundles/bundle_de.properties | 2 ++ core/assets/bundles/bundle_es.properties | 2 ++ core/assets/bundles/bundle_et.properties | 2 ++ core/assets/bundles/bundle_eu.properties | 2 ++ core/assets/bundles/bundle_fi.properties | 2 ++ core/assets/bundles/bundle_fil.properties | 2 ++ core/assets/bundles/bundle_fr.properties | 2 ++ core/assets/bundles/bundle_hu.properties | 2 ++ core/assets/bundles/bundle_id_ID.properties | 2 ++ core/assets/bundles/bundle_it.properties | 2 ++ core/assets/bundles/bundle_ja.properties | 2 ++ core/assets/bundles/bundle_ko.properties | 2 ++ core/assets/bundles/bundle_lt.properties | 2 ++ core/assets/bundles/bundle_nl.properties | 2 ++ core/assets/bundles/bundle_nl_BE.properties | 2 ++ core/assets/bundles/bundle_pl.properties | 2 ++ core/assets/bundles/bundle_pt_BR.properties | 2 ++ core/assets/bundles/bundle_pt_PT.properties | 2 ++ core/assets/bundles/bundle_ro.properties | 2 ++ core/assets/bundles/bundle_ru.properties | 2 ++ core/assets/bundles/bundle_sr.properties | 2 ++ core/assets/bundles/bundle_sv.properties | 2 ++ core/assets/bundles/bundle_th.properties | 2 ++ core/assets/bundles/bundle_tk.properties | 2 ++ core/assets/bundles/bundle_tr.properties | 2 ++ core/assets/bundles/bundle_uk_UA.properties | 2 ++ core/assets/bundles/bundle_vi.properties | 2 ++ core/assets/bundles/bundle_zh_CN.properties | 2 ++ core/assets/bundles/bundle_zh_TW.properties | 2 ++ 34 files changed, 68 insertions(+) diff --git a/core/assets/bundles/bundle_be.properties b/core/assets/bundles/bundle_be.properties index c25d6ae4c3..3c7a4d53a8 100644 --- a/core/assets/bundles/bundle_be.properties +++ b/core/assets/bundles/bundle_be.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x strength bar.regenerationrate = [stat]{0}/сек[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Кантралюецца Працэссарам @@ -1365,6 +1366,7 @@ unit.liquidunits = вадкасных адзінак unit.powerunits = энерг. адзінак unit.powerequilibrium = power equilibrium unit.heatunits = адзінкі энергіі +unit.heatunitsperside = heat units per side unit.degrees = град. unit.seconds = сек. unit.minutes = хв. diff --git a/core/assets/bundles/bundle_bg.properties b/core/assets/bundles/bundle_bg.properties index bd834e5f82..2278e4d325 100644 --- a/core/assets/bundles/bundle_bg.properties +++ b/core/assets/bundles/bundle_bg.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x сила bar.regenerationrate = [stat]{0}/sec[lightgray] скорост на регенерация bar.activationtimer = Ацтивация след {0} bar.activated = Активирано +bar.upto = Up to {0} units.processorcontrol = [lightgray]Контролиран от процесор @@ -1365,6 +1366,7 @@ unit.liquidunits = течност unit.powerunits = електричество unit.powerequilibrium = електрически баланс unit.heatunits = единици горещина +unit.heatunitsperside = heat units per side unit.degrees = градуси unit.seconds = секунди unit.minutes = минути diff --git a/core/assets/bundles/bundle_ca.properties b/core/assets/bundles/bundle_ca.properties index b30bf548eb..678aadf693 100644 --- a/core/assets/bundles/bundle_ca.properties +++ b/core/assets/bundles/bundle_ca.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]× força bar.regenerationrate = [stat]{0}/sec[lightgray] de taxa de regen. bar.activationtimer = S’activa d’aquí a {0} bar.activated = Activat +bar.upto = Up to {0} units.processorcontrol = [lightgray]Controlat pel processador @@ -1365,6 +1366,7 @@ unit.liquidunits = unitats de líquid unit.powerunits = unitats d’energia unit.powerequilibrium = potència d’equilibri unit.heatunits = unitats de calor +unit.heatunitsperside = heat units per side unit.degrees = ° unit.seconds = s unit.minutes = min diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index 9969e95d8b..3e9e1b3889 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x síla bar.regenerationrate = [stat]{0}/sek[lightgray] rychlost regenerace bar.activationtimer = Aktivuje se za {0} bar.activated = Aktivováno +bar.upto = Up to {0} units.processorcontrol = [lightgray]Procesor je ovládán[] @@ -1365,6 +1366,7 @@ unit.liquidunits = jednotek kapalin unit.powerunits = jednotek energie unit.powerequilibrium = rovnováha energie unit.heatunits = jednotek tepla +unit.heatunitsperside = heat units per side unit.degrees = úhly unit.seconds = sekundy unit.minutes = minuty diff --git a/core/assets/bundles/bundle_da.properties b/core/assets/bundles/bundle_da.properties index c29e18e5a6..b3236ffd1a 100644 --- a/core/assets/bundles/bundle_da.properties +++ b/core/assets/bundles/bundle_da.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x strength bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Processor kontrolleret @@ -1365,6 +1366,7 @@ unit.liquidunits = væskeenheder unit.powerunits = strømenheder unit.powerequilibrium = power equilibrium unit.heatunits = heat units +unit.heatunitsperside = heat units per side unit.degrees = grader unit.seconds = sekunder unit.minutes = minutter diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index d2763c1ebe..950a752453 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x Stärke bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Prozessorgesteuert @@ -1365,6 +1366,7 @@ unit.liquidunits = Flüssigkeitseinheiten unit.powerunits = Stromeinheiten unit.powerequilibrium = power equilibrium unit.heatunits = Hitzeeinheiten +unit.heatunitsperside = heat units per side unit.degrees = Grad unit.seconds = Sekunden unit.minutes = Minuten diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index a8551d838a..34c16544f3 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x potencia bar.regenerationrate = [stat]{0}/seg[lightgray] regeneración bar.activationtimer = Se activa en {0} bar.activated = Activado +bar.upto = Up to {0} units.processorcontrol = [lightgray]Controlado desde el procesador @@ -1365,6 +1366,7 @@ unit.liquidunits = unidades de líquido unit.powerunits = unidades de energía unit.powerequilibrium = power equilibrium unit.heatunits = unidades de calor +unit.heatunitsperside = heat units per side unit.degrees = grados unit.seconds = segundos unit.minutes = mins diff --git a/core/assets/bundles/bundle_et.properties b/core/assets/bundles/bundle_et.properties index ffa3e0cac3..43fea9a237 100644 --- a/core/assets/bundles/bundle_et.properties +++ b/core/assets/bundles/bundle_et.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x strength bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Processor Controlled @@ -1365,6 +1366,7 @@ unit.liquidunits = vedelikuühikut unit.powerunits = energiaühikut unit.powerequilibrium = power equilibrium unit.heatunits = heat units +unit.heatunitsperside = heat units per side unit.degrees = kraadi unit.seconds = s unit.minutes = mins diff --git a/core/assets/bundles/bundle_eu.properties b/core/assets/bundles/bundle_eu.properties index 4884b19833..d9d61b784f 100644 --- a/core/assets/bundles/bundle_eu.properties +++ b/core/assets/bundles/bundle_eu.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x indarra bar.regenerationrate = [stat]{0}/seg[lightgray] birsorkuntza tasa bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Prozesadorea kontrolatua @@ -1365,6 +1366,7 @@ unit.liquidunits = likido unitate unit.powerunits = energia unitate unit.powerequilibrium = power equilibrium unit.heatunits = berotze unitateak +unit.heatunitsperside = heat units per side unit.degrees = grado unit.seconds = segundo unit.minutes = minutuak diff --git a/core/assets/bundles/bundle_fi.properties b/core/assets/bundles/bundle_fi.properties index d7bf29cb84..143ba1a1ee 100644 --- a/core/assets/bundles/bundle_fi.properties +++ b/core/assets/bundles/bundle_fi.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x voimakkuus bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Prosessorin hallitsema @@ -1365,6 +1366,7 @@ unit.liquidunits = nesteyksikköä unit.powerunits = energiayksikköä unit.powerequilibrium = power equilibrium unit.heatunits = lämpöyksikköä +unit.heatunitsperside = heat units per side unit.degrees = astetta unit.seconds = sekunttia unit.minutes = minuuttia diff --git a/core/assets/bundles/bundle_fil.properties b/core/assets/bundles/bundle_fil.properties index d95665e2df..199326bb0c 100644 --- a/core/assets/bundles/bundle_fil.properties +++ b/core/assets/bundles/bundle_fil.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x strength bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Processor Controlled @@ -1365,6 +1366,7 @@ unit.liquidunits = mga yunit ng likido unit.powerunits = mga yunit ng kuryente unit.powerequilibrium = power equilibrium unit.heatunits = mga yunit ng init +unit.heatunitsperside = heat units per side unit.degrees = digri unit.seconds = segundo unit.minutes = mins diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index 65231a9ddb..2eb5c001fe 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x puissance bar.regenerationrate = [stat]{0}/sec[lightgray] taux de régénération bar.activationtimer = S'active dans {0} bar.activated = Activé +bar.upto = Up to {0} units.processorcontrol = [lightgray]Contrôlé par un processeur. @@ -1365,6 +1366,7 @@ unit.liquidunits = unités de liquide unit.powerunits = unités d'énergie unit.powerequilibrium = équilibre énergétique unit.heatunits = unités de température +unit.heatunitsperside = heat units per side unit.degrees = degrés unit.seconds = sec unit.minutes = min diff --git a/core/assets/bundles/bundle_hu.properties b/core/assets/bundles/bundle_hu.properties index 50e13d100b..7e2b4b636f 100644 --- a/core/assets/bundles/bundle_hu.properties +++ b/core/assets/bundles/bundle_hu.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x erő bar.regenerationrate = [stat]{0}/mp[lightgray] regenerálási sebesség bar.activationtimer = Aktiválás {0} mp múlva bar.activated = Aktiválva +bar.upto = Up to {0} units.processorcontrol = [lightgray]Processzorvezérelt @@ -1365,6 +1366,7 @@ unit.liquidunits = folyadékegység unit.powerunits = áramegység unit.powerequilibrium = áramegyensúly unit.heatunits = hőegység +unit.heatunitsperside = heat units per side unit.degrees = fok unit.seconds = másodperc unit.minutes = perc diff --git a/core/assets/bundles/bundle_id_ID.properties b/core/assets/bundles/bundle_id_ID.properties index 1c03b0450b..a26ec747f0 100644 --- a/core/assets/bundles/bundle_id_ID.properties +++ b/core/assets/bundles/bundle_id_ID.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x penguatan bar.regenerationrate = [stat]{0}/dtk[lightgray] waktu pemulihan bar.activationtimer = Aktif dalam {0} bar.activated = Aktif +bar.upto = Up to {0} units.processorcontrol = [lightgray]Dikendalikan Prosesor @@ -1365,6 +1366,7 @@ unit.liquidunits = unit zat cair unit.powerunits = unit tenaga unit.powerequilibrium = keseimbangan tenaga unit.heatunits = unit panas +unit.heatunitsperside = heat units per side unit.degrees = derajat unit.seconds = detik unit.minutes = menit diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index c1d0292bc3..f608b654a7 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x forza bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Attivazione in {0} bar.activated = Attivato +bar.upto = Up to {0} units.processorcontrol = [lightgray]Controllato dal Processore @@ -1365,6 +1366,7 @@ unit.liquidunits = unità liquidi unit.powerunits = unità energetica unit.powerequilibrium = power equilibrium unit.heatunits = unità termica +unit.heatunitsperside = heat units per side unit.degrees = gradi unit.seconds = secondi unit.minutes = minuti diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties index 2418813099..49436f0d31 100644 --- a/core/assets/bundles/bundle_ja.properties +++ b/core/assets/bundles/bundle_ja.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x 強化 bar.regenerationrate = [stat]{0}/秒[lightgray] 再生率 bar.activationtimer = 発動まで {0} bar.activated = アクティブ +bar.upto = Up to {0} units.processorcontrol = [lightgray]プロセッサーの制御下 @@ -1365,6 +1366,7 @@ unit.liquidunits = 液体 unit.powerunits = 電力 unit.powerequilibrium = 電力均衡 unit.heatunits = 熱量 +unit.heatunitsperside = heat units per side unit.degrees = 度 unit.seconds = 秒 unit.minutes = 分 diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index e7c6008d66..9c4757f070 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x 치료 속도[][] bar.regenerationrate = [stat]{0}/초[lightgray] 재생률 bar.activationtimer = {0}초 후 활성화 bar.activated = 활성화됨 +bar.upto = Up to {0} units.processorcontrol = [lightgray]프로세서 제어됨[] @@ -1365,6 +1366,7 @@ unit.liquidunits = 액체 unit.powerunits = 전력 unit.powerequilibrium = 전력 균형 unit.heatunits = 열 단위 +unit.heatunitsperside = heat units per side unit.degrees = 도 unit.seconds = 초 unit.minutes = 분 diff --git a/core/assets/bundles/bundle_lt.properties b/core/assets/bundles/bundle_lt.properties index e41d0b850a..bfeba25b4f 100644 --- a/core/assets/bundles/bundle_lt.properties +++ b/core/assets/bundles/bundle_lt.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x strength bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Processor Controlled @@ -1365,6 +1366,7 @@ unit.liquidunits = skysčio vienetai unit.powerunits = energijos vienetai unit.powerequilibrium = power equilibrium unit.heatunits = heat units +unit.heatunitsperside = heat units per side unit.degrees = laipsnių unit.seconds = sekundės unit.minutes = mins diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties index 22bf93b96a..70037c3e23 100644 --- a/core/assets/bundles/bundle_nl.properties +++ b/core/assets/bundles/bundle_nl.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x sterkte bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Processor Gestuurd @@ -1365,6 +1366,7 @@ unit.liquidunits = vloeistof eenheden unit.powerunits = stroom eenheden unit.powerequilibrium = power equilibrium unit.heatunits = warmte eenheden +unit.heatunitsperside = heat units per side unit.degrees = graden unit.seconds = seconden unit.minutes = minuten diff --git a/core/assets/bundles/bundle_nl_BE.properties b/core/assets/bundles/bundle_nl_BE.properties index b945d116de..5984807f94 100644 --- a/core/assets/bundles/bundle_nl_BE.properties +++ b/core/assets/bundles/bundle_nl_BE.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x strength bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Processor Controlled @@ -1365,6 +1366,7 @@ unit.liquidunits = liquid units unit.powerunits = power units unit.powerequilibrium = power equilibrium unit.heatunits = heat units +unit.heatunitsperside = heat units per side unit.degrees = degrees unit.seconds = seconds unit.minutes = mins diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index 7bdb93e1e7..d75076ada7 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x siły bar.regenerationrate = [stat]{0}/sek[lightgray] szybkość regeneracji bar.activationtimer = Aktywuje się za {0} bar.activated = Aktywowane +bar.upto = Up to {0} units.processorcontrol = [lightgray]Kontrolowany przez procesor @@ -1365,6 +1366,7 @@ unit.liquidunits = jednostek płynu unit.powerunits = jednostek prądu unit.powerequilibrium = równowaga energii unit.heatunits = jednostek ciepła +unit.heatunitsperside = heat units per side unit.degrees = stopnie unit.seconds = sekundy unit.minutes = min diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index dcd7284488..d54a6f1ae8 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x força bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Ativa em {0} bar.activated = Ativado +bar.upto = Up to {0} units.processorcontrol = [lightgray]Controlado por Processador @@ -1365,6 +1366,7 @@ unit.liquidunits = unidades de líquido unit.powerunits = unidades de energia unit.powerequilibrium = equilíbrio de energia unit.heatunits = unidades de calor +unit.heatunitsperside = heat units per side unit.degrees = Graus unit.seconds = segundos unit.minutes = mins diff --git a/core/assets/bundles/bundle_pt_PT.properties b/core/assets/bundles/bundle_pt_PT.properties index b2a3aaeb31..7c5bbd8712 100644 --- a/core/assets/bundles/bundle_pt_PT.properties +++ b/core/assets/bundles/bundle_pt_PT.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x força bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Controlado por Processador @@ -1365,6 +1366,7 @@ unit.liquidunits = Unidades de líquido unit.powerunits = Unidades de energia unit.powerequilibrium = power equilibrium unit.heatunits = Unidades de calor +unit.heatunitsperside = heat units per side unit.degrees = Graus unit.seconds = segundos unit.minutes = minutos diff --git a/core/assets/bundles/bundle_ro.properties b/core/assets/bundles/bundle_ro.properties index e40eb80383..af29611e2a 100644 --- a/core/assets/bundles/bundle_ro.properties +++ b/core/assets/bundles/bundle_ro.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x putere bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Controlat de Procesor @@ -1365,6 +1366,7 @@ unit.liquidunits = unități lichid unit.powerunits = electricitate unit.powerequilibrium = power equilibrium unit.heatunits = heat units +unit.heatunitsperside = heat units per side unit.degrees = grade unit.seconds = secunde unit.minutes = min diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 029d1ffe57..b88840314f 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x эффективность bar.regenerationrate = [stat]{0}/сек[lightgray] скорость регенерации bar.activationtimer = Активируется через {0} bar.activated = Активировано +bar.upto = Up to {0} units.processorcontrol = [lightgray]Управляется процессором @@ -1365,6 +1366,7 @@ unit.liquidunits = жидкостных единиц unit.powerunits = энерг. единиц unit.powerequilibrium = энерг. равновесие unit.heatunits = единиц тепла +unit.heatunitsperside = heat units per side unit.degrees = ° unit.seconds = сек unit.minutes = мин diff --git a/core/assets/bundles/bundle_sr.properties b/core/assets/bundles/bundle_sr.properties index f70c4ecc59..29ae18ce85 100644 --- a/core/assets/bundles/bundle_sr.properties +++ b/core/assets/bundles/bundle_sr.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x snage bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Procesno Upravljan @@ -1365,6 +1366,7 @@ unit.liquidunits = jedinica tečnosti unit.powerunits = jedinica energije unit.powerequilibrium = power equilibrium unit.heatunits = jedinica toplote +unit.heatunitsperside = heat units per side unit.degrees = stepeni unit.seconds = sekunde unit.minutes = minuti diff --git a/core/assets/bundles/bundle_sv.properties b/core/assets/bundles/bundle_sv.properties index feaaf5d87c..b01faed0d8 100644 --- a/core/assets/bundles/bundle_sv.properties +++ b/core/assets/bundles/bundle_sv.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x strength bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Processor Controlled @@ -1365,6 +1366,7 @@ unit.liquidunits = liquid units unit.powerunits = power units unit.powerequilibrium = power equilibrium unit.heatunits = heat units +unit.heatunitsperside = heat units per side unit.degrees = grader unit.seconds = sekunder unit.minutes = mins diff --git a/core/assets/bundles/bundle_th.properties b/core/assets/bundles/bundle_th.properties index a58165f364..7bb36c0d41 100644 --- a/core/assets/bundles/bundle_th.properties +++ b/core/assets/bundles/bundle_th.properties @@ -1314,6 +1314,7 @@ bar.strength = [lightgray]ความรุนแรง [stat]{0}[lightgray]x bar.regenerationrate = [stat]{0}/วิ[lightgray] อัตราการฟื้นฟู bar.activationtimer = เปิดใช้งานใน {0} bar.activated = เปิดใช้งานแล้ว +bar.upto = Up to {0} units.processorcontrol = [lightgray]ถูกตัวประมวลผลควบคุมอยู่ @@ -1365,6 +1366,7 @@ unit.liquidunits = หน่วยของเหลว unit.powerunits = หน่วยพลังงาน unit.powerequilibrium = สมดุลพลังงาน unit.heatunits = หน่วยความร้อน +unit.heatunitsperside = heat units per side unit.degrees = องศา unit.seconds = วินาที unit.minutes = นาที diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index fb27359a0f..e8b334163a 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x strength bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]Processor Controlled @@ -1365,6 +1366,7 @@ unit.liquidunits = Litre unit.powerunits = Volt unit.powerequilibrium = power equilibrium unit.heatunits = heat units +unit.heatunitsperside = heat units per side unit.degrees = derece unit.seconds = saniye unit.minutes = mins diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 1c781be1ef..2f84d4250d 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x Güç bar.regenerationrate = [stat]{0}/sec[lightgray] tamir hızı bar.activationtimer = {0} saniyede aktif olucak bar.activated = Aktif +bar.upto = Up to {0} units.processorcontrol = [lightgray]İşlemci Kontrolünde @@ -1365,6 +1366,7 @@ unit.liquidunits = sıvı birimi unit.powerunits = enerji birimi unit.powerequilibrium = enerji dengesi unit.heatunits = ısı birimi +unit.heatunitsperside = heat units per side unit.degrees = derece unit.seconds = saniye unit.minutes = dakika diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index 27124d4484..3210acc4c2 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -1314,6 +1314,7 @@ bar.strength = x[stat]{0}[lightgray] сила bar.regenerationrate = [stat]{0} [lightgray]відновлення [stat]за сек. bar.activationtimer = Активується через {0} bar.activated = Готово +bar.upto = Up to {0} units.processorcontrol = [lightgray]Керується процесором @@ -1365,6 +1366,7 @@ unit.liquidunits = одиниць рідини unit.powerunits = одиниць енергії unit.powerequilibrium = енергорівновага unit.heatunits = одиниць нагрівання +unit.heatunitsperside = heat units per side unit.degrees = град. unit.seconds = сек. unit.minutes = хв. diff --git a/core/assets/bundles/bundle_vi.properties b/core/assets/bundles/bundle_vi.properties index 2f8d46d020..443c2ded37 100644 --- a/core/assets/bundles/bundle_vi.properties +++ b/core/assets/bundles/bundle_vi.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x sức mạnh bar.regenerationrate = [stat]{0}/sec[lightgray] tốc độ hồi phục bar.activationtimer = Kích hoạt trong {0} bar.activated = Đã kích hoạt +bar.upto = Up to {0} units.processorcontrol = [lightgray]Điều khiển bởi bộ xử lý @@ -1365,6 +1366,7 @@ unit.liquidunits = đơn vị chất lỏng unit.powerunits = đơn vị năng lượng unit.powerequilibrium = cân bằng năng lượng unit.heatunits = đơn vị nhiệt +unit.heatunitsperside = heat units per side unit.degrees = độ unit.seconds = giây unit.minutes = phút diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index b3381086d1..1420e8a0c9 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x 效率 bar.regenerationrate = [stat]{0}/秒[lightgray] 恢复率 bar.activationtimer = 在 {0} 后激活 bar.activated = 已激活 +bar.upto = Up to {0} units.processorcontrol = [lightgray]由处理器控制 @@ -1365,6 +1366,7 @@ unit.liquidunits = 液体 unit.powerunits = 电力 unit.powerequilibrium = 电力平衡 unit.heatunits = 单位热量 +unit.heatunitsperside = heat units per side unit.degrees = 度 unit.seconds = 秒 unit.minutes = 分 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index 0850ad4de0..46c745ab13 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -1314,6 +1314,7 @@ bar.strength = [stat]{0}[lightgray]x 強度 bar.regenerationrate = [stat]{0}/sec[lightgray] regen rate bar.activationtimer = Activates in {0} bar.activated = Activated +bar.upto = Up to {0} units.processorcontrol = [lightgray]由微處理器控制 @@ -1365,6 +1366,7 @@ unit.liquidunits = 液體單位 unit.powerunits = 能量單位 unit.powerequilibrium = power equilibrium unit.heatunits = 熱量單位 +unit.heatunitsperside = heat units per side unit.degrees = 度 unit.seconds = 秒 unit.minutes = 分 From 9d49b5857103ee9ef76abb6187bf6dc314c4a3b7 Mon Sep 17 00:00:00 2001 From: Cardillan <122014763+cardillan@users.noreply.github.com> Date: Sat, 29 Aug 2026 00:15:49 +0200 Subject: [PATCH 41/42] More tileable display fixes (#12514) --- core/src/mindustry/game/MapObjectives.java | 4 ++-- core/src/mindustry/world/blocks/logic/LogicDisplay.java | 7 ++++--- .../world/blocks/logic/TileableLogicDisplay.java | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/core/src/mindustry/game/MapObjectives.java b/core/src/mindustry/game/MapObjectives.java index db871aa96c..994f333628 100644 --- a/core/src/mindustry/game/MapObjectives.java +++ b/core/src/mindustry/game/MapObjectives.java @@ -1415,10 +1415,10 @@ public class MapObjectives implements Iterable, Eachable> 5; if(ctype == displayDrawType){ if(id != index && id < displays.size && id >= 0 && displays.get(id).buffer != null){ - displays.get(id).getBufferRegion(Tmp.tr1); + displays.get(id).rootDisplay.getBufferRegion(Tmp.tr1); Draw.rect(Tmp.tr1, x, y, p2, p2 / Tmp.tr1.ratio(), p3); } }else if(ctype < ContentType.all.length && Vars.content.getByID(ContentType.all[ctype], id) instanceof UnlockableContent u){ diff --git a/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java b/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java index d0085d8562..d772e62899 100644 --- a/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java +++ b/core/src/mindustry/world/blocks/logic/TileableLogicDisplay.java @@ -269,11 +269,11 @@ public class TileableLogicDisplay extends LogicDisplay{ @Override public void ensureBuffer() { - if(buffer == null){ - buffer = new FrameBuffer(32 * tilesWidth - 2 * frameSize, 32 * tilesHeight - 2 * frameSize); + if(rootDisplay.buffer == null){ + rootDisplay.buffer = new FrameBuffer(32 * tilesWidth - 2 * frameSize, 32 * tilesHeight - 2 * frameSize); //clear the buffer - some OSs leave garbage in it - buffer.begin(backgroundColor); - buffer.end(); + rootDisplay.buffer.begin(backgroundColor); + rootDisplay.buffer.end(); } } From 8553bb7eccb820a80d6ac19bb0afa6eb9e9fb77e Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 28 Aug 2026 18:33:32 -0400 Subject: [PATCH 42/42] Revert "Fix mod browser null listing crash (#12546)" This reverts commit 77e2ce727453c3d7abf7d0310a55abef15b73bca. --- core/src/mindustry/ui/dialogs/ModBrowserDialog.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/src/mindustry/ui/dialogs/ModBrowserDialog.java b/core/src/mindustry/ui/dialogs/ModBrowserDialog.java index a4362700c8..523393780f 100644 --- a/core/src/mindustry/ui/dialogs/ModBrowserDialog.java +++ b/core/src/mindustry/ui/dialogs/ModBrowserDialog.java @@ -93,8 +93,7 @@ public class ModBrowserDialog extends BaseDialog{ String strResult = response.getResultAsString(); try{ - Seq parsed = json.fromJson(Seq.class, ModListing.class, strResult); - Seq mods = parsed == null ? new Seq<>() : parsed; + Seq mods = json.fromJson(Seq.class, ModListing.class, strResult); var d = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); Func parser = text -> {