More tests, fixed patcher error handler

This commit is contained in:
Anuken 2025-10-25 22:24:32 -04:00
parent 09783898aa
commit 50e2b828f7
3 changed files with 77 additions and 7 deletions

View file

@ -3,8 +3,8 @@ package mindustry.mod;
import arc.func.*; import arc.func.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
import arc.util.serialization.*;
import arc.util.serialization.Json.*; import arc.util.serialization.Json.*;
import arc.util.serialization.*;
import arc.util.serialization.Jval.*; import arc.util.serialization.Jval.*;
import mindustry.*; import mindustry.*;
import mindustry.core.*; import mindustry.core.*;
@ -12,8 +12,10 @@ import mindustry.ctype.*;
import mindustry.entities.part.*; import mindustry.entities.part.*;
import mindustry.type.*; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.*;
import mindustry.world.consumers.*; import mindustry.world.consumers.*;
import mindustry.world.draw.*; import mindustry.world.draw.*;
import mindustry.world.meta.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
@ -81,10 +83,8 @@ public class ContentPatcher{
currentlyApplying = null; currentlyApplying = null;
}catch(Exception e){ }catch(Exception e){
PatchSet set = new PatchSet(patch, new JsonValue("error")); patches.peek().error = true;
set.error = true; patches.peek().warnings.add(Strings.getSimpleMessage(e));
set.warnings.add(Strings.getSimpleMessage(e));
patches.add(set);
Log.err("Failed to apply patch: " + patch, e); Log.err("Failed to apply patch: " + patch, e);
} }
@ -260,7 +260,23 @@ public class ContentPatcher{
}else if(object instanceof ObjectSet set && field.equals("+")){ }else if(object instanceof ObjectSet set && field.equals("+")){
modifiedField(parentObject, parentField, set.copy()); modifiedField(parentObject, parentField, set.copy());
assignValue(object, field, metadata, () -> null, val -> set.add(val), value, false); var meta = new FieldData(metadata.elementType, null, null);
boolean multiAdd;
if(value instanceof JsonValue jval && jval.isArray()){
meta = metadata;
multiAdd = true;
}else{
multiAdd = false;
}
assignValue(object, field, multiAdd ? meta : metadata, () -> null, val -> {
if(multiAdd){
set.addAll((ObjectSet)val);
}else{
set.add(val);
}
}, value, false);
}else if(object instanceof ObjectMap map){ }else if(object instanceof ObjectMap map){
if(metadata == null){ if(metadata == null){
warn("ObjectMap cannot be parsed without metadata: @.@", parentObject, parentField); warn("ObjectMap cannot be parsed without metadata: @.@", parentObject, parentField);
@ -282,6 +298,19 @@ public class ContentPatcher{
}else{ }else{
assignValue(object, field, new FieldData(metadata.elementType, null, null), () -> map.get(key), val -> map.put(key, val), value, false); assignValue(object, field, new FieldData(metadata.elementType, null, null), () -> map.get(key), val -> map.put(key, val), value, false);
} }
}else if(object instanceof Attributes map && value instanceof JsonValue jval){
Attribute key = Attribute.getOrNull(field);
if(key == null){
warn("Unknown attribute: '@'", field);
return;
}
if(!jval.isNumber()){
warn("Attribute value must be a number: '@'", jval);
return;
}
float prev = map.get(key);
reset(() -> map.set(key, prev));
map.set(key, jval.asFloat());
}else{ }else{
Class<?> actualType = object.getClass(); Class<?> actualType = object.getClass();
if(actualType.isAnonymousClass()) actualType = actualType.getSuperclass(); if(actualType.isAnonymousClass()) actualType = actualType.getSuperclass();
@ -330,7 +359,7 @@ public class ContentPatcher{
try{ try{
if(value instanceof JsonValue jsv){ //setting values from object if(value instanceof JsonValue jsv){ //setting values from object
if(prevValue == null || !jsv.isObject() || jsv.has("type")){ if(prevValue == null || !jsv.isObject() || jsv.has("type") || (metadata != null && metadata.type == Attributes.class)){
if(UnlockableContent.class.isAssignableFrom(metadata.type) && jsv.isObject()){ if(UnlockableContent.class.isAssignableFrom(metadata.type) && jsv.isObject()){
warn("New content must not be instantiated: @", jsv); warn("New content must not be instantiated: @", jsv);
return; return;

View file

@ -1,6 +1,7 @@
package mindustry.world.meta; package mindustry.world.meta;
import arc.struct.*; import arc.struct.*;
import arc.util.*;
import mindustry.*; import mindustry.*;
public class Attribute{ public class Attribute{
@ -47,6 +48,11 @@ public class Attribute{
return map.getThrow(name, () -> new IllegalArgumentException("Unknown Attribute type: " + name)); return map.getThrow(name, () -> new IllegalArgumentException("Unknown Attribute type: " + name));
} }
/** May return null. */
public static @Nullable Attribute getOrNull(String name){
return map.get(name);
}
/** @return Whether an attribute exists. */ /** @return Whether an attribute exists. */
public static boolean exists(String name){ public static boolean exists(String name){
return map.containsKey(name); return map.containsKey(name);

View file

@ -247,6 +247,41 @@ public class PatcherTests{
assertEquals(1, Vars.state.patcher.patches.first().warnings.size); assertEquals(1, Vars.state.patcher.patches.first().warnings.size);
} }
@Test
void testAttributes() throws Exception{
Vars.state.patcher.apply(Seq.with("""
block.grass.attributes: {
oil: 99
}
block.grass.attributes.heat: 77
"""));
assertEquals(new Seq<>(), Vars.state.patcher.patches.first().warnings);
assertEquals(99, Blocks.grass.attributes.get(Attribute.oil));
assertEquals(77, Blocks.grass.attributes.get(Attribute.heat));
Vars.logic.reset();
assertEquals(0, Blocks.grass.attributes.get(Attribute.oil));
assertEquals(0, Blocks.grass.attributes.get(Attribute.heat));
}
@Test
void testSetMultiAdd() throws Exception{
Vars.state.patcher.apply(Seq.with("""
unit.dagger.immunities.+: [slow, fast]
"""));
assertEquals(new Seq<>(), Vars.state.patcher.patches.first().warnings);
assertTrue(UnitTypes.dagger.immunities.contains(StatusEffects.slow));
assertTrue(UnitTypes.dagger.immunities.contains(StatusEffects.fast));
Vars.logic.reset();
assertFalse(UnitTypes.dagger.immunities.contains(StatusEffects.slow));
assertFalse(UnitTypes.dagger.immunities.contains(StatusEffects.fast));
}
@Test @Test
void testBigPatch() throws Exception{ void testBigPatch() throws Exception{
Vars.state.patcher.apply(Seq.with(""" Vars.state.patcher.apply(Seq.with("""