Data patcher unit controller support / Warnings for invalid sounds in JSON/DP

This commit is contained in:
Anuken
2025-12-15 11:19:47 -05:00
parent f795007715
commit 8fca45468e
3 changed files with 47 additions and 6 deletions

View File

@@ -28,6 +28,7 @@ import mindustry.entities.effect.*;
import mindustry.entities.part.*;
import mindustry.entities.part.DrawPart.*;
import mindustry.entities.pattern.*;
import mindustry.entities.units.*;
import mindustry.game.*;
import mindustry.game.Objectives.*;
import mindustry.gen.*;
@@ -62,6 +63,8 @@ public class ContentParser{
Seq<ParseListener> listeners = new Seq<>();
/** If false, arbitrary class names cannot be resolved with Class.forName. */
boolean allowClassResolution = true;
/** If false, sound asset loading is disabled. */
boolean allowAssetLoading = true;
ObjectMap<Class<?>, FieldParser> classParsers = new ObjectMap<>(){{
put(Effect.class, (type, data) -> {
@@ -298,11 +301,20 @@ public class ContentParser{
if(data.isArray()) return new RandomSound(parser.readValue(Sound[].class, data));
var field = fieldOpt(Sounds.class, data);
if(!allowAssetLoading && field == null){
warn("Sound not found: @", data.asString());
return Sounds.none;
}
return field != null ? field : Vars.tree.loadSound(data.asString());
});
put(Music.class, (type, data) -> {
var field = fieldOpt(Musics.class, data);
if(!allowAssetLoading && field == null){
warn("Music not found: @", data.asString());
return new Music();
}
return field != null ? field : Vars.tree.loadMusic(data.asString());
});
put(Objectives.Objective.class, (type, data) -> {
@@ -602,16 +614,15 @@ public class ContentParser{
}else{
throw new IllegalArgumentException("Missing a valid 'block' in 'requirements'");
}
}
if(value.has("controller") || value.has("aiController")){
unit.aiController = supply(resolve(value.getString("controller", value.getString("aiController", "")), FlyingAI.class));
unit.aiController = resolveController(value.getString("controller", value.getString("aiController", "")));
value.remove("controller");
}
if(value.has("defaultController")){
var sup = supply(resolve(value.getString("defaultController"), FlyingAI.class));
var sup = resolveController(value.getString("defaultController"));
unit.controller = u -> sup.get();
value.remove("defaultController");
}
@@ -1094,6 +1105,12 @@ public class ContentParser{
}
}
Prov<UnitController> resolveController(String type){
//this is used as a captured value to avoid parsing it multiple times
var controller = supply(resolve(type, FlyingAI.class));
return controller::get;
}
Object field(Class<?> type, JsonValue value){
return field(type, value.asString());
}

View File

@@ -10,6 +10,8 @@ import mindustry.*;
import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.entities.part.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.*;
@@ -54,6 +56,7 @@ public class DataPatcher{
}
};
cont.allowClassResolution = false;
cont.allowAssetLoading = false;
return cont;
}
@@ -351,7 +354,14 @@ public class DataPatcher{
var fields = parser.getJson().getFields(actualType);
var fdata = fields.get(field);
var fobj = object;
if(fdata != null){
if(value instanceof JsonValue jsv && object instanceof UnitType && field.equals("controller")){
var fmeta = fields.get("controller");
assignValue(object, "controller", new FieldData(fmeta), () -> Reflect.get(fobj, fmeta.field), val -> Reflect.set(fobj, fmeta.field, val), (Func<Unit, UnitController>)(u -> parser.resolveController(jsv.asString()).get()), true);
}else if(value instanceof JsonValue jsv && object instanceof UnitType && field.equals("aiController")){
var fmeta = fields.get("aiController");
assignValue(object, "aiController", new FieldData(fmeta), () -> Reflect.get(fobj, fmeta.field), val -> Reflect.set(fobj, fmeta.field, val), parser.resolveController(jsv.asString()), true);
}else if(fdata != null){
if(checkField(fdata.field)) return;
assignValue(object, field, new FieldData(fdata), () -> Reflect.get(fobj, fdata.field), fv -> {