Merge branch 'master' of https://github.com/Anuken/Mindustry into v9

This commit is contained in:
Anuken
2026-09-13 09:51:01 -04:00
9 changed files with 60 additions and 30 deletions
+1 -1
View File
@@ -2467,7 +2467,7 @@ split.pickup = 某些物品可以被核心單位撿起。\n撿起這個[accent]
split.pickup.mobile = 某些物品可以被核心單位撿起。\n撿起這個[accent]容器[],然後放到 [accent]重物裝載機[] 上。\n(要撿起或放下東西,請長按該物品。)
split.acquire = 您必須獲取一些鎢才能建造單位。
split.build = 單位必須被運送到牆的另一邊。\n在牆的兩側各放一個[accent]重物質量驅動器[]。\n通過按壓其中一個來設置連結,然後選擇另一個。
split.container = 類似於容器,單位也可以使用[accent]重物質量驅動器[]進行運輸。\n將一個單位兵工廠放置在重物裝載機旁邊以裝載它們,然後將它們送到牆的另一側以進攻敵方基地。
split.container = 類似於容器,單位也可以使用[accent]重物質量驅動器[]進行運輸。\n將一個單位兵工廠放置在重物質量驅動器旁邊以裝載它們,然後將它們送到牆的另一側以進攻敵方基地。
item.copper.description = 最基本的結構材料。在各種類型的方塊中廣泛使用。
item.copper.details = 銅,蕈孢星上異常常見的金屬。加工前結構脆弱。
+1
View File
@@ -414,6 +414,7 @@ public class Logic implements ApplicationListener{
//map is over, no more world processor objective stuff
state.rules.disableWorldProcessors = true;
state.markers.clear(); //TODO: should this optional?
Call.clearObjectives();
+7
View File
@@ -16,6 +16,13 @@ public class MapMarkers{
public Seq<ObjectiveMarker> mapMarkers = new Seq<>(false);
public Seq<ObjectiveMarker> lightMarkers = new Seq<>(false);
public void clear(){
worldMarkers.clear();
mapMarkers.clear();
lightMarkers.clear();
map.clear();
}
public void add(int id, ObjectiveMarker marker){
if(marker == null) return;
var prev = map.put(id, marker);
+9
View File
@@ -6,6 +6,7 @@ import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import arc.util.serialization.*;
import mindustry.content.*;
import mindustry.content.TechTree.*;
import mindustry.core.*;
@@ -554,6 +555,14 @@ public abstract class SaveVersion extends SaveFileReader{
public void readDataPatches(DataInput stream, SaveReadState saveState) throws IOException{
stream.readInt(); //version - ignored for now
//the requiredPlanets filter needs this, since the rules aren't read yet
if(headless){
try{
Planet planet = content.planet(new JsonReader().parse(saveState.ruleString).getString("planet", Planets.serpulo.name));
state.rules.planet = planet == null ? Planets.serpulo : planet;
}catch(Exception ignored){}
}
int total = stream.readInt();
Seq<DataAsset> assets = new Seq<>(total);
+1 -1
View File
@@ -2,7 +2,7 @@ package mindustry.mod;
/** Mod listing as a data class. */
public class ModListing{
public String repo, name, internalName, author, lastUpdated, description, minGameVersion, version;
public String repo, name, internalName, author, lastUpdated, description, minGameVersion, version, iconHash = "";
public boolean hasScripts, hasJava, iosCompatible, legacyCompatible, hasIcon;
public String[] contentTypes = {};
public int stars;
@@ -249,7 +249,7 @@ public class ModBrowserDialog extends BaseDialog{
if(mod.hasIcon){
Fi cacheFolder = Vars.mobile ? Core.files.cache("modIconCache"): dataDirectory.child("modIconCache");
cacheFolder.mkdirs();
Fi cacheFile = cacheFolder.child(Strings.sanitizeFilename(mod.repo + mod.lastUpdated) + ".png");
Fi cacheFile = cacheFolder.child(Strings.sanitizeFilename(mod.repo + "_" + mod.iconHash) + ".png");
if(!cacheFile.exists()){ //fetch from Github
ConsT<HttpResponse, Exception> fetch = res -> {
@@ -5,15 +5,14 @@ import arc.graphics.g2d.*;
import arc.math.*;
import arc.scene.ui.TextField.*;
import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import mindustry.annotations.Annotations.*;
import mindustry.content.*;
import mindustry.graphics.*;
import mindustry.entities.units.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.*;
@@ -39,18 +38,18 @@ public class TargetDummy extends Block{
underBullets = true;
targetable = false;
allowedInPayloads = false;
canOverdrive = false;
saveConfig = true;
config(FloatSeq.class, (TargetDummyBuild tile, FloatSeq config) -> {
if(config.size > 0){
tile.unitTeam = tile.team;
if(config.get(0) == 1) tile.unitTeam = Team.get(tile.dummyTeam());
}
if(config.size > 1) tile.boosting = config.get(1) == 1;
if(config.size > 2) tile.unitArmor = config.get(2);
if(config.size > 3) tile.resetTime = config.get(3);
if(config.size > 4) tile.dummySize = config.get(4);
config(int[].class, (TargetDummyBuild tile, int[] config) -> {
if(config.length != 5) return; //invalid, must have 5 values exactly
tile.unitTeam = tile.team;
if(config[0] == 1) tile.unitTeam = Team.get(tile.dummyTeam());
tile.boosting = config[1] == 1;
tile.unitArmor = config[2];
tile.resetTime = config[3];
tile.dummySize = Float.intBitsToFloat(config[4]);
});
}
@@ -241,15 +240,15 @@ public class TargetDummy extends Block{
t.background(Styles.black6);
t.defaults().left();
t.check(Core.bundle.get("rules.enemyteam"), unitTeam != team, b -> configureFloat(0, Mathf.num(b))).colspan(3).row();
t.check(Core.bundle.get("stat.flying"), boosting, b -> configureFloat(1, Mathf.num(b))).colspan(3).row();
t.check(Core.bundle.get("rules.enemyteam"), unitTeam != team, b -> configureInt(0, Mathf.num(b))).colspan(3).row();
t.check(Core.bundle.get("stat.flying"), boosting, b -> configureInt(1, Mathf.num(b))).colspan(3).row();
t.add(Core.bundle.get("stat.armor"));
t.field("" + (int)unitArmor, TextFieldFilter.digitsOnly, s -> configureFloat(2, Strings.parseInt(s))).valid(val -> Strings.parseInt(val, Integer.MAX_VALUE) < 100_000).width(200f).padLeft(8f).colspan(2).row();
t.field("" + (int)unitArmor, TextFieldFilter.digitsOnly, s -> configureInt(2, Strings.parseInt(s))).valid(val -> Strings.parseInt(val, Integer.MAX_VALUE) < 100_000).width(200f).padLeft(8f).colspan(2).row();
t.add(Core.bundle.get("stat.resettime"));
t.field(Strings.autoFixed(resetTime / 60f, 2), TextFieldFilter.floatsOnly, s -> configureFloat(3, Strings.parseFloat(s) * 60f)).valid(Strings::canParsePositiveFloat).padLeft(8f).growX();
t.field(Strings.autoFixed(resetTime / 60f, 2), TextFieldFilter.floatsOnly, s -> configureInt(3, (int)(Strings.parseFloat(s) * 60f))).valid(Strings::canParsePositiveFloat).padLeft(8f).growX();
t.add(StatUnit.seconds.localized()).padLeft(8).row();
t.add(Core.bundle.get("stat.hitsize"));
t.field("" + (dummySize/tilesize), TextFieldFilter.floatsOnly, s -> configureFloat(4, Strings.parseFloat(s) * tilesize))
t.field("" + (dummySize/tilesize), TextFieldFilter.floatsOnly, s -> configureInt(4, Float.floatToIntBits(Strings.parseFloat(s) * tilesize)))
.valid(val -> {
float parsed = Strings.parseFloat(val, Float.MAX_VALUE);
return parsed >= 0.1f && parsed <= 50f;
@@ -259,10 +258,10 @@ public class TargetDummy extends Block{
}
//helper to send the rest of values, since config does not support arrays
public void configureFloat(int index, float value){
FloatSeq seq = FloatSeq.with(Mathf.num(unitTeam != team), Mathf.num(boosting), unitArmor, resetTime, dummySize);
seq.set(index, value);
configure(seq);
public void configureInt(int index, int value){
int[] values = config();
values[index] = value;
configure(values);
}
public int dummyTeam(){
@@ -271,8 +270,9 @@ public class TargetDummy extends Block{
}
@Override
public Object config(){
return FloatSeq.with(Mathf.num(unitTeam != team), Mathf.num(boosting), unitArmor, resetTime, dummySize);
public int[] config(){
//note: float[] is not supported in build 160
return new int[]{Mathf.num(unitTeam != team), Mathf.num(boosting), (int)unitArmor, (int)resetTime, Float.floatToIntBits(dummySize)};
}
@Override
@@ -47,8 +47,10 @@ public class ItemModule extends BlockModule{
public void updateFlow(){
//update the flow at N fps at most
if(flowTimer.get(1, flowPollInterval)){
int len = content.items().size;
if(items.length != len) items = Arrays.copyOf(items, len);
if(flow == null){
if(flow == null || flow.length != len || cacheSums == null || cacheFlow == null){
if(cacheFlow == null || cacheFlow.length != items.length){
cacheFlow = new WindowedMean[items.length];
for(int i = 0; i < items.length; i++){
@@ -290,6 +292,10 @@ public class ItemModule extends BlockModule{
public void checkArrayCapacity(int size){
if(items.length != size) items = Arrays.copyOf(items, size);
cacheFlow = null;
cacheSums = null;
displayFlow = null;
flow = null;
}
@Override
@@ -20,9 +20,9 @@ public class LiquidModule extends BlockModule{
public static float flowVisualRefreshInterval = 15f;
private static final Interval flowTimer = new Interval(2);
private static WindowedMean[] cacheFlow;
private static float[] cacheSums;
private static float[] displayFlow;
private static @Nullable WindowedMean[] cacheFlow;
private static @Nullable float[] cacheSums;
private static @Nullable float[] displayFlow;
private static final Bits cacheBits = new Bits();
private float[] liquids = new float[content.liquids().size];
@@ -32,7 +32,10 @@ public class LiquidModule extends BlockModule{
public void updateFlow(){
if(flowTimer.get(1, flowPollInterval)){
if(flow == null){
int len = content.liquids().size;
if(liquids.length != len) liquids = Arrays.copyOf(liquids, len);
if(flow == null || flow.length != len || cacheSums == null || cacheFlow == null){
if(cacheFlow == null || cacheFlow.length != liquids.length){
cacheFlow = new WindowedMean[liquids.length];
for(int i = 0; i < liquids.length; i++){
@@ -152,6 +155,10 @@ public class LiquidModule extends BlockModule{
public void checkArrayCapacity(int size){
if(liquids.length != size) liquids = Arrays.copyOf(liquids, size);
cacheFlow = null;
cacheSums = null;
displayFlow = null;
flow = null;
}
@Override