From 1fd290ba25badad9142130c2d63a17ef5c7a0a82 Mon Sep 17 00:00:00 2001 From: indoorjetpacks <33731861+indoorjetpacks@users.noreply.github.com> Date: Thu, 23 Jan 2020 22:46:40 -0600 Subject: [PATCH 1/5] Changing filter() function example previously used entities_list('all'), changed to entity_list('*') --- src/main/java/carpet/script/Expression.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index eeed2959..ca944573 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -1623,7 +1623,7 @@ public class Expression * With break and continue statements, the supplied value can be used as a boolean check instead.

*
      *     filter(range(100), !(_%5), _*_>1000)  => [0, 5, 10, 15, 20, 25, 30]
-     *     map(filter(entities_list('all'),_=='Witch'), query(_,'pos') )  => [[1082.5, 57, 1243.5]]
+     *     map(filter(entity_list('*'),_=='Witch'), query(_,'pos') )  => [[1082.5, 57, 1243.5]]
      * 
* *

first(list,expr(_,_i))

From 0d62fdc98019decc16ec18fbac41f1fb4fade3d6 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 25 Jan 2020 11:08:11 -0400 Subject: [PATCH 2/5] added in_slime_chunk, seed, add seed option to rand --- .../java/carpet/script/CarpetExpression.java | 26 ++++++++++++++++++- src/main/java/carpet/script/Expression.java | 14 +++++++--- src/main/java/carpet/script/ScriptHost.java | 10 +++++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java index 7ec510d4..24ecf6b7 100644 --- a/src/main/java/carpet/script/CarpetExpression.java +++ b/src/main/java/carpet/script/CarpetExpression.java @@ -102,6 +102,7 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkStatus; import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.ChunkRandom; import net.minecraft.world.loot.context.LootContext; import net.minecraft.world.loot.context.LootContextParameters; import org.apache.commons.lang3.tuple.Pair; @@ -607,6 +608,8 @@ public class CarpetExpression *

Numeric function, indicating hardness of a block.

*

blast_resistance(pos)

*

Numeric function, indicating blast_resistance of a block.

+ *

in_slime_chunk(pos)

+ *

Boolean indicating if the given block position is in a slime chunk.

*

top(type, pos)

*

Returns the Y value of the topmost block at given x, z coords (y value of a block is not important), according to the @@ -623,7 +626,7 @@ public class CarpetExpression * top('ocean_floor', x, y, z) => 41 * *

loaded(pos)

- *

Boolean function, true if the block is accessible forthe game mechanics. + *

Boolean function, true if the block is accessible for the game mechanics. * Normally scarpet doesn't check if operates on * loaded area - the game will automatically load missing blocks. We see this as advantage. * Vanilla fill/clone commands only check the specified corners for loadness.

