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))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.
seed()Returns current world seed.
*current_dimension()Returns current dimension that the script runs in.
*in_dimension(smth, expr)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
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