More patcher tests + unit type reassign support
This commit is contained in:
@@ -742,7 +742,7 @@ public class ContentParser{
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
private Prov<Unit> unitType(JsonValue value){
|
Prov<Unit> unitType(JsonValue value){
|
||||||
if(value == null) return UnitEntity::create;
|
if(value == null) return UnitEntity::create;
|
||||||
return switch(value.asString()){
|
return switch(value.asString()){
|
||||||
case "flying" -> UnitEntity::create;
|
case "flying" -> UnitEntity::create;
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ public class ContentPatcher{
|
|||||||
currentlyApplying = null;
|
currentlyApplying = null;
|
||||||
|
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
|
PatchSet set = new PatchSet(patch, new JsonValue("error"));
|
||||||
|
set.error = true;
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -283,10 +288,10 @@ public class ContentPatcher{
|
|||||||
|
|
||||||
var fields = parser.getJson().getFields(actualType);
|
var fields = parser.getJson().getFields(actualType);
|
||||||
var fdata = fields.get(field);
|
var fdata = fields.get(field);
|
||||||
|
var fobj = object;
|
||||||
if(fdata != null){
|
if(fdata != null){
|
||||||
if(checkField(fdata.field)) return;
|
if(checkField(fdata.field)) return;
|
||||||
|
|
||||||
var fobj = object;
|
|
||||||
assignValue(object, field, new FieldData(fdata), () -> Reflect.get(fobj, fdata.field), fv -> {
|
assignValue(object, field, new FieldData(fdata), () -> Reflect.get(fobj, fdata.field), fv -> {
|
||||||
if(fv == null && !fdata.field.isAnnotationPresent(Nullable.class) && !(Vars.headless && ContentParser.implicitNullable.contains(fdata.field.getType()))){
|
if(fv == null && !fdata.field.isAnnotationPresent(Nullable.class) && !(Vars.headless && ContentParser.implicitNullable.contains(fdata.field.getType()))){
|
||||||
warn("Field '@' cannot be null.", fdata.field);
|
warn("Field '@' cannot be null.", fdata.field);
|
||||||
@@ -311,6 +316,9 @@ public class ContentPatcher{
|
|||||||
Log.err(e);
|
Log.err(e);
|
||||||
warn("Failed to read consumers for '@': @", bl, Strings.getSimpleMessage(e));
|
warn("Failed to read consumers for '@': @", bl, Strings.getSimpleMessage(e));
|
||||||
}
|
}
|
||||||
|
}else if(value instanceof JsonValue jsv && object instanceof UnitType && field.equals("type")){
|
||||||
|
var fmeta = fields.get("constructor");
|
||||||
|
assignValue(object, "constructor", new FieldData(fmeta), () -> Reflect.get(fobj, fmeta.field), val -> Reflect.set(fobj, fmeta.field, val), parser.unitType(jsv), true);
|
||||||
}else{
|
}else{
|
||||||
warn("Unknown field '@' for class '@'", field, actualType.getSimpleName());
|
warn("Unknown field '@' for class '@'", field, actualType.getSimpleName());
|
||||||
}
|
}
|
||||||
@@ -320,37 +328,41 @@ public class ContentPatcher{
|
|||||||
void assignValue(Object object, String field, FieldData metadata, Prov getter, Cons setter, Object value, boolean modify) throws Exception{
|
void assignValue(Object object, String field, FieldData metadata, Prov getter, Cons setter, Object value, boolean modify) throws Exception{
|
||||||
Object prevValue = getter.get();
|
Object prevValue = getter.get();
|
||||||
|
|
||||||
if(value instanceof JsonValue jsv){ //setting values from object
|
try{
|
||||||
if(prevValue == null || !jsv.isObject() || jsv.has("type")){
|
if(value instanceof JsonValue jsv){ //setting values from object
|
||||||
if(UnlockableContent.class.isAssignableFrom(metadata.type) && jsv.isObject()){
|
if(prevValue == null || !jsv.isObject() || jsv.has("type")){
|
||||||
warn("New content must not be instantiated: @", jsv);
|
if(UnlockableContent.class.isAssignableFrom(metadata.type) && jsv.isObject()){
|
||||||
return;
|
warn("New content must not be instantiated: @", jsv);
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(modify) modifiedField(object, field, getter.get());
|
if(modify) modifiedField(object, field, getter.get());
|
||||||
|
|
||||||
//HACK: listen for creation of objects once
|
//HACK: listen for creation of objects once
|
||||||
parser.listeners.add((type, jsonData, result) -> created(result, object));
|
parser.listeners.add((type, jsonData, result) -> created(result, object));
|
||||||
try{
|
try{
|
||||||
setter.get(parser.getJson().readValue(metadata.type, metadata.elementType, jsv));
|
setter.get(parser.getJson().readValue(metadata.type, metadata.elementType, jsv));
|
||||||
}catch(Throwable e){
|
}catch(Throwable e){
|
||||||
warn("Failed to read value @.@ = @: @ (type = @ elementType = @)\n@", object, field, value, e.getMessage(), metadata.type, metadata.elementType, Strings.getStackTrace(e));
|
warn("Failed to read value @.@ = @: @ (type = @ elementType = @)\n@", object, field, value, e.getMessage(), metadata.type, metadata.elementType, Strings.getStackTrace(e));
|
||||||
}
|
}
|
||||||
parser.listeners.pop();
|
parser.listeners.pop();
|
||||||
}else{
|
}else{
|
||||||
//assign each field manually
|
//assign each field manually
|
||||||
var childFields = parser.getJson().getFields(prevValue.getClass().isAnonymousClass() ? prevValue.getClass().getSuperclass() : prevValue.getClass());
|
var childFields = parser.getJson().getFields(prevValue.getClass().isAnonymousClass() ? prevValue.getClass().getSuperclass() : prevValue.getClass());
|
||||||
for(var child : jsv){
|
for(var child : jsv){
|
||||||
if(child.name != null){
|
if(child.name != null){
|
||||||
assign(prevValue, child.name, child, !childFields.containsKey(child.name) ? null : new FieldData(childFields.get(child.name)), object, field);
|
assign(prevValue, child.name, child, !childFields.containsKey(child.name) ? null : new FieldData(childFields.get(child.name)), object, field);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}else{
|
||||||
}else{
|
//direct value is set
|
||||||
//direct value is set
|
if(modify) modifiedField(object, field, prevValue);
|
||||||
if(modify) modifiedField(object, field, prevValue);
|
|
||||||
|
|
||||||
setter.get(value);
|
setter.get(value);
|
||||||
|
}
|
||||||
|
}catch(Throwable e){
|
||||||
|
warn("Failed to assign @.@ = @: @", object, field, value, Strings.getStackTrace(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,6 +488,7 @@ public class ContentPatcher{
|
|||||||
public String patch;
|
public String patch;
|
||||||
public JsonValue json;
|
public JsonValue json;
|
||||||
public String name;
|
public String name;
|
||||||
|
public boolean error;
|
||||||
public Seq<String> warnings = new Seq<>();
|
public Seq<String> warnings = new Seq<>();
|
||||||
|
|
||||||
public PatchSet(String patch, JsonValue json){
|
public PatchSet(String patch, JsonValue json){
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import mindustry.*;
|
|||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.entities.abilities.*;
|
import mindustry.entities.abilities.*;
|
||||||
import mindustry.entities.bullet.*;
|
import mindustry.entities.bullet.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.blocks.units.*;
|
import mindustry.world.blocks.units.*;
|
||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
@@ -197,6 +198,20 @@ public class PatcherTests{
|
|||||||
assertEquals(oldLength, UnitTypes.dagger.targetFlags.length);
|
assertEquals(oldLength, UnitTypes.dagger.targetFlags.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUnitType() throws Exception{
|
||||||
|
Vars.state.patcher.apply(Seq.with("""
|
||||||
|
unit.dagger.type: legs
|
||||||
|
"""));
|
||||||
|
|
||||||
|
assertEquals(0, Vars.state.patcher.patches.first().warnings.size);
|
||||||
|
assertEquals(LegsUnit.class, UnitTypes.dagger.constructor.get().getClass());
|
||||||
|
|
||||||
|
Vars.logic.reset();
|
||||||
|
|
||||||
|
assertEquals(MechUnit.class, UnitTypes.dagger.constructor.get().getClass());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCannotPatch() throws Exception{
|
void testCannotPatch() throws Exception{
|
||||||
Vars.state.patcher.apply(Seq.with("""
|
Vars.state.patcher.apply(Seq.with("""
|
||||||
@@ -207,6 +222,17 @@ public class PatcherTests{
|
|||||||
assertEquals(1, Blocks.conveyor.size);
|
assertEquals(1, Blocks.conveyor.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGibberish() throws Exception{
|
||||||
|
Vars.state.patcher.apply(Seq.with("""
|
||||||
|
}[35209509()jfkjhadsf,
|
||||||
|
,,,,,[]
|
||||||
|
]{
|
||||||
|
"""));
|
||||||
|
|
||||||
|
assertEquals(1, Vars.state.patcher.patches.first().warnings.size);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testUnknownFieldWarn() throws Exception{
|
void testUnknownFieldWarn() throws Exception{
|
||||||
Vars.state.patcher.apply(Seq.with("""
|
Vars.state.patcher.apply(Seq.with("""
|
||||||
@@ -218,7 +244,7 @@ public class PatcherTests{
|
|||||||
unit.dagger.frogs: 10
|
unit.dagger.frogs: 10
|
||||||
"""));
|
"""));
|
||||||
|
|
||||||
assertEquals(2, Vars.state.patcher.patches.first().warnings.size);
|
assertEquals(1, Vars.state.patcher.patches.first().warnings.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user