diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index 7e5424b994..7648dabce0 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -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> implicitNullable = ObjectSet.with(TextureRegion.class, TextureRegion[].class, TextureRegion[][].class, TextureRegion[][][].class); ObjectMap, ContentType> contentTypes = new ObjectMap<>(); - ObjectSet> implicitNullable = ObjectSet.with(TextureRegion.class, TextureRegion[].class, TextureRegion[][].class, TextureRegion[][][].class); Seq listeners = new Seq<>(); ObjectMap, 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()){ diff --git a/core/src/mindustry/mod/ContentPatcher.java b/core/src/mindustry/mod/ContentPatcher.java index 052753b603..17d99e87a2 100644 --- a/core/src/mindustry/mod/ContentPatcher.java +++ b/core/src/mindustry/mod/ContentPatcher.java @@ -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()); diff --git a/core/src/mindustry/world/draw/DrawRegion.java b/core/src/mindustry/world/draw/DrawRegion.java index 5d2547890d..5bf7127eda 100644 --- a/core/src/mindustry/world/draw/DrawRegion.java +++ b/core/src/mindustry/world/draw/DrawRegion.java @@ -1,6 +1,7 @@ package mindustry.world.draw; import arc.*; +import arc.graphics.*; import arc.graphics.g2d.*; import arc.util.*; import mindustry.entities.units.*; @@ -11,6 +12,9 @@ import mindustry.world.*; public class DrawRegion extends DrawBlock{ public TextureRegion region; public String suffix = ""; + /** If set, overrides the region name. */ + public @Nullable String name; + public @Nullable Color color; public boolean spinSprite = false; public boolean drawPlan = true; public boolean buildingRotate = false; @@ -40,11 +44,13 @@ public class DrawRegion extends DrawBlock{ public void draw(Building build){ float z = Draw.z(); if(layer > 0) Draw.z(layer); + if(color != null) Draw.color(color); if(spinSprite){ Drawf.spinSprite(region, build.x + x, build.y + y, build.totalProgress() * rotateSpeed + rotation + (buildingRotate ? build.rotdeg() : 0)); }else{ Draw.rect(region, build.x + x, build.y + y, build.totalProgress() * rotateSpeed + rotation + (buildingRotate ? build.rotdeg() : 0)); } + if(color != null) Draw.color(); Draw.z(z); } @@ -65,6 +71,6 @@ public class DrawRegion extends DrawBlock{ @Override public void load(Block block){ - region = Core.atlas.find(block.name + suffix); + region = Core.atlas.find(name != null ? name : block.name + suffix); } } diff --git a/tests/src/test/java/PatcherTests.java b/tests/src/test/java/PatcherTests.java index b1c093397f..92b4071c67 100644 --- a/tests/src/test/java/PatcherTests.java +++ b/tests/src/test/java/PatcherTests.java @@ -196,4 +196,64 @@ public class PatcherTests{ assertEquals(oldLength, UnitTypes.dagger.targetFlags.length); } + + @Test + void testBigPatch() throws Exception{ + Vars.state.patcher.apply(Seq.with(""" + item: { + fissile-matter: { + hidden: false + fullIcon: duo-preview + uiIcon: block-duo-ui + } + } + block: { + pulverizer: { + consumes: { + remove: all + item: copper + } + uiIcon: block-duo-ui + region: block-duo-full + outputItems: [fissile-matter/1] + drawer: [ + { + type: DrawRegion + name: block-1 + } + { + type: DrawRegion + rotateSpeed: 1 + name: duo-preview + } + ] + } + } + unit: { + dagger: { + region: duo-preview + weapons: [ + { + x: 0 + y: 0 + reload: 20 + shoot: { + type: ShootAlternate + spread: 3.5 + } + bullet: { + width: 7 + height: 9 + lifetime: 60 + frontColor: eac1a8 + backColor: d39169 + } + } + ] + } + } + """)); + + assertEquals(new Seq<>(), Vars.state.patcher.patches.first().warnings); + } }