From 39cc6cfd6dca7bc060340e142cbdb98aa5f59ee4 Mon Sep 17 00:00:00 2001 From: Anuken Date: Wed, 3 Jun 2026 18:25:58 -0400 Subject: [PATCH] Misc minor fixes --- core/assets/bundles/bundle.properties | 2 +- core/src/mindustry/ctype/Content.java | 8 ++++++-- core/src/mindustry/mod/DataAssetCache.java | 11 ++++++----- core/src/mindustry/mod/DataManager.java | 3 --- core/src/mindustry/mod/DataPatcher.java | 3 ++- core/src/mindustry/mod/data/PatchAsset.java | 6 +++--- core/src/mindustry/net/Streamable.java | 8 ++------ core/src/mindustry/type/Planet.java | 6 +++++- core/src/mindustry/type/SectorPreset.java | 4 ++-- core/src/mindustry/ui/dialogs/PlanetDialog.java | 1 + server/src/mindustry/server/ServerControl.java | 4 ++-- 11 files changed, 30 insertions(+), 26 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 90ad3d0e1c..a55580fa9e 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -334,7 +334,7 @@ reconnecting = [accent]Reconnecting... connecting.establish = [accent]Establishing connection... receiving.world = [accent]Receiving world data ({0})... receiving.assets = [accent]Receiving assets ({0})... -receiving.assets.fail = Error occurred while receiving assets. +receiving.assets.fail = I/O error occurred while receiving assets. server.port = Port: server.invalidport = Invalid port number! diff --git a/core/src/mindustry/ctype/Content.java b/core/src/mindustry/ctype/Content.java index 2bc031f9a9..7965d8f754 100644 --- a/core/src/mindustry/ctype/Content.java +++ b/core/src/mindustry/ctype/Content.java @@ -3,8 +3,9 @@ package mindustry.ctype; import arc.files.*; import arc.util.*; import mindustry.*; -import mindustry.mod.*; +import mindustry.annotations.Annotations.*; import mindustry.mod.Mods.*; +import mindustry.mod.*; import mindustry.mod.data.*; /** Base class for a content type that is loaded in {@link mindustry.core.ContentLoader}. */ @@ -13,6 +14,8 @@ public abstract class Content implements Comparable{ public short id; /** Info on which mod this content was loaded from. */ public ModContentInfo minfo = new ModContentInfo(); + /** If true, this content is invalid (added in a data patch and then removed). */ + public boolean removed; public Content(){ this.id = (short)Vars.content.getBy(getContentType()).size; @@ -26,7 +29,8 @@ public abstract class Content implements Comparable{ public abstract ContentType getContentType(); /** Called when this content is removed in a data patch. */ - public void remove(){} + @CallSuper + public void removeContent(){} /** Called after all content and modules are created. Do not use to load regions or texture data! */ public void init(){} diff --git a/core/src/mindustry/mod/DataAssetCache.java b/core/src/mindustry/mod/DataAssetCache.java index c393a4a390..43b11db376 100644 --- a/core/src/mindustry/mod/DataAssetCache.java +++ b/core/src/mindustry/mod/DataAssetCache.java @@ -48,14 +48,15 @@ public class DataAssetCache{ return get(encodeHash(shaHash)); } - //base32 without padding - public static String encodeHash(byte[] data) { + //base32 without padding; data must be exactly 32 bytes + public static String encodeHash(byte[] data){ + if(data.length != 32) throw new IllegalArgumentException("Data must be exactly 32 bytes (length: " + data.length + ")"); char[] out = new char[52]; int di = 0, oi = 0; - long bits; for(int i = 0; i < 6; i++){ - bits = ((long)(data[di++] & 0xFF) << 32) | + long bits = + ((long)(data[di++] & 0xFF) << 32) | ((long)(data[di++] & 0xFF) << 24) | ((long)(data[di++] & 0xFF) << 16) | ((long)(data[di++] & 0xFF) << 8) | @@ -77,7 +78,7 @@ public class DataAssetCache{ out[oi++] = base32Alphabet[(b0 >>> 3) & 0x1F]; out[oi++] = base32Alphabet[((b0 << 2) & 0x1C) | ((b1 >>> 6) & 0x03)]; out[oi++] = base32Alphabet[(b1 >>> 1) & 0x1F]; - out[oi++] = base32Alphabet[(b1 << 4) & 0x10]; + out[oi++] = base32Alphabet[(b1 << 4) & 0x1F]; return new String(out); } diff --git a/core/src/mindustry/mod/DataManager.java b/core/src/mindustry/mod/DataManager.java index bac77f5193..e6ce81217f 100644 --- a/core/src/mindustry/mod/DataManager.java +++ b/core/src/mindustry/mod/DataManager.java @@ -6,9 +6,6 @@ import mindustry.mod.data.*; /** * TODO: - * - Patchset names are weird and broken with the new path system (no unique file name) - * - Test planets and make sure remove() works properly - * - Try really hard to make the game crash or misbehave * - Unit tests */ public class DataManager{ diff --git a/core/src/mindustry/mod/DataPatcher.java b/core/src/mindustry/mod/DataPatcher.java index 22951292c0..d58e72be71 100644 --- a/core/src/mindustry/mod/DataPatcher.java +++ b/core/src/mindustry/mod/DataPatcher.java @@ -264,7 +264,8 @@ public class DataPatcher{ for(var arr : Vars.content.getContentMap()){ for(var value : arr){ if(value.isModded() && value.minfo.mod == dpMod){ - value.remove(); + value.removed = true; + value.removeContent(); } } } diff --git a/core/src/mindustry/mod/data/PatchAsset.java b/core/src/mindustry/mod/data/PatchAsset.java index 515eadaac4..ae6f4ca886 100644 --- a/core/src/mindustry/mod/data/PatchAsset.java +++ b/core/src/mindustry/mod/data/PatchAsset.java @@ -1,7 +1,6 @@ package mindustry.mod.data; import arc.files.*; -import arc.math.*; import arc.struct.*; import arc.util.*; import arc.util.serialization.*; @@ -9,6 +8,7 @@ import arc.util.serialization.JsonWriter.*; import arc.util.serialization.Jval.*; import java.io.*; +import java.util.*; public class PatchAsset extends DataAsset{ private static final JsonValue emptyValue = new JsonValue("error"); @@ -23,8 +23,8 @@ public class PatchAsset extends DataAsset{ public Seq warnings = new Seq<>(); public PatchAsset(String patch){ - //patches don't have a path by default, so make it something random when reading. TODO: this is a temporary measure. - setPath("patch-" + Mathf.rand.nextLong() + ".json"); + //patches don't have a path by default, so make it something random when reading. TODO: this is a temporary measure until a proper editor is added. + setPath("patch-" + UUID.randomUUID() + ".json"); this.patch = patch; } diff --git a/core/src/mindustry/net/Streamable.java b/core/src/mindustry/net/Streamable.java index d6ceaff65b..ed2035859f 100644 --- a/core/src/mindustry/net/Streamable.java +++ b/core/src/mindustry/net/Streamable.java @@ -111,10 +111,6 @@ public class Streamable extends Packet{ if(isClosed) throw new ClosedChannelException(); if(currentBuffer == null || currentOffset >= currentBuffer.length){ - //after a finish(), reads are allowed, but only if the queue isn't empty (otherwise it's a EOF) - //throwing EOF is against convention, but I don't care, this is invalid state, and you shouldn't be here - if(isFinished && queue.isEmpty()) throw new EOFException(); - try{ currentBuffer = queue.take(); currentOffset = 0; @@ -123,7 +119,7 @@ public class Streamable extends Packet{ if(currentBuffer == closedSignal){ queue.add(closedSignal); //if the queue was finished, and you were trying to read something, you should get a EOF instead (invalid state) - if(isFinished) throw new EOFException(); + if(isFinished) return -1; throw new ClosedChannelException(); } }catch(InterruptedException e){ @@ -146,7 +142,7 @@ public class Streamable extends Packet{ return result == -1 ? -1 : (singleByte[0] & 0xFF); } - /** unlike close(), this allows the stream to finish reading whatever it's reading, but if it tries to read more, it will return -1 (EOF) */ + /** unlike close(), this allows the stream to finish reading whatever it's reading, but if it tries to read more, it will throw EOF */ public void finish(){ isFinished = true; queue.add(closedSignal); diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index 322a2f8b1b..b0987a8a86 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -237,10 +237,14 @@ public class Planet extends UnlockableContent{ } @Override - public void remove(){ + public void removeContent(){ + super.removeContent(); + if(parent != null){ parent.children.remove(this); parent.updateTotalRadius(); + if(mesh != null) mesh.dispose(); + if(cloudMesh != null) cloudMesh.dispose(); } } diff --git a/core/src/mindustry/type/SectorPreset.java b/core/src/mindustry/type/SectorPreset.java index fec4fe2e2d..d27e8bfd0f 100644 --- a/core/src/mindustry/type/SectorPreset.java +++ b/core/src/mindustry/type/SectorPreset.java @@ -95,8 +95,8 @@ public class SectorPreset extends UnlockableContent{ } @Override - public void remove(){ - super.remove(); + public void removeContent(){ + super.removeContent(); if(sector != null && sector.preset == this){ sector.preset = null; } diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index dcb24ef207..fec80c8b4e 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -605,6 +605,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{ } boolean selectable(Planet planet){ + if(planet.removed) return false; if(mode == select) return planet == state.planet; if(mode == planetLaunch) return launchSector != null && (launchCandidates.contains(planet) || (planet == launchSector.planet && planet.allowSelfSectorLaunch)); return (planet.alwaysUnlocked && planet.isLandable()) || planet.sectors.contains(Sector::hasBase) || debugSelect; diff --git a/server/src/mindustry/server/ServerControl.java b/server/src/mindustry/server/ServerControl.java index c4121fba5f..9926e4e34c 100644 --- a/server/src/mindustry/server/ServerControl.java +++ b/server/src/mindustry/server/ServerControl.java @@ -578,10 +578,10 @@ public class ServerControl implements ApplicationListener{ info("Map directory: &fi@", customMapDirectory.file().getAbsoluteFile().toString()); }); - handler.register("reloadpatches", "Reload all patch files from disk.", arg -> { + handler.register("reloadassets", "Reload all content/patch asset files from disk.", arg -> { loadDataAssets(); if(dataAssets.isEmpty()){ - err("No valid content patch files found."); + err("No valid asset files found."); } });