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("_"))