From 8ec12880792976678433b2c691c68aeab11b08ae Mon Sep 17 00:00:00 2001 From: DeadlyMC Date: Fri, 11 Oct 2019 18:28:37 +0530 Subject: [PATCH 01/10] flatWorldStructureSpawning --- .../mixins/FlatChunkGeneratorMixin.java | 58 +++++++++++++++++++ .../java/carpet/settings/CarpetSettings.java | 6 ++ src/main/resources/carpet.mixins.json | 1 + 3 files changed, 65 insertions(+) create mode 100644 src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java diff --git a/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java b/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java new file mode 100644 index 00000000..b4fdef36 --- /dev/null +++ b/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java @@ -0,0 +1,58 @@ +package carpet.mixins; + +import carpet.settings.CarpetSettings; +import net.minecraft.entity.EntityCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.source.BiomeSource; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.chunk.FlatChunkGenerator; +import net.minecraft.world.gen.chunk.FlatChunkGeneratorConfig; +import net.minecraft.world.gen.feature.Feature; +import org.spongepowered.asm.mixin.Mixin; + +import java.util.List; + +@Mixin(FlatChunkGenerator.class) +public abstract class FlatChunkGeneratorMixin extends ChunkGenerator +{ + public FlatChunkGeneratorMixin(IWorld iWorld, BiomeSource biome, FlatChunkGeneratorConfig chunkGeneratorConfig) + { + super(iWorld, biome, chunkGeneratorConfig); + } + + @Override + public List getEntitySpawnList(EntityCategory category, BlockPos pos) + { + if (CarpetSettings.flatWorldStructureSpawning) + { + if (Feature.SWAMP_HUT.method_14029(this.world, pos)) + { + if (category == EntityCategory.MONSTER) + { + return Feature.SWAMP_HUT.getMonsterSpawns(); + } + + if (category == EntityCategory.CREATURE) + { + return Feature.SWAMP_HUT.getCreatureSpawns(); + } + } + else if (category == EntityCategory.MONSTER) + { + if (Feature.PILLAGER_OUTPOST.isApproximatelyInsideStructure(this.world, pos)) + { + return Feature.PILLAGER_OUTPOST.getMonsterSpawns(); + } + + if (Feature.OCEAN_MONUMENT.isApproximatelyInsideStructure(this.world, pos)) + { + return Feature.OCEAN_MONUMENT.getMonsterSpawns(); + } + } + } + + return super.getEntitySpawnList(category, pos); + } +} diff --git a/src/main/java/carpet/settings/CarpetSettings.java b/src/main/java/carpet/settings/CarpetSettings.java index 2fff5bb4..f707a39d 100644 --- a/src/main/java/carpet/settings/CarpetSettings.java +++ b/src/main/java/carpet/settings/CarpetSettings.java @@ -445,4 +445,10 @@ public class CarpetSettings category = BUGFIX ) public static boolean horseWanderingFix = false; + + @Rule( + desc = "Allows structure mobs to spawn in flat worlds", + category = {EXPERIMENTAL, CREATIVE} + ) + public static boolean flatWorldStructureSpawning = false; } diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index 6d0fc634..901905a0 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -67,6 +67,7 @@ "PlayerEntity_parrotMixin", "SaplingBlockMixin", "EntityMixin", + "FlatChunkGeneratorMixin", "GuardianEntityMixin", "DesertPyramidFeatureMixin", From a84b06306adfc087e8f0fa3aa02f66b44e2cef5b Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 11 Oct 2019 11:11:02 -0300 Subject: [PATCH 02/10] . operator as lvalue --- src/main/java/carpet/script/Context.java | 1 + src/main/java/carpet/script/Expression.java | 23 ++++++++++---- .../carpet/script/value/FrameworkValue.java | 30 +++++++++++++++++++ .../script/value/FunctionSignatureValue.java | 24 ++------------- .../carpet/script/value/LContainerValue.java | 16 ++++++++++ 5 files changed, 67 insertions(+), 27 deletions(-) create mode 100644 src/main/java/carpet/script/value/FrameworkValue.java create mode 100644 src/main/java/carpet/script/value/LContainerValue.java diff --git a/src/main/java/carpet/script/Context.java b/src/main/java/carpet/script/Context.java index 6d39a603..5aaa1399 100644 --- a/src/main/java/carpet/script/Context.java +++ b/src/main/java/carpet/script/Context.java @@ -16,6 +16,7 @@ public class Context static final int ITERATOR = 6; static final int SIGNATURE = 7; static final int LOCALIZATION = 8; + static final int LVALUE = 9; private Map variables = new HashMap<>(); diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 7ffaabe8..6b037022 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -16,6 +16,7 @@ import carpet.script.value.AbstractListValue; import carpet.script.value.ContainerValueInterface; import carpet.script.value.FunctionSignatureValue; import carpet.script.value.GlobalValue; +import carpet.script.value.LContainerValue; import carpet.script.value.LazyListValue; import carpet.script.value.ListValue; import carpet.script.value.MapValue; @@ -1242,11 +1243,18 @@ public class Expression implements Cloneable */ public void Operators() { - addBinaryOperator(".", precedence.get("attribute~."),true, (container, key) -> + addLazyBinaryOperator(".", precedence.get("attribute~."),true, (c, t, container_lv, key_lv) -> { - if (container instanceof ContainerValueInterface) - return ((ContainerValueInterface) container).get(key); - throw new InternalExpressionException("Cannot access elements of a non-container"); + Value container = container_lv.evalValue(c); + if (!(container instanceof ContainerValueInterface)) + throw new InternalExpressionException("Cannot access elements of a non-container"); + Value address = key_lv.evalValue(c); + if (t != Context.LVALUE) + { + Value retVal = ((ContainerValueInterface) container).get(address); + return (cc, ct) -> retVal; + } + return (cc, ct) -> new LContainerValue((ContainerValueInterface) container, address); }); addBinaryOperator("+", precedence.get("addition+-"), true, Value::add); addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract); @@ -1290,7 +1298,7 @@ public class Expression implements Cloneable addLazyBinaryOperator("=", precedence.get("assign=<>"), false, (c, t, lv1, lv2) -> { - Value v1 = lv1.evalValue(c); + Value v1 = lv1.evalValue(c, Context.LVALUE); Value v2 = lv2.evalValue(c); if (v1 instanceof ListValue.ListConstructorValue && v2 instanceof ListValue) { @@ -1309,6 +1317,11 @@ public class Expression implements Cloneable } return (cc, tt) -> Value.TRUE; } + if (v1 instanceof LContainerValue) + { + Value ret = ((LContainerValue) v1).getContainer().put(((LContainerValue) v1).getAddress(), v2); + return (cc, tt) -> ret; + } v1.assertAssignable(); String varname = v1.getVariable(); Value copy = v2.reboundedTo(varname); diff --git a/src/main/java/carpet/script/value/FrameworkValue.java b/src/main/java/carpet/script/value/FrameworkValue.java new file mode 100644 index 00000000..cae758ab --- /dev/null +++ b/src/main/java/carpet/script/value/FrameworkValue.java @@ -0,0 +1,30 @@ +package carpet.script.value; + +import carpet.script.exception.ExpressionException; + +public abstract class FrameworkValue extends Value +{ + @Override + public String getString() + { + throw new ExpressionException("Scarpet language component cannot be used"); + } + + @Override + public boolean getBoolean() + { + throw new ExpressionException("Scarpet language component cannot be used"); + } + + @Override + public Value clone() + { + throw new ExpressionException("Scarpet language component cannot be used"); + } + + @Override + public int hashCode() + { + throw new UnsupportedOperationException("Scarpet language component cannot be used as map key"); + } +} diff --git a/src/main/java/carpet/script/value/FunctionSignatureValue.java b/src/main/java/carpet/script/value/FunctionSignatureValue.java index 48596a49..49903a00 100644 --- a/src/main/java/carpet/script/value/FunctionSignatureValue.java +++ b/src/main/java/carpet/script/value/FunctionSignatureValue.java @@ -4,29 +4,13 @@ import carpet.script.exception.ExpressionException; import java.util.List; -public class FunctionSignatureValue extends Value +public class FunctionSignatureValue extends FrameworkValue { private String identifier; private List arguments; private List globals; - @Override - public String getString() - { - throw new ExpressionException("Function "+identifier+" is not defined yet"); - } - @Override - public boolean getBoolean() - { - throw new ExpressionException("Function "+identifier+" is not defined yet"); - } - - @Override - public Value clone() - { - throw new ExpressionException("Function "+identifier+" is not defined yet"); - } public FunctionSignatureValue(String name, List args, List globals) { this.identifier = name; @@ -43,11 +27,7 @@ public class FunctionSignatureValue extends Value } public List getGlobals() {return globals;} - @Override - public int hashCode() - { - throw new UnsupportedOperationException("function signature value cannot be used as map key"); - } + } diff --git a/src/main/java/carpet/script/value/LContainerValue.java b/src/main/java/carpet/script/value/LContainerValue.java new file mode 100644 index 00000000..b95ae723 --- /dev/null +++ b/src/main/java/carpet/script/value/LContainerValue.java @@ -0,0 +1,16 @@ +package carpet.script.value; + +public class LContainerValue extends FrameworkValue +{ + private ContainerValueInterface container; + private Value address; + + public LContainerValue(ContainerValueInterface c, Value v) + { + container = c; + address = v; + } + + public ContainerValueInterface getContainer() {return container; } + public Value getAddress() {return address; } +} From 0957bb9b0cf27be6b622597475a697e4df1980de Mon Sep 17 00:00:00 2001 From: DeadlyMC Date: Fri, 11 Oct 2019 20:19:36 +0530 Subject: [PATCH 03/10] forgot to add desert temple spawns --- src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java b/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java index b4fdef36..b76d6cfe 100644 --- a/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java +++ b/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java @@ -45,6 +45,14 @@ public abstract class FlatChunkGeneratorMixin extends ChunkGenerator Date: Fri, 11 Oct 2019 20:31:02 +0530 Subject: [PATCH 04/10] added nether and end mobs --- .../mixins/FlatChunkGeneratorMixin.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java b/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java index b76d6cfe..91bfc51c 100644 --- a/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java +++ b/src/main/java/carpet/mixins/FlatChunkGeneratorMixin.java @@ -1,6 +1,7 @@ package carpet.mixins; import carpet.settings.CarpetSettings; +import net.minecraft.block.Blocks; import net.minecraft.entity.EntityCategory; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; @@ -58,6 +59,24 @@ public abstract class FlatChunkGeneratorMixin extends ChunkGenerator Date: Fri, 11 Oct 2019 13:39:29 -0300 Subject: [PATCH 05/10] . operator as lvalue --- src/main/resources/assets/carpet/scripts/camera.sc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/resources/assets/carpet/scripts/camera.sc b/src/main/resources/assets/carpet/scripts/camera.sc index b023b3d9..da531eb9 100644 --- a/src/main/resources/assets/carpet/scripts/camera.sc +++ b/src/main/resources/assets/carpet/scripts/camera.sc @@ -57,7 +57,7 @@ __add_path_segment(vector, duration, mode) -> if ( (l('sharp','smooth') ~ mode) == null, exit('use smooth or sharp point')); if(!global_points, exit('Cannot add point to path that didn\'t started yet!')); l(v, end_time, m) = global_points.(-1); - put(vector, -2, __adjusted_rot(v.(-2) , vector.(-2) )); + vector.(-2) = __adjusted_rot(v.(-2) , vector.(-2) ); global_points += l(vector, end_time+duration, mode) ); // adjusts current rotation so we don\'t spin around like crazy @@ -76,7 +76,7 @@ repeat(times, last_section_duration) -> positions = map(global_points, _.0); modes = map(global_points, _.(-1)); durations = map(global_points, global_points.(_i+1).1 - _.1 ); - put(durations, -1, last_section_duration); + durations.(-1) = last_section_duration; loop(times, loop( length(positions), __add_path_segment(positions._, durations._, modes._) @@ -92,7 +92,7 @@ speed(percentage) -> ); ratio = percentage/100; previous_path_length = global_points.(-1).1; - for(global_points, put(_, 1, _.1*ratio ) ); + for(global_points, _.1 = _. 1 *ratio ); undef('global_path_precalculated'); str('path %s from %d to %d ticks', if(ratio<1,'shortened','extended'), @@ -135,7 +135,7 @@ __get_path_at(segment, start, index) -> v = global_path_precalculated.(start+index); if(v == null, v = __find_position_for_point(segment, index); - put(global_path_precalculated, start+index, v) + global_path_precalculated.(start+index) = v ); v ); From 4dca3575e7e2c3d3f9e48a14147a581c2ea9e7c6 Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 11 Oct 2019 16:07:40 -0300 Subject: [PATCH 06/10] delete accepts lvalues, still need to be more full proofed. --- src/main/java/carpet/script/Expression.java | 22 +++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 6b037022..a10c16eb 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -2399,13 +2399,27 @@ public class Expression implements Cloneable } }); - addBinaryFunction("delete", (container, address) -> + addLazyFunction("delete", -1, (c, t, lv) -> { - if (container instanceof ContainerValueInterface) + Value containerOrLValue = lv.get(0).evalValue(c, Context.LVALUE); + ContainerValueInterface container; + Value address; + if (containerOrLValue instanceof LContainerValue) { - return ((ContainerValueInterface) container).delete(address); + container = ((LContainerValue) containerOrLValue).getContainer(); + address = ((LContainerValue) containerOrLValue).getAddress(); } - throw new InternalExpressionException("First argument of delete should be a container: list, map or nbt"); + else if (containerOrLValue instanceof ContainerValueInterface) + { + container = (ContainerValueInterface) containerOrLValue; + address = lv.get(1).evalValue(c); + } + else + { + throw new InternalExpressionException("First argument of delete should be a container: list, map or nbt"); + } + Value ret = container.delete(address); + return (cc, tt) -> ret; }); } From 18a211cd5b44b0407c358860d381b42b727f1f5d Mon Sep 17 00:00:00 2001 From: gnembon Date: Fri, 11 Oct 2019 17:06:57 -0300 Subject: [PATCH 07/10] delete accepts lvalues, still need to be more full proofed. --- src/main/java/carpet/script/Expression.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index a10c16eb..e55ac1f2 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -23,6 +23,7 @@ import carpet.script.value.MapValue; import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.Value; +import com.sun.xml.internal.fastinfoset.algorithm.IntEncodingAlgorithm; import org.apache.commons.lang3.text.WordUtils; import java.math.BigInteger; @@ -2401,6 +2402,8 @@ public class Expression implements Cloneable addLazyFunction("delete", -1, (c, t, lv) -> { + if (lv.size() < 1) + throw new InternalExpressionException("delete requires arguments"); Value containerOrLValue = lv.get(0).evalValue(c, Context.LVALUE); ContainerValueInterface container; Value address; @@ -2412,6 +2415,8 @@ public class Expression implements Cloneable else if (containerOrLValue instanceof ContainerValueInterface) { container = (ContainerValueInterface) containerOrLValue; + if (lv.size() < 2) + throw new InternalExpressionException("delete requires two arguments, container (list, map) and address"); address = lv.get(1).evalValue(c); } else From d59a4ba4597bfeb50f6b135bb3ec594cbee2da67 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 12 Oct 2019 00:41:07 -0300 Subject: [PATCH 08/10] changed to ':' --- src/main/java/carpet/script/Expression.java | 25 ++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index e55ac1f2..2695f85b 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -23,7 +23,6 @@ import carpet.script.value.MapValue; import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.Value; -import com.sun.xml.internal.fastinfoset.algorithm.IntEncodingAlgorithm; import org.apache.commons.lang3.text.WordUtils; import java.math.BigInteger; @@ -338,7 +337,7 @@ import static java.lang.Math.min; public class Expression implements Cloneable { private static final Map precedence = new HashMap() {{ - put("attribute~.", 80); + put("attribute~:", 80); put("unary+-!", 60); put("exponent^", 40); put("multiplication*/%", 30); @@ -1073,7 +1072,7 @@ public class Expression implements Cloneable * even if they look like them: *

*
    - *
  • Match, Get ~ .
  • + *
  • Match, Get ~ :
  • *
  • Unary + - !
  • *
  • Exponent ^
  • *
  • Multiplication * / %
  • @@ -1088,7 +1087,7 @@ public class Expression implements Cloneable *
  • Bracket ( )
  • *
* - *

Get, Accessor Operator .

+ *

Get, Accessor Operator :

*

Operator version of the get(...) function to access elements of lists, maps, and potentially other * containers (i.e. NBTs). It is important to distinguish from ~ operator, which is a matching operator, * which is expected to perform some extra computations to retrieve the result, while . should be @@ -1096,7 +1095,7 @@ public class Expression implements Cloneable * API, meaning get(...), put(...), delete(...), * and has(...) functions

*

WARNING: Unlike for some languages, where item access operator can be an L-value, to assign new values to - * container elements, use put function instead, i.e. a.1='foo' won't work.

+ * container elements, use put function instead, i.e. a:1='foo' won't work.

* *

Matching Operator ~

*

This operator should be understood as 'matches', 'contains', 'is_in', @@ -1244,9 +1243,19 @@ public class Expression implements Cloneable */ public void Operators() { - addLazyBinaryOperator(".", precedence.get("attribute~."),true, (c, t, container_lv, key_lv) -> + addLazyBinaryOperator(":", precedence.get("attribute~:"),true, (c, t, container_lv, key_lv) -> { Value container = container_lv.evalValue(c); + if (container instanceof LContainerValue) + { + ContainerValueInterface outerContainer = ((LContainerValue) container).getContainer(); + Value outerAddress = ((LContainerValue) container).getAddress(); + Value innerContainer = outerContainer.get(outerAddress); + if (!(innerContainer instanceof ContainerValueInterface)) + throw new InternalExpressionException("Cannot access elements of a non-container"); + Value innerLValue = new LContainerValue((ContainerValueInterface) innerContainer, key_lv.evalValue(c)); + return (cc, tt) -> innerLValue; + } if (!(container instanceof ContainerValueInterface)) throw new InternalExpressionException("Cannot access elements of a non-container"); Value address = key_lv.evalValue(c); @@ -2023,7 +2032,7 @@ public class Expression implements Cloneable *

Here is a list of operations that work on all types of containers: lists, maps, as well as other Minecraft * specific modifyable containers, like NBTs

* - *

get(container, address), '.' operator

+ *

get(container, address), ':' operator

*

Returns the value at address element from the value. * For lists it indicates an index, use negative numbers to reach elements from the end of the list. get * call will always be able to find the index. In case there is few items, it will loop over

@@ -2036,7 +2045,7 @@ public class Expression implements Cloneable * get(l(range(10)), 5) => 5 * get(l(range(10)), -1) => 9 * get(l(range(10)), 10) => 0 - * l(range(10)).93 => 3 + * l(range(10)):93 => 3 * * get(player() ~ 'nbt', 'Health') => 20 // inefficient way to get player health, use player() ~ 'health' instead * From 8b531834d0561f2c9769636ce217698b61239323 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 12 Oct 2019 01:18:14 -0300 Subject: [PATCH 09/10] changed to ':' --- src/main/java/carpet/script/Expression.java | 2 +- .../resources/assets/carpet/scripts/camera.sc | 54 +++++++++---------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 2695f85b..1851dfd0 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -1291,7 +1291,7 @@ public class Expression implements Cloneable return v2.getBoolean() ? ((cc, tt) -> v2) : LazyValue.FALSE; }); - addBinaryOperator("~", precedence.get("attribute~."), true, Value::in); + addBinaryOperator("~", precedence.get("attribute~:"), true, Value::in); addBinaryOperator(">", precedence.get("compare>=><=<"), false, (v1, v2) -> v1.compareTo(v2) > 0 ? Value.TRUE : Value.FALSE); diff --git a/src/main/resources/assets/carpet/scripts/camera.sc b/src/main/resources/assets/carpet/scripts/camera.sc index da531eb9..960ac306 100644 --- a/src/main/resources/assets/carpet/scripts/camera.sc +++ b/src/main/resources/assets/carpet/scripts/camera.sc @@ -56,8 +56,8 @@ __add_path_segment(vector, duration, mode) -> undef('global_path_precalculated'); if ( (l('sharp','smooth') ~ mode) == null, exit('use smooth or sharp point')); if(!global_points, exit('Cannot add point to path that didn\'t started yet!')); - l(v, end_time, m) = global_points.(-1); - vector.(-2) = __adjusted_rot(v.(-2) , vector.(-2) ); + l(v, end_time, m) = global_points:(-1); + vector:(-2) = __adjusted_rot(v:(-2) , vector:(-2) ); global_points += l(vector, end_time+duration, mode) ); // adjusts current rotation so we don\'t spin around like crazy @@ -73,13 +73,13 @@ __adjusted_rot(previous_rot, current_rot) -> repeat(times, last_section_duration) -> ( undef('global_path_precalculated'); - positions = map(global_points, _.0); - modes = map(global_points, _.(-1)); - durations = map(global_points, global_points.(_i+1).1 - _.1 ); - durations.(-1) = last_section_duration; + positions = map(global_points, _:0); + modes = map(global_points, _:(-1)); + durations = map(global_points, global_points:(_i+1):1 - _:1 ); + durations:(-1) = last_section_duration; loop(times, loop( length(positions), - __add_path_segment(positions._, durations._, modes._) + __add_path_segment(positions:_, durations:_, modes:_) ) ); str('Add %d points %d times', length(positions), times) @@ -91,13 +91,13 @@ speed(percentage) -> exit('path speed can only be speed, or slowed down 4 times. Recall command for larger changes') ); ratio = percentage/100; - previous_path_length = global_points.(-1).1; - for(global_points, _.1 = _. 1 *ratio ); + previous_path_length = global_points:(-1):1; + for(global_points, _:1 = _:1*ratio ); undef('global_path_precalculated'); str('path %s from %d to %d ticks', if(ratio<1,'shortened','extended'), previous_path_length, - global_points.(-1).1 + global_points:(-1):1 ) ); select_interpolation(method) -> @@ -132,14 +132,14 @@ __assert_valid_for_motion() -> ); __get_path_at(segment, start, index) -> ( - v = global_path_precalculated.(start+index); + v = global_path_precalculated:(start+index); if(v == null, v = __find_position_for_point(segment, index); - global_path_precalculated.(start+index) = v + global_path_precalculated:(start+index) = v ); v ); -__invalidate_points_cache() -> global_path_precalculated = map(range(global_points. (-1) . 1), null); +__invalidate_points_cache() -> global_path_precalculated = map(range(global_points:(-1):1), null); show() -> ( loop(100, @@ -160,8 +160,8 @@ play(fps) -> point = 0; loop( length(global_points)-1, segment = _; - start = global_points.segment.1; - end = global_points.(segment+1).1; + start = global_points:segment:1; + end = global_points:(segment+1):1; loop(end-start, v = __get_path_at(segment, start, _); modify(p, 'location', v); @@ -182,8 +182,8 @@ _show_path_tick(particle_type, total) -> __prepare_path_if_needed(); loop(total, segment = floor(rand(length(global_points)-1)); - start = global_points.segment.1; - end = global_points.(segment+1).1; + start = global_points:segment:1; + end = global_points:(segment+1):1; index = floor(rand(end-start)); l(x, y, z) = slice(__get_path_at(segment, start, index), 0, 3); particle(particle_type, x, y, z, 1, 0, 0) @@ -196,8 +196,8 @@ __prepare_path_if_needed_generic() -> ); __find_position_for_linear(segment, point) -> ( - l(va, start, mode_a) = global_points.segment; - l(vb, end, mode_b) = global_points.(segment+1); + l(va, start, mode_a) = global_points:segment; + l(vb, end, mode_b) = global_points:(segment+1); section = end-start; dt = point/section; dt*vb+(1-dt)*va @@ -209,15 +209,15 @@ __find_position_for_gauss(from_index, point) -> ( dev = global_interpol_option; components = l(); - path_point = global_points.from_index.1; + path_point = global_points:from_index:1; try( for(range(from_index+1, length(global_points)), - l(v,ptime,mode) = global_points._; + l(v,ptime,mode) = global_points:_; dev = if (global_interpol_option > 0, global_interpol_option, devs = l(); - if (_+1 < length(global_points), devs += global_points.(_+1).1-ptime); - if (_-1 >= 0, devs += ptime-global_points.(_-1).1); + if (_+1 < length(global_points), devs += global_points:(_+1):1-ptime); + if (_-1 >= 0, devs += ptime-global_points:(_-1):1); 0.6*reduce(devs, _a+_, 0)/length(devs) ); impact = __norm_prob(path_point+point, ptime, dev); @@ -228,11 +228,11 @@ __find_position_for_gauss(from_index, point) -> ); try( for(range(from_index, -1, -1), - l(v,ptime,mode) = global_points._; + l(v,ptime,mode) = global_points:_; dev = if (global_interpol_option > 0, global_interpol_option, devs = l(); - if (_+1 < length(global_points), devs += global_points.(_+1).1-ptime); - if (_-1 >= 0, devs += ptime-global_points.(_-1).1); + if (_+1 < length(global_points), devs += global_points:(_+1):1-ptime); + if (_-1 >= 0, devs += ptime-global_points:(_-1):1); 0.6*reduce(devs, _a+_, 0)/length(devs) ); impact = __norm_prob(path_point+point, ptime, dev); @@ -242,5 +242,5 @@ __find_position_for_gauss(from_index, point) -> ) ); total = rtotal+ltotal; - reduce(components, _a+_.0*(_.1/total), l(0,0,0,0,0)) + reduce(components, _a+_:0*(_:1/total), l(0,0,0,0,0)) ) \ No newline at end of file From 701a717135d6f2d2b6efc628f15f9afd8c7b74f2 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 13 Oct 2019 02:54:18 -0300 Subject: [PATCH 10/10] reworked container access (never throw, multi-field access, return values, operator), added package storage --- src/main/java/carpet/CarpetServer.java | 1 + .../java/carpet/script/CarpetExpression.java | 29 +++ .../carpet/script/CarpetScriptServer.java | 14 +- src/main/java/carpet/script/Expression.java | 202 ++++++++++++------ src/main/java/carpet/script/ScriptHost.java | 76 ++++++- .../carpet/script/bundled/FileModule.java | 80 ++++++- .../script/bundled/ModuleInterface.java | 5 + .../script/value/ContainerValueInterface.java | 10 +- .../java/carpet/script/value/ListValue.java | 29 +-- .../java/carpet/script/value/MapValue.java | 12 +- .../script/value/NBTSerializableValue.java | 17 +- src/main/java/carpet/script/value/Value.java | 8 +- 12 files changed, 369 insertions(+), 114 deletions(-) diff --git a/src/main/java/carpet/CarpetServer.java b/src/main/java/carpet/CarpetServer.java index 6711e796..b46928a9 100644 --- a/src/main/java/carpet/CarpetServer.java +++ b/src/main/java/carpet/CarpetServer.java @@ -111,6 +111,7 @@ public class CarpetServer // static for now - easier to handle all around the co public static void onServerClosed(MinecraftServer server) { + scriptServer.onClose(); LoggerRegistry.stopLoggers(); extensions.forEach(e -> e.onServerClosed(server)); } diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index cd1fc8a4..3ccea2b3 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -50,6 +50,7 @@ import net.minecraft.item.BlockItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; import net.minecraft.particle.ParticleEffect; import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.server.MinecraftServer; @@ -2873,6 +2874,34 @@ public class CarpetExpression CarpetServer.scriptServer.events.scheduleCall(cc, funname, args, delay); return (c_, t_) -> Value.TRUE; }); + + this.expr.addLazyFunction("get_global_state", -1, (c, t, lv) -> + { + String file = null; + if (lv.size()>0) + file = lv.get(0).evalValue(c).getString(); + Tag state = ((CarpetContext)c).host.getGlobalState(file); + if (state == null) + return (cc, tt) -> Value.NULL; + Value retVal = new NBTSerializableValue(state); + return (cc, tt) -> retVal; + }); + + this.expr.addLazyFunction("set_global_state", -1, (c, t, lv) -> + { + if (lv.size() == 0) + throw new InternalExpressionException("save_state needs nbt tag and optional file"); + Value val = lv.get(0).evalValue(c); + String file = null; + if (lv.size()>1) + file = lv.get(1).evalValue(c).getString(); + NBTSerializableValue tagValue = (val instanceof NBTSerializableValue) + ? (NBTSerializableValue) val + : new NBTSerializableValue(val.getString()); + Tag tag = tagValue.getTag(); + ((CarpetContext)c).host.setGlobalState(tag, file); + return (cc, tt) -> Value.NULL; + }); } /** diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index c03d67bb..c19f8fa8 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -126,7 +126,7 @@ public class CarpetScriptServer private ScriptHost createMinecraftScriptHost(String name, ModuleInterface module, boolean perPlayer, ServerCommandSource source) { - ScriptHost host = new ScriptHost(name, module, perPlayer ); + ScriptHost host = new ScriptHost(name, module, perPlayer, null ); host.globalVariables.put("_x", (c, t) -> Value.ZERO); host.globalVariables.put("_y", (c, t) -> Value.ZERO); host.globalVariables.put("_z", (c, t) -> Value.ZERO); @@ -360,5 +360,17 @@ public class CarpetScriptServer public void tick() { events.tick(); + for (ScriptHost host : modules.values()) + { + host.tick(); + } + } + + public void onClose() + { + for (ScriptHost host : modules.values()) + { + host.onClose(); + } } } diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 1851dfd0..1ba0bc63 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -1243,29 +1243,6 @@ public class Expression implements Cloneable */ public void Operators() { - addLazyBinaryOperator(":", precedence.get("attribute~:"),true, (c, t, container_lv, key_lv) -> - { - Value container = container_lv.evalValue(c); - if (container instanceof LContainerValue) - { - ContainerValueInterface outerContainer = ((LContainerValue) container).getContainer(); - Value outerAddress = ((LContainerValue) container).getAddress(); - Value innerContainer = outerContainer.get(outerAddress); - if (!(innerContainer instanceof ContainerValueInterface)) - throw new InternalExpressionException("Cannot access elements of a non-container"); - Value innerLValue = new LContainerValue((ContainerValueInterface) innerContainer, key_lv.evalValue(c)); - return (cc, tt) -> innerLValue; - } - if (!(container instanceof ContainerValueInterface)) - throw new InternalExpressionException("Cannot access elements of a non-container"); - Value address = key_lv.evalValue(c); - if (t != Context.LVALUE) - { - Value retVal = ((ContainerValueInterface) container).get(address); - return (cc, ct) -> retVal; - } - return (cc, ct) -> new LContainerValue((ContainerValueInterface) container, address); - }); addBinaryOperator("+", precedence.get("addition+-"), true, Value::add); addBinaryOperator("-", precedence.get("addition+-"), true, Value::subtract); addBinaryOperator("*", precedence.get("multiplication*/%"), true, Value::multiply); @@ -1329,8 +1306,12 @@ public class Expression implements Cloneable } if (v1 instanceof LContainerValue) { - Value ret = ((LContainerValue) v1).getContainer().put(((LContainerValue) v1).getAddress(), v2); - return (cc, tt) -> ret; + ContainerValueInterface container = ((LContainerValue) v1).getContainer(); + if (container == null) + return (cc, tt) -> Value.NULL; + Value address = ((LContainerValue) v1).getAddress(); + if (!(container.put(address, v2))) return (cc, tt) -> Value.NULL; + return (cc, tt) -> v2; } v1.assertAssignable(); String varname = v1.getVariable(); @@ -2341,13 +2322,13 @@ public class Expression implements Cloneable addUnaryFunction("keys", v -> { if (v instanceof MapValue) return new ListValue(((MapValue) v).getMap().keySet()); - throw new InternalExpressionException("keys applies only to maps"); + return Value.NULL; }); addUnaryFunction("values", v -> { if (v instanceof MapValue) return new ListValue(((MapValue) v).getMap().values()); - throw new InternalExpressionException("keys applies only to maps"); + return Value.NULL; }); addUnaryFunction("pairs", v -> { @@ -2355,21 +2336,93 @@ public class Expression implements Cloneable return ListValue.wrap(((MapValue) v).getMap().entrySet().stream().map( (p) -> ListValue.of(p.getKey(), p.getValue()) ).collect(Collectors.toList())); - throw new InternalExpressionException("pairs applies only to maps"); + return Value.NULL; }); - addBinaryFunction("get", (container, key) -> + addLazyBinaryOperator(":", precedence.get("attribute~:"),true, (c, t, container_lv, key_lv) -> { - if (container instanceof ContainerValueInterface) - return ((ContainerValueInterface) container).get(key); - throw new InternalExpressionException("Cannot access elements of a non-container"); + Value container = container_lv.evalValue(c); + if (container instanceof LContainerValue) + { + ContainerValueInterface outerContainer = ((LContainerValue) container).getContainer(); + if (outerContainer == null) + { + Value innerLValue = new LContainerValue(null, null); + return (cc, tt) -> innerLValue; + } + Value innerContainer = outerContainer.get(((LContainerValue) container).getAddress()); + if (!(innerContainer instanceof ContainerValueInterface)) + { + Value innerLValue = new LContainerValue(null, null); + return (cc, tt) -> innerLValue; + } + Value innerLValue = new LContainerValue((ContainerValueInterface) innerContainer, key_lv.evalValue(c)); + return (cc, tt) -> innerLValue; + } + if (!(container instanceof ContainerValueInterface)) + return (cc, tt) -> Value.NULL; + Value address = key_lv.evalValue(c); + if (t != Context.LVALUE) + { + Value retVal = ((ContainerValueInterface) container).get(address); + return (cc, ct) -> retVal; + } + Value retVal = new LContainerValue((ContainerValueInterface) container, address); + return (cc, ct) -> retVal; }); - addBinaryFunction("has", (container, key) -> + addLazyFunction("get", -1, (c, t, lv) -> { - if (container instanceof ContainerValueInterface) - return new NumericValue(((ContainerValueInterface) container).has(key)); - throw new InternalExpressionException("Cannot access elements of a non-container"); + if (lv.size() == 0) + throw new InternalExpressionException("get requires parameters"); + if (lv.size() == 1) + { + Value v = lv.get(0).evalValue(c, Context.LVALUE); + if (!(v instanceof LContainerValue)) + return (cc, tt) -> Value.NULL; + ContainerValueInterface container = ((LContainerValue) v).getContainer(); + if (container == null) + return (cc, tt) -> Value.NULL; + Value ret = container.get(((LContainerValue) v).getAddress()); + return (cc, tt) -> ret; + } + Value container = lv.get(0).evalValue(c); + for (int i = 1; i < lv.size(); i++) + { + if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL; + container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c)); + } + if (container == null) + return (cc, tt) -> Value.NULL; + Value finalContainer = container; + return (cc, tt) -> finalContainer; + }); + + addLazyFunction("has", -1, (c, t, lv) -> + { + if (lv.size() == 0) + throw new InternalExpressionException("get requires parameters"); + if (lv.size() == 1) + { + Value v = lv.get(0).evalValue(c, Context.LVALUE); + if (!(v instanceof LContainerValue)) + return (cc, tt) -> Value.NULL; + ContainerValueInterface container = ((LContainerValue) v).getContainer(); + if (container == null) + return (cc, tt) -> Value.NULL; + Value ret = new NumericValue(container.has(((LContainerValue) v).getAddress())); + return (cc, tt) -> ret; + } + Value container = lv.get(0).evalValue(c); + for (int i = 1; i < lv.size()-1; i++) + { + if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL; + container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c)); + } + if (!(container instanceof ContainerValueInterface)) + return (cc, tt) -> Value.NULL; + Value ret = new NumericValue(((ContainerValueInterface) container).has(lv.get(lv.size()-1).evalValue(c))); + return (cc, tt) -> ret; }); //Deprecated, use "get" instead, or . operator @@ -2386,53 +2439,68 @@ public class Expression implements Cloneable return items.get((int)index); }); - addFunction("put", (lv) -> + addLazyFunction("put", -1, (c, t, lv) -> { + if(lv.size()<2) + { + throw new InternalExpressionException("put takes at least three arguments, a container, address, and values to insert at that index"); + } + Value container = lv.get(0).evalValue(c, Context.LVALUE); + if (container instanceof LContainerValue) + { + ContainerValueInterface internalContainer = ((LContainerValue) container).getContainer(); + if (internalContainer == null) + { + return (cc, tt) -> Value.NULL; + } + Value address = ((LContainerValue) container).getAddress(); + Value what = lv.get(1).evalValue(c); + Value retVal = new NumericValue( (lv.size() > 2) + ? internalContainer.put(address, what, lv.get(3).evalValue(c)) + : internalContainer.put(address, what)); + return (cc, tt) -> retVal; + + } if(lv.size()<3) { throw new InternalExpressionException("put takes at least three arguments, a container, address, and values to insert at that index"); } - Value container = lv.get(0); if (!(container instanceof ContainerValueInterface)) { - throw new InternalExpressionException("First argument of put should be a container: list, map or nbt"); - } - Value where = lv.get(1); - Value what = lv.get(2); - if (lv.size()>3) - { - return ((ContainerValueInterface) container).put(where, what, lv.get(3)); - } - else - { - return ((ContainerValueInterface) container).put(where, what); + return (cc, tt) -> Value.NULL; } + Value where = lv.get(1).evalValue(c); + Value what = lv.get(2).evalValue(c); + Value retVal = new NumericValue( (lv.size()>3) + ? ((ContainerValueInterface) container).put(where, what, lv.get(3).evalValue(c)) + : ((ContainerValueInterface) container).put(where, what)); + return (cc, tt) -> retVal; }); addLazyFunction("delete", -1, (c, t, lv) -> { - if (lv.size() < 1) - throw new InternalExpressionException("delete requires arguments"); - Value containerOrLValue = lv.get(0).evalValue(c, Context.LVALUE); - ContainerValueInterface container; - Value address; - if (containerOrLValue instanceof LContainerValue) + if (lv.size() == 0) + throw new InternalExpressionException("delete requires parameters"); + if (lv.size() == 1) { - container = ((LContainerValue) containerOrLValue).getContainer(); - address = ((LContainerValue) containerOrLValue).getAddress(); + Value v = lv.get(0).evalValue(c, Context.LVALUE); + if (!(v instanceof LContainerValue)) + return (cc, tt) -> Value.NULL; + ContainerValueInterface container = ((LContainerValue) v).getContainer(); + if (container == null) + return (cc, tt) -> Value.NULL; + Value ret = new NumericValue(container.delete(((LContainerValue) v).getAddress())); + return (cc, tt) -> ret; } - else if (containerOrLValue instanceof ContainerValueInterface) + Value container = lv.get(0).evalValue(c); + for (int i = 1; i < lv.size()-1; i++) { - container = (ContainerValueInterface) containerOrLValue; - if (lv.size() < 2) - throw new InternalExpressionException("delete requires two arguments, container (list, map) and address"); - address = lv.get(1).evalValue(c); + if (!(container instanceof ContainerValueInterface)) return (cc, tt) -> Value.NULL; + container = ((ContainerValueInterface) container).get(lv.get(i).evalValue(c)); } - else - { - throw new InternalExpressionException("First argument of delete should be a container: list, map or nbt"); - } - Value ret = container.delete(address); + if (!(container instanceof ContainerValueInterface)) + return (cc, tt) -> Value.NULL; + Value ret = new NumericValue(((ContainerValueInterface) container).delete(lv.get(lv.size()-1).evalValue(c))); return (cc, tt) -> ret; }); } diff --git a/src/main/java/carpet/script/ScriptHost.java b/src/main/java/carpet/script/ScriptHost.java index a73f2cb0..f0901383 100644 --- a/src/main/java/carpet/script/ScriptHost.java +++ b/src/main/java/carpet/script/ScriptHost.java @@ -9,6 +9,7 @@ import carpet.script.value.NumericValue; import carpet.script.value.StringValue; import carpet.script.value.Value; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.nbt.Tag; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.math.BlockPos; @@ -25,18 +26,25 @@ import static java.lang.Math.max; public class ScriptHost { - public final Map userHosts = new HashMap<>(); + private final Map userHosts = new HashMap<>(); public Map globalFunctions = new HashMap<>(); public Map globalVariables = new HashMap<>(); + private Tag globalState; + private int saveTimeout; + + private ScriptHost parent; + private String name; public String getName() {return name;} private final ModuleInterface myCode; - public final boolean perUser; + private final boolean perUser; - ScriptHost(String name, ModuleInterface code, boolean perUser) + ScriptHost(String name, ModuleInterface code, boolean perUser, ScriptHost parent) { + this.saveTimeout = 0; + this.parent = parent; this.name = name; this.myCode = code; this.perUser = perUser; @@ -50,16 +58,19 @@ public class ScriptHost globalVariables.put("_", (c, t) -> Value.ZERO); globalVariables.put("_i", (c, t) -> Value.ZERO); globalVariables.put("_a", (c, t) -> Value.ZERO); + + if (parent == null && name != null) + globalState = loadState(); } - public ScriptHost retrieveForExecution(String /*Nullable*/ user) + private ScriptHost retrieveForExecution(String /*Nullable*/ user) { if (!perUser) return this; ScriptHost userHost = userHosts.get(user); if (userHost != null) return userHost; - userHost = new ScriptHost(this.name, myCode, false); + userHost = new ScriptHost(this.name, myCode, false, this); userHost.globalVariables.putAll(this.globalVariables); userHost.globalFunctions.putAll(this.globalFunctions); userHosts.put(user, userHost); @@ -221,5 +232,60 @@ public class ScriptHost } } + private void dumpState() + { + myCode.saveData(null, globalState); + } + private Tag loadState() + { + return myCode.getData(null); + } + + public Tag getGlobalState(String file) + { + if (name == null || myCode.isInternal()) return null; + if (file != null) + myCode.getData(file); + if (parent == null) + return globalState; + return parent.globalState; + } + + public void setGlobalState(Tag tag, String file) + { + if (name == null || myCode.isInternal()) return; + + if (file!= null) + { + myCode.saveData(file, tag); + return; + } + + ScriptHost responsibleHost = (parent != null)?parent:this; + responsibleHost.globalState = tag; + if (responsibleHost.saveTimeout == 0) + { + responsibleHost.dumpState(); + responsibleHost.saveTimeout = 200; + } + } + + public void tick() + { + if (this.saveTimeout > 0) + { + this.saveTimeout --; + if (this.saveTimeout == 0) + { + dumpState(); + } + } + } + + public void onClose() + { + if (this.saveTimeout > 0) + dumpState(); + } } diff --git a/src/main/java/carpet/script/bundled/FileModule.java b/src/main/java/carpet/script/bundled/FileModule.java index f6edef71..b9d45b22 100644 --- a/src/main/java/carpet/script/bundled/FileModule.java +++ b/src/main/java/carpet/script/bundled/FileModule.java @@ -1,9 +1,15 @@ package carpet.script.bundled; import carpet.CarpetServer; +import net.minecraft.nbt.EndTag; +import net.minecraft.nbt.PositionTracker; +import net.minecraft.nbt.Tag; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.File; -import java.io.FileReader; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.util.Locale; @@ -42,4 +48,76 @@ public class FileModule implements ModuleInterface { return code; } + + @Override + public boolean isInternal() + { + return false; + } + + //copied private method from net.minecraft.nbt.NbtIo.read() + private static Tag read(File file) + { + try (DataInputStream dataInput_1 = new DataInputStream(new FileInputStream(file))) + { + byte byte_1 = dataInput_1.readByte(); + if (byte_1 == 0) + { + return new EndTag(); + } + else + { + dataInput_1.readUTF(); + Tag tag_1 = Tag.createTag(byte_1); + tag_1.read(dataInput_1, 0, PositionTracker.DEFAULT); + return tag_1; + } + } + catch (IOException ignored) + { + } + return null; + } + + //copied private method from net.minecraft.nbt.NbtIo.write() and client method safe_write + private static void write(Tag tag_1, File file) + { + File file_2 = new File(file.getAbsolutePath() + "_tmp"); + if (file_2.exists()) file_2.delete(); + + try(DataOutputStream dataOutputStream_1 = new DataOutputStream(new FileOutputStream(file_2))) + { + dataOutputStream_1.writeByte(tag_1.getType()); + if (tag_1.getType() != 0) + { + dataOutputStream_1.writeUTF(""); + tag_1.write(dataOutputStream_1); + } + } + catch (IOException e) + { + return; + } + if (file.exists()) file.delete(); + if (!file.exists()) file_2.renameTo(file); + } + + @Override + public Tag getData(String file) + { + File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile( + CarpetServer.minecraft_server.getLevelName(), "scripts/"+name+".data"+(file==null?"":"."+file)+".nbt"); + if (!(dataFile.isFile())) + return null; + return read(dataFile); + } + + @Override + public void saveData(String file, Tag globalState) + { + File dataFile =CarpetServer.minecraft_server.getLevelStorage().resolveFile( + CarpetServer.minecraft_server.getLevelName(), "scripts/"+name+".data"+(file==null?"":"."+file)+".nbt"); + write(globalState, dataFile); + + } } diff --git a/src/main/java/carpet/script/bundled/ModuleInterface.java b/src/main/java/carpet/script/bundled/ModuleInterface.java index aaf4bf0b..009df028 100644 --- a/src/main/java/carpet/script/bundled/ModuleInterface.java +++ b/src/main/java/carpet/script/bundled/ModuleInterface.java @@ -1,7 +1,12 @@ package carpet.script.bundled; +import net.minecraft.nbt.Tag; + public interface ModuleInterface { String getName(); String getCode(); + default boolean isInternal() {return true; } + default Tag getData(String file) {return null; } + default void saveData(String file, Tag globalState) {} } diff --git a/src/main/java/carpet/script/value/ContainerValueInterface.java b/src/main/java/carpet/script/value/ContainerValueInterface.java index 3b62d327..6e05554a 100644 --- a/src/main/java/carpet/script/value/ContainerValueInterface.java +++ b/src/main/java/carpet/script/value/ContainerValueInterface.java @@ -2,12 +2,12 @@ package carpet.script.value; public interface ContainerValueInterface { - public Value put(Value where, Value value); - default Value put(Value where, Value value, Value conditions) + boolean put(Value where, Value value); + default boolean put(Value where, Value value, Value conditions) { return put(where, value); } - public Value get(Value where); - public boolean has(Value where); - public Value delete(Value where); + Value get(Value where); + boolean has(Value where); + boolean delete(Value where); } diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java index 3e1b43fd..c7e77bf6 100644 --- a/src/main/java/carpet/script/value/ListValue.java +++ b/src/main/java/carpet/script/value/ListValue.java @@ -306,7 +306,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public Value put(Value where, Value value, Value conditionValue) + public boolean put(Value where, Value value, Value conditionValue) { String condition = conditionValue.getString(); if (condition.equalsIgnoreCase("insert")) @@ -319,11 +319,12 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public Value put(Value ind, Value value) + public boolean put(Value ind, Value value) { return put(ind, value, true, false); } - private Value put(Value ind, Value value, boolean replace, boolean extend) + + private boolean put(Value ind, Value value, boolean replace, boolean extend) { if (ind == Value.NULL) { @@ -335,12 +336,14 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf { items.add(value); } - return items.get(items.size()-1); + return true; } else { int numitems = items.size(); - int index = (int) NumericValue.asNumber(ind).getLong(); + if (!(ind instanceof NumericValue)) + return false; + int index = (int)((NumericValue) ind).getLong(); if (index < 0) { long range = abs(index) / numitems; @@ -350,7 +353,8 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf if (replace) { while (index >= items.size()) items.add(Value.NULL); - return items.set(index, value); + items.set(index, value); + return true; } while (index > items.size()) items.add(Value.NULL); @@ -359,11 +363,10 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf Iterable iterable = ((AbstractListValue) value)::iterator; List appendix = StreamSupport.stream( iterable.spliterator(), false).collect(Collectors.toList()); items.addAll(index, appendix ); - return items.get(index+appendix.size()-1); + return true; } items.add(index, value); - return value; - + return true; } } @@ -386,14 +389,16 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } @Override - public Value delete(Value where) + public boolean delete(Value where) { - long index = NumericValue.asNumber(where).getLong(); + if (!(where instanceof NumericValue) || items.isEmpty()) return false; + long index = ((NumericValue) where).getLong(); int numitems = items.size(); long range = abs(index)/numitems; index += (range+2)*numitems; index = index % numitems; - return items.remove((int)index); + items.remove((int)index); + return true; } @Override diff --git a/src/main/java/carpet/script/value/MapValue.java b/src/main/java/carpet/script/value/MapValue.java index bf217311..f924256b 100644 --- a/src/main/java/carpet/script/value/MapValue.java +++ b/src/main/java/carpet/script/value/MapValue.java @@ -177,21 +177,17 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa } @Override - public Value delete(Value where) + public boolean delete(Value where) { Value ret = map.remove(where); - if (ret == null) - return Value.NULL; - return ret; + return ret != null; } @Override - public Value put(Value key, Value value) + public boolean put(Value key, Value value) { Value ret = map.put(key, value); - if (ret == null) - return Value.NULL; - return ret; + return ret != null; } @Override diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index ebfee982..c90ff247 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -191,7 +191,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return new StringValue(t.asString()); } - private Tag getTag() + public Tag getTag() { if (nbtTag == null) nbtTag = nbtSupplier.get(); @@ -210,7 +210,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa { if (o instanceof NBTSerializableValue) return getTag().equals(((NBTSerializableValue) o).getTag()); - return super.equals((Value)o); + return super.equals(o); } @Override @@ -240,13 +240,13 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } @Override - public Value put(Value where, Value value) + public boolean put(Value where, Value value) { return put(where, value, new StringValue("replace")); } @Override - public Value put(Value where, Value value, Value conditions) + public boolean put(Value where, Value value, Value conditions) { /// WIP @@ -272,14 +272,15 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } else { - return this; + return false; } } if (modifiedTag != null) { replaceTag(modifiedTag); + return true; } - return this; + return false; } @@ -412,13 +413,13 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } @Override - public Value delete(Value where) + public boolean delete(Value where) { NbtPathArgumentType.NbtPath path = cachePath(where.getString()); Tag tag = getTag().copy(); int removed = path.remove(tag); if (removed > 0) replaceTag(tag); - return new NumericValue(removed); + return removed > 0; } public static class InventoryLocator diff --git a/src/main/java/carpet/script/value/Value.java b/src/main/java/carpet/script/value/Value.java index c585748d..32ee351b 100644 --- a/src/main/java/carpet/script/value/Value.java +++ b/src/main/java/carpet/script/value/Value.java @@ -116,7 +116,7 @@ public abstract class Value implements Comparable, Cloneable return getString().compareTo(o.getString()); } - @Override // for hashmap key access + @Override // for hashmap key access, and == operator public boolean equals(final Object o) { if (o instanceof Value) @@ -124,12 +124,6 @@ public abstract class Value implements Comparable, Cloneable return false; } - // for general use - public boolean equals(final Value o) - { - return this.compareTo(o)==0; - } - public void assertAssignable() { if (boundVariable == null || boundVariable.startsWith("_"))