Better unknown field warnings for patcher
This commit is contained in:
@@ -59,6 +59,8 @@ public class ContentParser{
|
||||
|
||||
ObjectMap<Class<?>, ContentType> contentTypes = new ObjectMap<>();
|
||||
Seq<ParseListener> listeners = new Seq<>();
|
||||
/** If false, arbitrary class names cannot be resolved with Class.forName. */
|
||||
boolean allowClassResolution = true;
|
||||
|
||||
ObjectMap<Class<?>, FieldParser> classParsers = new ObjectMap<>(){{
|
||||
put(Effect.class, (type, data) -> {
|
||||
@@ -458,7 +460,7 @@ public class ContentParser{
|
||||
if(consumeType != Consume.class){
|
||||
block.removeConsumers(b -> consumeType.isAssignableFrom(b.getClass()));
|
||||
}else{
|
||||
Log.warn("Unknown consumer type '@' (Class: @) in consume: remove.", type, "Consume" + Strings.capitalize(type));
|
||||
warn("Unknown consumer type '@' (Class: @) in consume: remove.", type, "Consume" + Strings.capitalize(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -503,7 +505,7 @@ public class ContentParser{
|
||||
|
||||
if(locate(ContentType.block, name) != null){
|
||||
if(value.has("type")){
|
||||
Log.warn("Warning: '" + currentMod.name + "-" + name + "' re-declares a type. This will be interpreted as a new block. If you wish to override a vanilla block, omit the 'type' section, as vanilla block `type`s cannot be changed.");
|
||||
warn("Warning: '" + currentMod.name + "-" + name + "' re-declares a type. This will be interpreted as a new block. If you wish to override a vanilla block, omit the 'type' section, as vanilla block `type`s cannot be changed.");
|
||||
block = make(resolve(value.getString("type", ""), Block.class), mod + "-" + name);
|
||||
}else{
|
||||
block = locate(ContentType.block, name);
|
||||
@@ -1122,7 +1124,7 @@ public class ContentParser{
|
||||
FieldMetadata metadata = fields.get(child.name().replace(" ", "_"));
|
||||
if(metadata == null){
|
||||
if(ignoreUnknownFields){
|
||||
Log.warn("[@]: Ignoring unknown field: @ (@)", currentContent == null ? null : currentContent.minfo.sourceFile.name(), child.name, type.getSimpleName());
|
||||
warn("@Unknown field '@' for class '@'", currentContent == null ? "" : "[" + currentContent.minfo.sourceFile.name() + "]: ", child.name, type.getSimpleName());
|
||||
continue;
|
||||
}else{
|
||||
SerializationException ex = new SerializationException("Field not found: " + child.name + " (" + type.getName() + ")");
|
||||
@@ -1241,7 +1243,7 @@ public class ContentParser{
|
||||
TechNode parent = TechTree.all.find(t -> t.content.name.equals(researchName) || t.content.name.equals(currentMod.name + "-" + researchName) || t.content.name.equals(SaveVersion.mapFallback(researchName)));
|
||||
|
||||
if(parent == null){
|
||||
Log.warn("Content '" + researchName + "' isn't in the tech tree, but '" + unlock.name + "' requires it to be researched.");
|
||||
warn("Content '" + researchName + "' isn't in the tech tree, but '" + unlock.name + "' requires it to be researched.");
|
||||
}else{
|
||||
//add this node to the parent
|
||||
if(!parent.children.contains(node)){
|
||||
@@ -1252,7 +1254,7 @@ public class ContentParser{
|
||||
node.planet = parent.planet;
|
||||
}
|
||||
}else{
|
||||
Log.warn(unlock.name + " is not a root node, and does not have a `parent: ` property. Ignoring.");
|
||||
warn(unlock.name + " is not a root node, and does not have a `parent: ` property. Ignoring.");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1279,7 +1281,7 @@ public class ContentParser{
|
||||
if(out != null) return (Class<T>)out;
|
||||
|
||||
//try to resolve it as a raw class name
|
||||
if(base.indexOf('.') != -1){
|
||||
if(base.indexOf('.') != -1 && allowClassResolution){
|
||||
try{
|
||||
return (Class<T>)Class.forName(base);
|
||||
}catch(Exception ignored){
|
||||
@@ -1291,12 +1293,21 @@ public class ContentParser{
|
||||
}
|
||||
|
||||
if(def != null){
|
||||
if(warn) Log.warn("[@] No type '" + base + "' found, defaulting to type '" + def.getSimpleName() + "'", currentContent == null && currentMod != null ? currentMod.name : "");
|
||||
if(warn) warn("[@] No type '" + base + "' found, defaulting to type '" + def.getSimpleName() + "'", currentContent == null && currentMod != null ? currentMod.name : "");
|
||||
return def;
|
||||
}
|
||||
throw new IllegalArgumentException("Type not found: " + base);
|
||||
}
|
||||
|
||||
void warn(String string, Object... format){
|
||||
Log.warn(string, format);
|
||||
}
|
||||
|
||||
public Json getJson(){
|
||||
checkInit();
|
||||
return parser;
|
||||
}
|
||||
|
||||
private interface FieldParser{
|
||||
Object parse(Class<?> type, JsonValue value) throws Exception;
|
||||
}
|
||||
@@ -1305,11 +1316,6 @@ public class ContentParser{
|
||||
T parse(String mod, String name, JsonValue value) throws Exception;
|
||||
}
|
||||
|
||||
public Json getJson(){
|
||||
checkInit();
|
||||
return parser;
|
||||
}
|
||||
|
||||
//intermediate class for parsing
|
||||
static class UnitReq{
|
||||
public Block block;
|
||||
|
||||
@@ -23,8 +23,8 @@ import java.util.*;
|
||||
public class ContentPatcher{
|
||||
private static final Object root = new Object();
|
||||
private static final ObjectMap<String, ContentType> nameToType = new ObjectMap<>();
|
||||
private static ContentParser parser = createParser();
|
||||
|
||||
private Json json;
|
||||
private boolean applied;
|
||||
private ContentLoader contentLoader;
|
||||
private ObjectSet<Object> usedpatches = new ObjectSet<>();
|
||||
@@ -41,13 +41,27 @@ public class ContentPatcher{
|
||||
}
|
||||
}
|
||||
|
||||
static ContentParser createParser(){
|
||||
ContentParser cont = new ContentParser(){
|
||||
@Override
|
||||
void warn(String string, Object... format){
|
||||
//forward warnings to the current patcher - this is a bit hacky, but I do not want to re-initialize the parser every time
|
||||
if(Vars.state.patcher != null){
|
||||
Vars.state.patcher.warn(string, format);
|
||||
}
|
||||
}
|
||||
};
|
||||
cont.allowClassResolution = false;
|
||||
|
||||
return cont;
|
||||
}
|
||||
|
||||
/** Applies the specified patches. If patches were already applied, the previous ones are un-applied - they do not stack! */
|
||||
public void apply(Seq<String> patchArray) throws Exception{
|
||||
if(applied){
|
||||
unapply();
|
||||
applied = false;
|
||||
}
|
||||
json = Vars.mods.getContentParser().getJson();
|
||||
|
||||
applied = true;
|
||||
contentLoader = Vars.content.copy();
|
||||
@@ -55,7 +69,7 @@ public class ContentPatcher{
|
||||
|
||||
for(String patch : patchArray){
|
||||
try{
|
||||
JsonValue value = json.fromJson(null, Jval.read(patch).toString(Jformat.plain));
|
||||
JsonValue value = parser.getJson().fromJson(null, Jval.read(patch).toString(Jformat.plain));
|
||||
PatchSet set = new PatchSet(patch, value);
|
||||
patches.add(set);
|
||||
currentlyApplying = set;
|
||||
@@ -267,7 +281,7 @@ public class ContentPatcher{
|
||||
Class<?> actualType = object.getClass();
|
||||
if(actualType.isAnonymousClass()) actualType = actualType.getSuperclass();
|
||||
|
||||
var fields = json.getFields(actualType);
|
||||
var fields = parser.getJson().getFields(actualType);
|
||||
var fdata = fields.get(field);
|
||||
if(fdata != null){
|
||||
if(checkField(fdata.field)) return;
|
||||
@@ -292,13 +306,13 @@ public class ContentPatcher{
|
||||
after(bl::reinitializeConsumers);
|
||||
|
||||
try{
|
||||
Vars.mods.getContentParser().readBlockConsumers(bl, jsv);
|
||||
parser.readBlockConsumers(bl, jsv);
|
||||
}catch(Throwable e){
|
||||
Log.err(e);
|
||||
warn("Failed to read consumers for '@': @", bl, Strings.getSimpleMessage(e));
|
||||
}
|
||||
}else{
|
||||
warn("Unknown field: '@' for class '@'", field, actualType.getSimpleName());
|
||||
warn("Unknown field '@' for class '@'", field, actualType.getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -316,16 +330,16 @@ 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));
|
||||
parser.listeners.add((type, jsonData, result) -> created(result, object));
|
||||
try{
|
||||
setter.get(json.readValue(metadata.type, metadata.elementType, jsv));
|
||||
setter.get(parser.getJson().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();
|
||||
parser.listeners.pop();
|
||||
}else{
|
||||
//assign each field manually
|
||||
var childFields = json.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){
|
||||
if(child.name != null){
|
||||
assign(prevValue, child.name, child, !childFields.containsKey(child.name) ? null : new FieldData(childFields.get(child.name)), object, field);
|
||||
@@ -383,7 +397,7 @@ public class ContentPatcher{
|
||||
Class<?> actualType = object.getClass();
|
||||
if(actualType.isAnonymousClass()) actualType = actualType.getSuperclass();
|
||||
|
||||
var fields = json.getFields(actualType);
|
||||
var fields = parser.getJson().getFields(actualType);
|
||||
var fdata = fields.get(field);
|
||||
if(fdata != null){
|
||||
if(checkField(fdata.field)) return null;
|
||||
@@ -407,7 +421,7 @@ public class ContentPatcher{
|
||||
void modifiedField(Object target, String field, Object value){
|
||||
if(!applied || target == null) return;
|
||||
|
||||
var fields = json.getFields(target.getClass());
|
||||
var fields = parser.getJson().getFields(target.getClass());
|
||||
var meta = fields.get(field);
|
||||
if(meta != null){
|
||||
|
||||
@@ -431,7 +445,7 @@ public class ContentPatcher{
|
||||
}
|
||||
|
||||
Object convertKeyType(String string, Class<?> type){
|
||||
return json.fromJson(type, string);
|
||||
return parser.getJson().fromJson(type, string);
|
||||
}
|
||||
|
||||
void warn(String error, Object... fmt){
|
||||
|
||||
@@ -971,10 +971,6 @@ public class Mods implements Loadable{
|
||||
}
|
||||
}
|
||||
|
||||
public ContentParser getContentParser(){
|
||||
return parser;
|
||||
}
|
||||
|
||||
/** @return the mods that the client is missing.
|
||||
* The inputted array is changed to contain the extra mods that the client has but the server doesn't.*/
|
||||
public Seq<String> getIncompatibility(Seq<String> out){
|
||||
|
||||
Reference in New Issue
Block a user