From b472fed36d8a003f96675fcff9fcd2f18467e9e3 Mon Sep 17 00:00:00 2001 From: Anuken Date: Fri, 24 Oct 2025 11:51:39 -0400 Subject: [PATCH] More patcher tests and fixes --- core/src/mindustry/mod/ContentPatcher.java | 36 ++++++++-- tests/src/test/java/PatcherTests.java | 81 ++++++++++++++++++++++ 2 files changed, 111 insertions(+), 6 deletions(-) diff --git a/core/src/mindustry/mod/ContentPatcher.java b/core/src/mindustry/mod/ContentPatcher.java index 3c52a85c00..052753b603 100644 --- a/core/src/mindustry/mod/ContentPatcher.java +++ b/core/src/mindustry/mod/ContentPatcher.java @@ -142,12 +142,27 @@ public class ContentPatcher{ }else if(object instanceof Seq || object.getClass().isArray()){ //TODO if(field.equals("+")){ - var meta = new FieldData(metadata.elementType, null, null); + var meta = new FieldData(metadata.type.isArray() ? metadata.type.getComponentType() : metadata.elementType, null, null); + boolean multiAdd; + + if(value instanceof JsonValue jval && jval.isArray()){ + meta = metadata; + multiAdd = true; + }else{ + multiAdd = false; + } + //handle array addition syntax if(object instanceof Seq s){ modifiedField(parentObject, parentField, s.copy()); - assignValue(object, field, meta, () -> null, s::add, value, false); + assignValue(object, field, meta, () -> null, val -> { + if(multiAdd){ + s.addAll((Seq)val); + }else{ + s.add(val); + } + }, value, false); }else{ modifiedField(parentObject, parentField, copyArray(object)); @@ -158,9 +173,18 @@ public class ContentPatcher{ try{ //create copy array, put the new object in the last slot, and assign the parent's field to it int len = Array.getLength(fobj); - Object copy = Array.newInstance(fobj.getClass().getComponentType(), len + 1); - Array.set(copy, len - 1, val); - System.arraycopy(fobj, 0, copy, 0, len); + Object copy; + + if(multiAdd){ + int otherLen = Array.getLength(val); + copy = Array.newInstance(fobj.getClass().getComponentType(), len + otherLen); + System.arraycopy(val, 0, copy, len, otherLen); + System.arraycopy(fobj, 0, copy, 0, len); + }else{ + copy = Array.newInstance(fobj.getClass().getComponentType(), len + 1); + Array.set(copy, len, val); + System.arraycopy(fobj, 0, copy, 0, len); + } assign(fpo, fpf, copy, null, null, null); }catch(Exception e){ @@ -262,7 +286,7 @@ public class ContentPatcher{ if(value instanceof JsonValue jsv){ //setting values from object if(prevValue == null || !jsv.isObject() || jsv.has("type")){ - if(UnlockableContent.class.isAssignableFrom(metadata.type) && (jsv.isObject())){ + if(UnlockableContent.class.isAssignableFrom(metadata.type) && jsv.isObject()){ warn("New content must not be instantiated: @", jsv); return; } diff --git a/tests/src/test/java/PatcherTests.java b/tests/src/test/java/PatcherTests.java index 962a90589b..3eb1227359 100644 --- a/tests/src/test/java/PatcherTests.java +++ b/tests/src/test/java/PatcherTests.java @@ -1,6 +1,7 @@ import arc.struct.*; import mindustry.*; import mindustry.content.*; +import mindustry.entities.abilities.*; import mindustry.entities.bullet.*; import mindustry.type.*; import mindustry.world.blocks.units.*; @@ -115,4 +116,84 @@ public class PatcherTests{ assertEquals(2, UnitTypes.dagger.weapons.size); assertEquals("large-weapon", UnitTypes.dagger.weapons.get(0).name); } + + @Test + void testUnitAbilities() throws Exception{ + Vars.state.patcher.apply(Seq.with(""" + unit.dagger.abilities.+: { + type: ShieldArcAbility + max: 1000 + } + """)); + + assertEquals(1, UnitTypes.dagger.abilities.size); + assertEquals(ShieldArcAbility.class, UnitTypes.dagger.abilities.get(0).getClass()); + assertEquals(100f, ((ShieldArcAbility)UnitTypes.dagger.abilities.get(0)).max); + + Vars.logic.reset(); + + assertEquals(0, UnitTypes.dagger.abilities.size); + } + + @Test + void testUnitAbilitiesArray() throws Exception{ + Vars.state.patcher.apply(Seq.with(""" + unit.dagger.abilities.+: [ + { + type: ShieldArcAbility + max: 1000 + }, + { + type: MoveEffectAbility + amount: 10 + } + ] + """)); + + assertEquals(2, UnitTypes.dagger.abilities.size); + assertEquals(ShieldArcAbility.class, UnitTypes.dagger.abilities.get(0).getClass()); + assertEquals(1000f, ((ShieldArcAbility)UnitTypes.dagger.abilities.get(0)).max); + + assertEquals(MoveEffectAbility.class, UnitTypes.dagger.abilities.get(1).getClass()); + assertEquals(10, ((MoveEffectAbility)UnitTypes.dagger.abilities.get(1)).amount); + + Vars.logic.reset(); + + assertEquals(0, UnitTypes.dagger.abilities.size); + } + + @Test + void testUnitFlagsArray() throws Exception{ + int oldLength = UnitTypes.dagger.targetFlags.length; + + Vars.state.patcher.apply(Seq.with(""" + unit.dagger.targetFlags.+: [ + shield, drill + ] + """)); + + assertEquals(oldLength + 2, UnitTypes.dagger.targetFlags.length); + assertEquals(BlockFlag.shield, UnitTypes.dagger.targetFlags[UnitTypes.dagger.targetFlags.length - 2]); + assertEquals(BlockFlag.drill, UnitTypes.dagger.targetFlags[UnitTypes.dagger.targetFlags.length - 1]); + + Vars.logic.reset(); + + assertEquals(oldLength, UnitTypes.dagger.targetFlags.length); + } + + @Test + void testUnitFlags() throws Exception{ + int oldLength = UnitTypes.dagger.targetFlags.length; + + Vars.state.patcher.apply(Seq.with(""" + unit.dagger.targetFlags.+: shield + """)); + + assertEquals(oldLength + 1, UnitTypes.dagger.targetFlags.length); + assertEquals(BlockFlag.shield, UnitTypes.dagger.targetFlags[UnitTypes.dagger.targetFlags.length - 1]); + + Vars.logic.reset(); + + assertEquals(oldLength, UnitTypes.dagger.targetFlags.length); + } }