More patcher tests and fixes

This commit is contained in:
Anuken
2025-10-24 20:30:08 -04:00
parent 6ff28b5d31
commit a305ac31e6
4 changed files with 96 additions and 4 deletions

View File

@@ -55,9 +55,9 @@ import static mindustry.Vars.*;
public class ContentParser{
private static final boolean ignoreUnknownFields = true;
private static final ContentType[] typesToSearch = {ContentType.block, ContentType.item, ContentType.unit, ContentType.liquid, ContentType.planet};
static final ObjectSet<Class<?>> implicitNullable = ObjectSet.with(TextureRegion.class, TextureRegion[].class, TextureRegion[][].class, TextureRegion[][][].class);
ObjectMap<Class<?>, ContentType> contentTypes = new ObjectMap<>();
ObjectSet<Class<?>> implicitNullable = ObjectSet.with(TextureRegion.class, TextureRegion[].class, TextureRegion[][].class, TextureRegion[][][].class);
Seq<ParseListener> listeners = new Seq<>();
ObjectMap<Class<?>, FieldParser> classParsers = new ObjectMap<>(){{
@@ -97,7 +97,7 @@ public class ContentParser{
}
}
});
put(TextureRegion.class, (type, data) -> Core.atlas.find(data.asString()));
put(TextureRegion.class, (type, data) -> Core.atlas == null ? null : Core.atlas.find(data.asString()));
put(Color.class, (type, data) -> Color.valueOf(data.asString()));
put(StatusEffect.class, (type, data) -> {
if(data.isString()){

View File

@@ -9,8 +9,11 @@ import arc.util.serialization.Jval.*;
import mindustry.*;
import mindustry.core.*;
import mindustry.ctype.*;
import mindustry.entities.part.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.consumers.*;
import mindustry.world.draw.*;
import java.lang.reflect.*;
import java.util.*;
@@ -99,6 +102,25 @@ public class ContentPatcher{
}
}
void created(Object object, Object parent){
if(!Vars.headless){
if(object instanceof DrawPart part && parent instanceof MappableContent cont){
part.load(cont.name);
}else if(object instanceof DrawBlock draw && parent instanceof Block block){
draw.load(block);
}else if(object instanceof Weapon weapon){
weapon.load();
weapon.init();
}else if(object instanceof Content cont){
cont.load();
}
}else{
if(object instanceof Weapon weapon){
weapon.init();
}
}
}
void assign(Object object, String field, Object value, @Nullable FieldData metadata, @Nullable Object parentObject, @Nullable String parentField) throws Exception{
if(field == null || field.isEmpty()) return;
@@ -252,7 +274,7 @@ public class ContentPatcher{
var fobj = object;
assignValue(object, field, new FieldData(fdata), () -> Reflect.get(fobj, fdata.field), fv -> {
if(fv == null && !fdata.field.isAnnotationPresent(Nullable.class)){
if(fv == null && !fdata.field.isAnnotationPresent(Nullable.class) && !(Vars.headless && ContentParser.implicitNullable.contains(fdata.field.getType()))){
warn("Field '@' cannot be null.", fdata.field);
return;
}
@@ -292,11 +314,15 @@ public class ContentPatcher{
}
if(modify) modifiedField(object, field, getter.get());
//HACK: listen for creation of objects once
Vars.mods.getContentParser().listeners.add((type, jsonData, result) -> created(result, object));
try{
setter.get(json.readValue(metadata.type, metadata.elementType, jsv));
}catch(Throwable e){
warn("Failed to read value @.@ = @: @ (type = @ elementType = @)\n@", object, field, value, e.getMessage(), metadata.type, metadata.elementType, Strings.getStackTrace(e));
}
Vars.mods.getContentParser().listeners.pop();
}else{
//assign each field manually
var childFields = json.getFields(prevValue.getClass().isAnonymousClass() ? prevValue.getClass().getSuperclass() : prevValue.getClass());