@@ -1018,6 +1021,19 @@ public class CarpetExpression this.expr.addLazyFunction("blast_resistance", -1, (c, t, lv) -> genericStateTest(c, "blast_resistance", lv, (s, p, w) -> new NumericValue(s.getBlock().getBlastResistance()))); + this.expr.addLazyFunction("in_slime_chunk", -1, (c, t, lv) -> + { + BlockPos pos = BlockValue.fromParams((CarpetContext)c, lv, 0).block.getPos(); + ChunkPos chunkPos = new ChunkPos(pos); + Value ret = new NumericValue(ChunkRandom.create( + chunkPos.x, chunkPos.z, + ((CarpetContext)c).s.getWorld().getSeed(), + 987234911L + ).nextInt(10) == 0); + return (_c, _t) -> ret; + }); + + this.expr.addLazyFunction("top", -1, (c, t, lv) -> { String type = lv.get(0).evalValue(c).getString().toLowerCase(Locale.ROOT); @@ -2957,6 +2973,8 @@ public class CarpetExpression * loop(1000,game_tick()) // runs the game as fast as it can for 1000 ticks * loop(1000,game_tick(100)) // runs the game twice as slow for 1000 ticks * + *

seed()

+ *

Returns current world seed.

*

current_dimension()

*

Returns current dimension that the script runs in.

*

in_dimension(smth, expr)

@@ -3399,6 +3417,12 @@ public class CarpetExpression return (cc, tt) -> Value.TRUE; }); + this.expr.addLazyFunction("seed", -1, (c, t, lv) -> { + ServerCommandSource s = ((CarpetContext)c).s; + Value ret = new NumericValue(s.getWorld().getSeed()); + return (cc, tt) -> ret; + }); + this.expr.addLazyFunction("current_dimension", 0, (c, t, lv) -> { ServerCommandSource s = ((CarpetContext)c).s; Value retval = new StringValue(NBTSerializableValue.nameFromRegistryId(Registry.DIMENSION.getId(s.getWorld().dimension.getType()))); diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index d5ad5457..4e7a63d4 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -2720,12 +2720,15 @@ public class Expression * length('foo') => 3 * * - *

rand(expr)

+ *

rand(expr), rand(expr, seed)

*

returns a random number from 0.0 * (inclusive) to expr (exclusive). * In boolean context (in conditions, boolean functions, or bool), returns * false if the randomly selected value is less than 1. This means that rand(2) returns true half - * of the time and rand(5) returns true for 80% (4/5) of the time

+ * of the time and rand(5) returns true for 80% (4/5) of the time. If seed is not provided, uses a random seed. + * If seed is provided, each consecutive call to rand() will act like 'next' call to the same random object. + * Scarpet keeps track of up to 1024 custom random number generators, so if you exceed this number (per app), then your + * random sequence will revert to the beginning.

*
      * map(range(10), floor(rand(10))) => [5, 8, 0, 6, 9, 3, 9, 9, 1, 8]
      * map(range(10), bool(rand(2))) => [1, 1, 1, 0, 0, 1, 1, 0, 0, 0]
@@ -2982,7 +2985,12 @@ public class Expression
         addUnaryFunction("type", v -> new StringValue(v.getTypeString()));
 
         addUnaryFunction("length", v -> new NumericValue(v.length()));
-        addLazyFunction("rand", 1, (c, t, lv) -> {
+        addLazyFunction("rand", -1, (c, t, lv) -> {
+            int argsize = lv.size();
+            Random randomizer = Expression.randomizer;
+            if (argsize != 1 && argsize != 2)
+                throw new InternalExpressionException("'rand' takes one (range) or two arguments (range and seed)");
+            if (argsize == 2) randomizer = c.host.getRandom(NumericValue.asNumber(lv.get(1).evalValue(c)).getLong());
             Value argument = lv.get(0).evalValue(c);
             if (argument instanceof ListValue)
             {
diff --git a/src/main/java/carpet/script/ScriptHost.java b/src/main/java/carpet/script/ScriptHost.java
index ad2ba58f..63ef1dc2 100644
--- a/src/main/java/carpet/script/ScriptHost.java
+++ b/src/main/java/carpet/script/ScriptHost.java
@@ -4,11 +4,13 @@ import carpet.script.bundled.Module;
 import carpet.script.exception.InternalExpressionException;
 import carpet.script.value.FunctionValue;
 import carpet.script.value.Value;
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
 import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
 
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Random;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
@@ -16,6 +18,14 @@ import java.util.stream.Stream;
 public abstract class ScriptHost
 {
     public static Map systemGlobals = new ConcurrentHashMap<>();
+    private static Map randomizers = new Long2ObjectOpenHashMap<>();
+
+    public Random getRandom(long aLong)
+    {
+        if (randomizers.size() > 1024)
+            randomizers.clear();
+        return randomizers.computeIfAbsent(aLong, Random::new);
+    }
 
 
     public static class ModuleData

From b612be2b04e1ac4e65e9c64171f926078189e58e Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Sat, 25 Jan 2020 20:03:44 -0400
Subject: [PATCH 3/5] renaming a few structures for consistence

---
 .../java/carpet/helpers/FeatureGenerator.java | 32 +++++++++----------
 .../java/carpet/script/CarpetExpression.java  |  6 ++--
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/src/main/java/carpet/helpers/FeatureGenerator.java b/src/main/java/carpet/helpers/FeatureGenerator.java
index ee8e97a3..1a8ee947 100644
--- a/src/main/java/carpet/helpers/FeatureGenerator.java
+++ b/src/main/java/carpet/helpers/FeatureGenerator.java
@@ -120,11 +120,11 @@ public class FeatureGenerator
     {
         structureToFeature.put("Monument", Collections.singletonList("monument"));
         structureToFeature.put("EndCity", Collections.singletonList("end_city"));
-        structureToFeature.put("Ocean_Ruin", Arrays.asList("oceanruin", "oceanruin_warm", "oceanruin_small", "oceanruin_warm_small", "oceanruin_tall", "oceanruin_warm_tall"));
+        structureToFeature.put("Ocean_Ruin", Arrays.asList("ocean_ruin", "ocean_ruin_warm", "ocean_ruin_small", "ocean_ruin_warm_small", "ocean_ruin_tall", "ocean_ruin_warm_tall"));
         structureToFeature.put("Village", Arrays.asList("village", "village_desert", "village_savanna", "village_taiga", "village_snowy"));
         structureToFeature.put("Mansion", Collections.singletonList("mansion"));
         structureToFeature.put("Buried_Treasure", Collections.singletonList("treasure"));
-        structureToFeature.put("Swamp_Hut", Collections.singletonList("witchhut"));
+        structureToFeature.put("Swamp_Hut", Collections.singletonList("witch_hut"));
         structureToFeature.put("Stronghold", Collections.singletonList("stronghold"));
         structureToFeature.put("Desert_Pyramid", Collections.singletonList("desert_temple"));
         structureToFeature.put("Jungle_Pyramid", Collections.singletonList("jungle_temple"));
@@ -147,20 +147,20 @@ public class FeatureGenerator
         put("igloo", ((StructureFeatureInterface)Feature.IGLOO)::gridAnywhere);
         put("shipwreck", gridCustomStructure(Feature.SHIPWRECK, new ShipwreckFeatureConfig(true), Biomes.PLAINS));
         put("shipwreck2", gridCustomStructure(Feature.SHIPWRECK, new ShipwreckFeatureConfig(false), Biomes.PLAINS));
-        put("witchhut", ((StructureFeatureInterface)Feature.SWAMP_HUT)::gridAnywhere);
+        put("witch_hut", ((StructureFeatureInterface)Feature.SWAMP_HUT)::gridAnywhere);
         put("stronghold", ((StructureFeatureInterface)Feature.STRONGHOLD)::gridAnywhere);
 
-        put("oceanruin_small", gridCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin_small", gridCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.COLD, 0.0F, 0.5F), Biomes.PLAINS));
-        put("oceanruin_warm_small", gridCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin_warm_small", gridCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.WARM, 0.0F, 0.5F), Biomes.PLAINS));
-        put("oceanruin_tall", gridCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin_tall", gridCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.COLD, 1.0F, 0.0F), Biomes.PLAINS));
-        put("oceanruin_warm_tall", gridCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin_warm_tall", gridCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.WARM, 1.0F, 0.0F), Biomes.PLAINS));
-        put("oceanruin", gridCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin", gridCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.COLD, 1.0F, 1.0F), Biomes.PLAINS));
-        put("oceanruin_warm", gridCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin_warm", gridCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.WARM, 1.0F, 1.0F), Biomes.PLAINS));
         put("treasure", ((StructureFeatureInterface)Feature.BURIED_TREASURE)::gridAnywhere);
 
@@ -248,20 +248,20 @@ public class FeatureGenerator
         put("igloo", ((StructureFeatureInterface)Feature.IGLOO)::plopAnywhere);
         put("shipwreck", spawnCustomStructure(Feature.SHIPWRECK, new ShipwreckFeatureConfig(true), Biomes.PLAINS));
         put("shipwreck2", spawnCustomStructure(Feature.SHIPWRECK, new ShipwreckFeatureConfig(false), Biomes.PLAINS));
-        put("witchhut", ((StructureFeatureInterface)Feature.SWAMP_HUT)::plopAnywhere);
+        put("witch_hut", ((StructureFeatureInterface)Feature.SWAMP_HUT)::plopAnywhere);
         put("stronghold", ((StructureFeatureInterface)Feature.STRONGHOLD)::plopAnywhere);
 
-        put("oceanruin_small", spawnCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin_small", spawnCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.COLD, 0.0F, 0.5F), Biomes.PLAINS));
-        put("oceanruin_warm_small", spawnCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin_warm_small", spawnCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.WARM, 0.0F, 0.5F), Biomes.PLAINS));
-        put("oceanruin_tall", spawnCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin_tall", spawnCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.COLD, 1.0F, 0.0F), Biomes.PLAINS));
-        put("oceanruin_warm_tall", spawnCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin_warm_tall", spawnCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.WARM, 1.0F, 0.0F), Biomes.PLAINS));
-        put("oceanruin", spawnCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin", spawnCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.COLD, 1.0F, 1.0F), Biomes.PLAINS));
-        put("oceanruin_warm", spawnCustomStructure(Feature.OCEAN_RUIN,
+        put("ocean_ruin_warm", spawnCustomStructure(Feature.OCEAN_RUIN,
                 new OceanRuinFeatureConfig(OceanRuinFeature.BiomeType.WARM, 1.0F, 1.0F), Biomes.PLAINS));
         put("treasure", ((StructureFeatureInterface)Feature.BURIED_TREASURE)::plopAnywhere);
 
diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java
index 24ecf6b7..1c0dac89 100644
--- a/src/main/java/carpet/script/CarpetExpression.java
+++ b/src/main/java/carpet/script/CarpetExpression.java
@@ -3034,9 +3034,9 @@ public class CarpetExpression
      *     
  • igloo: Igloo
  • *
  • shipwreck: Shipwreck, version1?
  • *
  • shipwreck2: Shipwreck, version2?
  • - *
  • witchhut
  • - *
  • oceanruin, oceanruin_small, oceanruin_tall: Stone variants of ocean ruins.
  • - *
  • oceanruin_warm, oceanruin_warm_small, oceanruin_warm_tall: Sandstone variants of ocean ruins.
  • + *
  • witch_hut
  • + *
  • ocean_ruin, ocean_ruin_small, ocean_ruin_tall: Stone variants of ocean ruins.
  • + *
  • ocean_ruin_warm, ocean_ruin_warm_small, ocean_ruin_warm_tall: Sandstone variants of ocean ruins.
  • *
  • treasure: A treasure chest. Yes, its a whole structure.
  • *
  • pillager_outpost: A pillager outpost.
  • *
  • mineshaft: A mineshaft.
  • From 5ba04a331795bde94dfe891868b87ef41790451b Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 25 Jan 2020 20:04:13 -0400 Subject: [PATCH 4/5] adding to map will always add null value. --- src/main/java/carpet/script/value/MapValue.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/carpet/script/value/MapValue.java b/src/main/java/carpet/script/value/MapValue.java index c79ca8a5..7bd65d1a 100644 --- a/src/main/java/carpet/script/value/MapValue.java +++ b/src/main/java/carpet/script/value/MapValue.java @@ -124,7 +124,7 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa @Override public void append(Value v) { - put(v); + map.put(v, Value.NULL); } @Override From e8c077a65d5e24a416263423cbddaca44c0d7615 Mon Sep 17 00:00:00 2001 From: gnembon Date: Sat, 25 Jan 2020 20:05:52 -0400 Subject: [PATCH 5/5] added structure renderer. --- .../carpet/script/CarpetScriptServer.java | 1 + src/main/java/carpet/script/Expression.java | 2 +- .../assets/carpet/scripts/structures.sc | 78 +++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/assets/carpet/scripts/structures.sc diff --git a/src/main/java/carpet/script/CarpetScriptServer.java b/src/main/java/carpet/script/CarpetScriptServer.java index f065a4e8..a486b3fe 100644 --- a/src/main/java/carpet/script/CarpetScriptServer.java +++ b/src/main/java/carpet/script/CarpetScriptServer.java @@ -43,6 +43,7 @@ public class CarpetScriptServer private static final List bundledModuleData = new ArrayList(){{ add(new BundledModule("camera", false)); + add(new BundledModule("structures", false)); add(new BundledModule("event_test", false)); add(new BundledModule("stats_test", false)); add(new BundledModule("math", true)); diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 4e7a63d4..8f2b8c2c 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -1312,7 +1312,7 @@ public class Expression LazyValue boundedLHS; if (v1 instanceof ListValue || v1 instanceof MapValue) { - ((ListValue) v1).append(v2); + ((AbstractListValue) v1).append(v2); boundedLHS = (cc, tt)-> v1; } else diff --git a/src/main/resources/assets/carpet/scripts/structures.sc b/src/main/resources/assets/carpet/scripts/structures.sc new file mode 100644 index 00000000..a6b46b07 --- /dev/null +++ b/src/main/resources/assets/carpet/scripts/structures.sc @@ -0,0 +1,78 @@ +import('math', '_euclidean_sq', '_euclidean'); + +global_current_structures = m(); +global_overlay_active = false; +global_range = 3; +global_max_pieces = 4; + +__command() -> ''; + +monument() -> __toggle('monument'); +fortress() -> __toggle('fortress'); +mansion() -> __toggle('mansion'); +jungle_temple() -> __toggle('jungle_temple'); +desert_temple() -> __toggle('desert_temple'); +end_city() -> __toggle('end_city'); +igloo() -> __toggle('igloo'); +shipwreck() -> __toggle('shipwreck'); +witch_hut() -> __toggle('witch_hut'); +stronghold() -> __toggle('stronghold'); +ocean_ruin() -> __toggle('ocean_ruin'); +treasure() -> __toggle('treasure'); +pillager_outpost() -> __toggle('pillager_outpost'); +mineshaft() -> __toggle('mineshaft'); +village() -> __toggle('village'); + +__toggle(structure) -> +( + p = player() + if( has(global_current_structures:structure), + delete(global_current_structures:structure); + 'disabled '+structure+' overlays'; + , + global_current_structures:structure = null; + if (!global_overlay_active, __structure_renderer(p~'name')); + 'enabled '+structure+' overlays'; + ) +); + +__structure_renderer(player_name) -> +( + if (length(global_current_structures)==0, global_overlay_active = false; return()); + p = player(player_name); + if (!p, global_overlay_active = false; return()); + global_overlay_active = true; + in_dimension(p, + ppos = pos(p); + starts = m(); + for(range(-global_range,global_range), cx =_; + for (range(-global_range,global_range), cz = _; + ref_pos = ppos + l(16*cx,0,16*cz); + for(filter(structure_references(ref_pos), has(global_current_structures:_)), + name = _; + for(structure_references(ref_pos, name), + starts += l(_, name); + ) + ) + ) + ); + for (starts, l(position, name) = _; + structure_data = structures(position):name; + if (!structure_data, continue()); // messed up references - shouldn't happen + structure_pieces = structures(position, name); + if (!structure_pieces, continue()); // messed up references - shouldn't happen + l(from, to) = structure_data; + total_size = _euclidean(from, to); + density = max(10, total_size/10); + particle_rect('dust 0 1 1 2', from, to+1, density); + structure_pieces = slice(sort_key(structure_pieces, _euclidean_sq((_:2+_:3)/2,ppos)), 0, global_max_pieces); + for (structure_pieces, l(piece, direction, from, to) = _; + factor = 1-_i/global_max_pieces/2; + total_size = _euclidean(from, to); + density = max(_i+1, total_size/10); + particle_rect(str('dust %.2f %.2f 1 1',factor, factor), from, to+1, density); + ) + ) + ); + schedule(3, '__structure_renderer', player_name); +); \ No newline at end of file