diff --git a/gradle.properties b/gradle.properties index 19e9e13..1aeca77 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -version = 1.0-alpha2 +version = 1.0-beta1 diff --git a/src/main/java/com/sovdee/oopsk/core/Struct.java b/src/main/java/com/sovdee/oopsk/core/Struct.java index a44cffe..8523a15 100644 --- a/src/main/java/com/sovdee/oopsk/core/Struct.java +++ b/src/main/java/com/sovdee/oopsk/core/Struct.java @@ -2,6 +2,7 @@ import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.util.ContextlessEvent; +import ch.njol.skript.registrations.Classes; import com.sovdee.oopsk.events.DynamicFieldEvalEvent; import org.bukkit.event.Event; import org.jetbrains.annotations.NotNull; @@ -28,7 +29,7 @@ public class Struct { * @param event The event to evaluate the default values in. * @see StructManager#createStruct(StructTemplate, Event) */ - Struct(@NotNull StructTemplate template, @Nullable Event event) { + public Struct(@NotNull StructTemplate template, @Nullable Event event) { this.template = template; fieldValues = new HashMap<>(); for (Field field : template.getFields()) { @@ -36,6 +37,25 @@ public class Struct { } } + /** + * Copy constructor for creating a struct that's a 'deep' copy of another struct. + * Uses {@link Classes#clone(Object)} to clone the field values. + * + * @param source The struct to copy from. + * @see StructManager#createStruct(StructTemplate, Event) + */ + public Struct(Struct source) { + this.template = source.template; + fieldValues = new HashMap<>(); + for (Map.Entry, Object[]> entry : source.fieldValues.entrySet()) { + Field field = entry.getKey(); + Object[] value = entry.getValue(); + // clone the value array + Object[] clonedValue = (Object[]) Classes.clone(value); + fieldValues.put(field, clonedValue); + } + } + /** * Creates a new struct with the given template and event. Allows a map of initial values to be set in the struct. * diff --git a/src/main/java/com/sovdee/oopsk/elements/expressions/ExprFieldAccess.java b/src/main/java/com/sovdee/oopsk/elements/expressions/ExprFieldAccess.java index 770485b..1308c1e 100644 --- a/src/main/java/com/sovdee/oopsk/elements/expressions/ExprFieldAccess.java +++ b/src/main/java/com/sovdee/oopsk/elements/expressions/ExprFieldAccess.java @@ -130,7 +130,7 @@ private boolean updateFieldGuesses() { @Override protected Object[] get(Event event, Struct[] source) { if (source.length == 0) - return null; + return new Object[0]; // get actual struct and template Struct struct = source[0]; StructTemplate template = struct.getTemplate(); @@ -138,7 +138,7 @@ protected Object[] get(Event event, Struct[] source) { Field field = template.getField(fieldName); if (field == null) { error("Field " + fieldName + " not found in struct " + template.getName()); - return null; + return new Object[0]; } var value = struct.getFieldValue(field); // check type is accurate to what we claimed @@ -153,7 +153,7 @@ protected Object[] get(Event event, Struct[] source) { // if the field is not valid, and the value is not convertible, error error("The " + field + " of " + struct + " is not the same type it claimed to be at parse time. " + "This likely was caused by template changes. Consider reloading this script."); - return null; + return new Object[0]; } // get the value return value; diff --git a/src/main/java/com/sovdee/oopsk/elements/expressions/ExprStructCopy.java b/src/main/java/com/sovdee/oopsk/elements/expressions/ExprStructCopy.java new file mode 100644 index 0000000..fe3a833 --- /dev/null +++ b/src/main/java/com/sovdee/oopsk/elements/expressions/ExprStructCopy.java @@ -0,0 +1,27 @@ +package com.sovdee.oopsk.elements.expressions; + +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import com.sovdee.oopsk.core.Struct; +import org.jetbrains.annotations.Nullable; + +public class ExprStructCopy extends SimplePropertyExpression { + + static { + register(ExprStructCopy.class, Struct.class, "[a] struct copy", "structs"); + } + + @Override + public @Nullable Struct convert(Struct struct) { + return new Struct(struct); + } + + @Override + public Class getReturnType() { + return Struct.class; + } + + @Override + protected String getPropertyName() { + return "copy"; + } +} diff --git a/src/test/scripts/copies.sk b/src/test/scripts/copies.sk new file mode 100644 index 0000000..44dcddb --- /dev/null +++ b/src/test/scripts/copies.sk @@ -0,0 +1,27 @@ +struct copyable: + copy_num: int + copy_vectors: vectors + +test "copy structs": + set {_A} to a copyable struct: + copy_num: 1 + copy_vectors: vector(1, 2, 3) and vector(4, 5, 6) + + assert {_A}->copy_num is 1 with "copy_num was not set correctly" + assert {_A}->copy_vectors is vector(1, 2, 3) and vector(4, 5, 6) with "copy_vectors was not set correctly" + + set {_B} to a struct copy of {_A} + assert {_B}->copy_num is 1 with "copy_num was not copied correctly" + assert {_B}->copy_vectors is vector(1, 2, 3) and vector(4, 5, 6) with "copy_vectors was not copied correctly" + + set {_B}->copy_num to 2 + assert {_A}->copy_num is 1 with "copy_num was changed in original after copying" + assert {_B}->copy_num is 2 with "copy_num was not changed in copy" + + set x of {_A}->copy_vectors to 10 + assert {_A}->copy_vectors is vector(10, 2, 3) and vector(10, 5, 6) with "copy_vectors was not changed in original" + assert {_B}->copy_vectors is vector(1, 2, 3) and vector(4, 5, 6) with "copy_vectors was changed in copy" + + set {_B}->copy_vectors to vector(7, 8, 9) and vector(10, 11, 12) + assert {_A}->copy_vectors is vector(10, 2, 3) and vector(10, 5, 6) with "copy_vectors was changed in original after copying" + assert {_B}->copy_vectors is vector(7, 8, 9) and vector(10, 11, 12) with "copy_vectors was not changed in copy"