From b041e05b47e5ed1a35d19025fc2bbc87b74bd949 Mon Sep 17 00:00:00 2001 From: gnembon Date: Tue, 17 Mar 2020 10:14:36 -0300 Subject: [PATCH 1/9] removed inspector --- docs/scarpet/language/Operators.md | 2 +- .../java/carpet/commands/ScriptCommand.java | 45 ++++++++++----- .../ArmorStandEntity_scarpetMarkerMixin.java | 6 +- .../java/carpet/script/CarpetExpression.java | 9 +-- .../java/carpet/script/CarpetScriptHost.java | 2 +- src/main/java/carpet/script/Expression.java | 14 +++-- .../carpet/script/ExpressionInspector.java | 55 ------------------- .../script/exception/ExpressionException.java | 7 +-- 8 files changed, 54 insertions(+), 86 deletions(-) delete mode 100644 src/main/java/carpet/script/ExpressionInspector.java diff --git a/docs/scarpet/language/Operators.md b/docs/scarpet/language/Operators.md index 9fc49180..6d78efd6 100644 --- a/docs/scarpet/language/Operators.md +++ b/docs/scarpet/language/Operators.md @@ -7,7 +7,7 @@ as `(2+4)-3`, which in case of numbers doesn't matter, but since `scarpet` allow the associativity would matter, and may lead to unintended effects: Important operator is function definition `->` operator. It will be covered -in {@link carpet.script.Expression#UserDefinedFunctionsAndControlFlow} +in [User Defined Functions and Program Control Flow](docs/scarpet/language/FunctionsAndControlFlow.md)
 '123'+4-2 => ('123'+4)-2 => '1234'-2 => '134'
diff --git a/src/main/java/carpet/commands/ScriptCommand.java b/src/main/java/carpet/commands/ScriptCommand.java
index 8e5a3108..2524978c 100644
--- a/src/main/java/carpet/commands/ScriptCommand.java
+++ b/src/main/java/carpet/commands/ScriptCommand.java
@@ -1,14 +1,8 @@
 package carpet.commands;
 
 import carpet.CarpetServer;
-import carpet.script.CarpetScriptHost;
+import carpet.script.*;
 import carpet.CarpetSettings;
-import carpet.script.CarpetEventServer;
-import carpet.script.CarpetExpression;
-import carpet.script.Expression;
-import carpet.script.ExpressionInspector;
-import carpet.script.LazyValue;
-import carpet.script.Tokenizer;
 import carpet.script.exception.CarpetExpressionException;
 import carpet.script.value.FunctionValue;
 import carpet.settings.SettingsManager;
@@ -31,11 +25,9 @@ import net.minecraft.util.Clearable;
 import net.minecraft.util.math.BlockPos;
 import net.minecraft.server.world.ServerWorld;
 import net.minecraft.util.math.BlockBox;
+import org.apache.commons.lang3.StringUtils;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Locale;
+import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
@@ -47,6 +39,33 @@ import static net.minecraft.server.command.CommandSource.suggestMatching;
 
 public class ScriptCommand
 {
+    private static TreeSet scarpetFunctions;
+    private static TreeSet APIFunctions;
+    static
+    {
+        Set allFunctions = (new CarpetExpression(null, "null", null, null)).getExpr().getFunctionNames();
+        scarpetFunctions = new TreeSet<>(Expression.none.getFunctionNames());
+        APIFunctions = allFunctions.stream().filter(s -> !scarpetFunctions.contains(s)).collect(Collectors.toCollection(TreeSet::new));
+    }
+
+    public static List suggestFunctions(ScriptHost host, String previous, String prefix)
+    {
+        previous = previous.replace("\\'", "");
+        int quoteCount = StringUtils.countMatches(previous,'\'');
+        if (quoteCount % 2 == 1)
+            return Collections.emptyList();
+        int maxLen = prefix.length()<3 ? (prefix.length()*2+1) : 1234;
+        List scarpetMatches = scarpetFunctions.stream().
+                filter(s -> s.startsWith(prefix) && s.length() <= maxLen).map(s -> s+"(").collect(Collectors.toList());
+        scarpetMatches.addAll(APIFunctions.stream().
+                filter(s -> s.startsWith(prefix) && s.length() <= maxLen).map(s -> s+"(").collect(Collectors.toList()));
+        // not that useful in commandline, more so in external scripts, so skipping here
+        //scarpetMatches.addAll(CarpetServer.scriptServer.events.eventHandlers.keySet().stream().
+        //        filter(s -> s.startsWith(prefix) && s.length() <= maxLen).map(s -> "__"+s+"(").collect(Collectors.toList()));
+        scarpetMatches.addAll(host.globaFunctionNames(host.main, s -> s.startsWith(prefix)).map(s -> s+"(").collect(Collectors.toList()));
+        scarpetMatches.addAll(host.globaVariableNames(host.main, s -> s.startsWith(prefix)).collect(Collectors.toList()));
+        return scarpetMatches;
+    }
 
     private static CompletableFuture suggestCode(
             CommandContext context,
@@ -66,7 +85,7 @@ public class ScriptCommand
             return suggestionsBuilder.buildFuture();
         String prefix = lastToken.reverse().toString();
         String previousString =  previous.substring(0,previous.length()-prefix.length()) ;
-        ExpressionInspector.suggestFunctions(currentHost, previousString, prefix).forEach(text -> suggestionsBuilder.suggest(previousString+text));
+        suggestFunctions(currentHost, previousString, prefix).forEach(text -> suggestionsBuilder.suggest(previousString+text));
         return suggestionsBuilder.buildFuture();
     }
 
@@ -333,7 +352,7 @@ public class ScriptCommand
             }
             Expression expr = fun.getExpression();
             Tokenizer.Token tok = fun.getToken();
-            List snippet = ExpressionInspector.Expression_getExpressionSnippet(tok, expr);
+            List snippet = expr.getExpressionSnippet(tok);
             Messenger.m(source, "wb "+fun.fullName(),"t  defined at: line "+(tok.lineno+1)+" pos "+(tok.linepos+1));
             for (String snippetLine: snippet)
             {
diff --git a/src/main/java/carpet/mixins/ArmorStandEntity_scarpetMarkerMixin.java b/src/main/java/carpet/mixins/ArmorStandEntity_scarpetMarkerMixin.java
index c962e7c8..34e5ea2d 100644
--- a/src/main/java/carpet/mixins/ArmorStandEntity_scarpetMarkerMixin.java
+++ b/src/main/java/carpet/mixins/ArmorStandEntity_scarpetMarkerMixin.java
@@ -1,7 +1,7 @@
 package carpet.mixins;
 
 import carpet.CarpetServer;
-import carpet.script.ExpressionInspector;
+import carpet.script.CarpetExpression;
 import carpet.CarpetSettings;
 import net.minecraft.entity.EntityType;
 import net.minecraft.entity.LivingEntity;
@@ -32,9 +32,9 @@ public abstract class ArmorStandEntity_scarpetMarkerMixin extends LivingEntity
     {
         if ((CarpetSettings.scriptsAutoload || !CarpetSettings.commandScript.equals("false")) && !world.isClient)
         {
-            if (getScoreboardTags().contains(ExpressionInspector.MARKER_STRING))
+            if (getScoreboardTags().contains(CarpetExpression.MARKER_STRING))
             {
-                String prefix = ExpressionInspector.MARKER_STRING+"_";
+                String prefix = CarpetExpression.MARKER_STRING+"_";
                 Optional owner = getScoreboardTags().stream().filter(s -> s.startsWith(prefix)).findFirst();
                 if (owner.isPresent())
                 {
diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java
index 411fc046..da72d743 100644
--- a/src/main/java/carpet/script/CarpetExpression.java
+++ b/src/main/java/carpet/script/CarpetExpression.java
@@ -139,10 +139,11 @@ public class CarpetExpression
     private final ServerCommandSource source;
     private final BlockPos origin;
     private final Expression expr;
-    Expression getExpr() {return expr;}
+    public Expression getExpr() {return expr;}
     private static long tickStart = 0L;
     // dummy entity for dummy requirements in the loot tables (see snowball)
     private static FallingBlockEntity DUMMY_ENTITY = new FallingBlockEntity(EntityType.FALLING_BLOCK, null);
+    public static final String MARKER_STRING = "__scarpet_marker";
 
     private static boolean stopAll = false;
 
@@ -2377,8 +2378,8 @@ public class CarpetExpression
                     (float)pointLocator.yaw,
                     (float) pointLocator.pitch
             );
-            armorstand.addScoreboardTag(ExpressionInspector.MARKER_STRING+"_"+((cc.host.getName()==null)?"":cc.host.getName()));
-            armorstand.addScoreboardTag(ExpressionInspector.MARKER_STRING);
+            armorstand.addScoreboardTag(MARKER_STRING+"_"+((cc.host.getName()==null)?"":cc.host.getName()));
+            armorstand.addScoreboardTag(MARKER_STRING);
             if (targetBlock != null)
                 armorstand.equipStack(EquipmentSlot.HEAD, new ItemStack(targetBlock.getBlock().asItem()));
             if (!name.isEmpty())
@@ -2399,7 +2400,7 @@ public class CarpetExpression
         this.expr.addLazyFunction("remove_all_markers", 0, (c, t, lv) -> {
             CarpetContext cc = (CarpetContext)c;
             int total = 0;
-            String markerName = ExpressionInspector.MARKER_STRING+"_"+((cc.host.getName()==null)?"":cc.host.getName());
+            String markerName = MARKER_STRING+"_"+((cc.host.getName()==null)?"":cc.host.getName());
             for (Entity e : cc.s.getWorld().getEntities(EntityType.ARMOR_STAND, (as) -> as.getScoreboardTags().contains(markerName)))
             {
                 total ++;
diff --git a/src/main/java/carpet/script/CarpetScriptHost.java b/src/main/java/carpet/script/CarpetScriptHost.java
index 7d27ba4e..0b1a5eb7 100644
--- a/src/main/java/carpet/script/CarpetScriptHost.java
+++ b/src/main/java/carpet/script/CarpetScriptHost.java
@@ -346,7 +346,7 @@ public class CarpetScriptHost extends ScriptHost
             }
         });
 
-        String markerName = ExpressionInspector.MARKER_STRING+"_"+((getName()==null)?"":getName());
+        String markerName = CarpetExpression.MARKER_STRING+"_"+((getName()==null)?"":getName());
         for (ServerWorld world : CarpetServer.minecraft_server.getWorlds())
         {
             for (Entity e : world.getEntities(EntityType.ARMOR_STAND, (as) -> as.getScoreboardTags().contains(markerName)))
diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java
index b5175f4a..fbe5a08c 100644
--- a/src/main/java/carpet/script/Expression.java
+++ b/src/main/java/carpet/script/Expression.java
@@ -99,6 +99,12 @@ public class Expression
 
     public Module module = null;
 
+    public String getModuleName()
+    {
+        return module == null?null:module.getName();
+    }
+
+
     void asATextSource()
     {
         allowNewlineSubstitutions = false;
@@ -119,11 +125,11 @@ public class Expression
     boolean isAnOperator(String opname) { return operators.containsKey(opname) || operators.containsKey(opname+"u");}
 
     private final Map functions = new  Object2ObjectOpenHashMap<>();
-    Set getFunctionNames() {return functions.keySet();}
+    public Set getFunctionNames() {return functions.keySet();}
 
-    static List getExpressionSnippet(Tokenizer.Token token, Expression expr)
+    public List getExpressionSnippet(Tokenizer.Token token)
     {
-        String code = expr.getCodeString();
+        String code = this.getCodeString();
         List output = new ArrayList<>();
         for (String line: getExpressionSnippetLeftContext(token, code, 1))
         {
@@ -1949,7 +1955,7 @@ public class Expression
         return var;
     }
 
-    static final Expression none = new Expression("null");
+    public static final Expression none = new Expression("null");
     /**
      * @param expression .
      */
diff --git a/src/main/java/carpet/script/ExpressionInspector.java b/src/main/java/carpet/script/ExpressionInspector.java
deleted file mode 100644
index e6d2a1f6..00000000
--- a/src/main/java/carpet/script/ExpressionInspector.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package carpet.script;
-
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.stream.Collectors;
-
-/**
- * sole purpose of this package is to provide public access to package-private methods of Expression and CarpetExpression
- * classes so they don't leave garbage in javadocs
- */
-public class ExpressionInspector
-{
-    public static final String MARKER_STRING = "__scarpet_marker";
-    public static List Expression_getExpressionSnippet(Tokenizer.Token token, Expression expr)
-    {
-        return Expression.getExpressionSnippet(token, expr);
-    }
-
-    public static String Expression_getModuleName(Expression e)
-    {
-        return e.module == null?null:e.module.getName();
-    }
-
-    private static TreeSet scarpetFunctions;
-    private static TreeSet APIFunctions;
-    static
-    {
-        Set allFunctions = (new CarpetExpression(null, "null", null, null)).getExpr().getFunctionNames();
-        scarpetFunctions = new TreeSet<>(Expression.none.getFunctionNames());
-        APIFunctions = allFunctions.stream().filter(s -> !scarpetFunctions.contains(s)).collect(Collectors.toCollection(TreeSet::new));
-    }
-
-    public static List suggestFunctions(ScriptHost host, String previous, String prefix)
-    {
-        previous = previous.replace("\\'", "");
-        int quoteCount = StringUtils.countMatches(previous,'\'');
-        if (quoteCount % 2 == 1)
-            return Collections.emptyList();
-        int maxLen = prefix.length()<3 ? (prefix.length()*2+1) : 1234;
-        List scarpetMatches = scarpetFunctions.stream().
-                filter(s -> s.startsWith(prefix) && s.length() <= maxLen).map(s -> s+"(").collect(Collectors.toList());
-        scarpetMatches.addAll(APIFunctions.stream().
-                filter(s -> s.startsWith(prefix) && s.length() <= maxLen).map(s -> s+"(").collect(Collectors.toList()));
-        // not that useful in commandline, more so in external scripts, so skipping here
-        //scarpetMatches.addAll(CarpetServer.scriptServer.events.eventHandlers.keySet().stream().
-        //        filter(s -> s.startsWith(prefix) && s.length() <= maxLen).map(s -> "__"+s+"(").collect(Collectors.toList()));
-        scarpetMatches.addAll(host.globaFunctionNames(host.main, s -> s.startsWith(prefix)).map(s -> s+"(").collect(Collectors.toList()));
-        scarpetMatches.addAll(host.globaVariableNames(host.main, s -> s.startsWith(prefix)).collect(Collectors.toList()));
-        return scarpetMatches;
-    }
-}
diff --git a/src/main/java/carpet/script/exception/ExpressionException.java b/src/main/java/carpet/script/exception/ExpressionException.java
index ec6486b6..34d34c96 100644
--- a/src/main/java/carpet/script/exception/ExpressionException.java
+++ b/src/main/java/carpet/script/exception/ExpressionException.java
@@ -9,9 +9,6 @@ import carpet.script.value.FunctionValue;
 import java.util.ArrayList;
 import java.util.List;
 
-import static carpet.script.ExpressionInspector.Expression_getExpressionSnippet;
-import static carpet.script.ExpressionInspector.Expression_getModuleName;
-
 /* The expression evaluators exception class. */
 public class ExpressionException extends RuntimeException implements ResolvedException
 {
@@ -40,10 +37,10 @@ public class ExpressionException extends RuntimeException implements ResolvedExc
     {
 
         List errMsg = new ArrayList<>();
-        errmessage += Expression_getModuleName(expr) == null?"":(" in "+Expression_getModuleName(expr));
+        errmessage += expr.getModuleName() == null?"":(" in "+expr.getModuleName());
         if (token != null)
         {
-            List snippet = Expression_getExpressionSnippet(token, expr);
+            List snippet = expr.getExpressionSnippet(token);
             errMsg.addAll(snippet);
 
             if (snippet.size() != 1)

From 29b164b513bbb32770912a2ffda35fda47448f68 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Tue, 17 Mar 2020 10:44:48 -0300
Subject: [PATCH 2/9] added notepad editor file, outdated

---
 .../scarpet/resources/editors/npp/scarpet.xml | 111 ++++++++++++++++++
 1 file changed, 111 insertions(+)
 create mode 100644 docs/scarpet/resources/editors/npp/scarpet.xml

diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml
new file mode 100644
index 00000000..63125df1
--- /dev/null
+++ b/docs/scarpet/resources/editors/npp/scarpet.xml
@@ -0,0 +1,111 @@
+
+    
+        
+            
+            
+        
+        
+            00// 01 02 03 04
+            0x
+            
+            
+            
+            
+            
+            
+            ; + - * / % ^ && || > >= < <= == != = += -> <> ! ~ , :
+            
+            (
+            
+            )
+            
+            
+            
+            
+            
+            
+            
+                not fact rand
+                sin cos tan asin acos atan atan2 sinh cosh tanh sec csc sech csch cot acot coth asinh acosh atanh
+                rad deg
+                log log10 log1p
+                sqrt
+                max min abs round floor ceil
+                mandelbrot relu
+
+                print return exit throw try
+
+                l join split slice sort sort_key range m keys values pairs copy
+
+                get put has delete
+
+                var undef vars if loop map filter first all for while reduce continue break
+
+                call outer type bool number str length rand sleep time profile_expr lower upper title replace replace_first
+            
+            
+                block pos pos_offset solid air liquid flammable
+                transparent opacity blocks_daylight emitted_light light block_light sky_light see_sky
+                hardness blast_resistance top loaded suffocates power ticks_randomly update block_tick random_tick
+                set
+                blocks_movement block_sound material map_colour property block_properties block_data
+                place_item set_biome biome loaded_status generation_status chunk_tickets
+
+                player spawn entity_id entity_list entity_area entity_selector query modify entity_event
+
+                stack_limit item_category inventory_size inventory_has_items inventory_get inventory_set inventory_find inventory_remove drop_item
+
+                scan volume neighbours rect diamond
+
+                logger sound particle particle_line particle_rect
+
+                run save tick_time game_tick current_dimension in_dimension
+
+                plop harvest destroy schedule nbt create_marker remove_all_markers load_app_data store_app_data escape_nbt
+            
+            euler pi null true false
+            x y z p
+            _ _i _a _x _y _z
+            global_
+            
+                __command
+                __config
+                __on_player_jumps __on_player_deploys_elytra __on_player_wakes_up __on_player_rides __on_player_uses_item
+                __on_player_clicks_block __on_player_right_clicks_block __on_player_breaks_block
+                __on_player_interacts_with_entity __on_player_attacks_entity
+                __on_player_starts_sneaking __on_player_stops_sneaking __on_player_starts_sprinting __on_player_stops_sprinting
+                __on_player_releases_item __on_player_finishes_using_item
+                __on_player_drops_item __on_player_drops_stack
+                __on_tick __on_tick_ender __on_tick_nether
+            
+            $
+            00' 01\ 02' 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+        
+        
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+            
+        
+    
+

From a3cc9eec8cb363bdf603111a10ebeda743fa3829 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Tue, 17 Mar 2020 11:01:40 -0300
Subject: [PATCH 3/9] updated notepad specs

---
 .../scarpet/resources/editors/npp/scarpet.xml | 20 ++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml
index 63125df1..e77cbbf0 100644
--- a/docs/scarpet/resources/editors/npp/scarpet.xml
+++ b/docs/scarpet/resources/editors/npp/scarpet.xml
@@ -32,24 +32,30 @@
                 sqrt
                 max min abs round floor ceil
                 mandelbrot relu
+                perlin simplex
 
                 print return exit throw try
 
+                task task_count task_value task_join task_completed synchronize
+
+                system_variable_get system_variable_set
+
                 l join split slice sort sort_key range m keys values pairs copy
 
                 get put has delete
 
                 var undef vars if loop map filter first all for while reduce continue break
 
-                call outer type bool number str length rand sleep time profile_expr lower upper title replace replace_first
+                import call outer type hash_code bool number str length rand sleep time profile_expr lower upper title replace replace_first
             
             
                 block pos pos_offset solid air liquid flammable
-                transparent opacity blocks_daylight emitted_light light block_light sky_light see_sky
-                hardness blast_resistance top loaded suffocates power ticks_randomly update block_tick random_tick
-                set
-                blocks_movement block_sound material map_colour property block_properties block_data
+                transparent opacity blocks_daylight emitted_light light block_light sky_light see_sky brightness
+                hardness blast_resistance top loaded suffocates power ticks_randomly update block_tick random_tick in_slime_chunk
+                set without_updates
+                blocks_movement block_sound material map_colour property block_properties block_data poi set_poi
                 place_item set_biome biome loaded_status generation_status chunk_tickets
+                structures structure_references set_structure reset_chunk
 
                 player spawn entity_id entity_list entity_area entity_selector query modify entity_event
 
@@ -59,9 +65,9 @@
 
                 logger sound particle particle_line particle_rect
 
-                run save tick_time game_tick current_dimension in_dimension
+                run save tick_time game_tick seed current_dimension in_dimension
 
-                plop harvest destroy schedule nbt create_marker remove_all_markers load_app_data store_app_data escape_nbt
+                plop harvest destroy schedule nbt create_marker remove_all_markers load_app_data store_app_data escape_nbt statistic
             
             euler pi null true false
             x y z p

From 4d232f09b0c02bd0ee095f4aa74cc4477a72a3e5 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Tue, 17 Mar 2020 14:34:43 -0300
Subject: [PATCH 4/9] add idea custom keywords

---
 docs/scarpet/resources/editors/idea/1.txt     |  92 ++++++++++++++++++
 docs/scarpet/resources/editors/idea/2.txt     |  83 ++++++++++++++++
 docs/scarpet/resources/editors/idea/3.txt     |  11 +++
 docs/scarpet/resources/editors/idea/4.txt     |  27 +++++
 .../resources/editors/idea/customize.png      | Bin 0 -> 52601 bytes
 .../resources/editors/idea/settings.png       | Bin 0 -> 48201 bytes
 6 files changed, 213 insertions(+)
 create mode 100644 docs/scarpet/resources/editors/idea/1.txt
 create mode 100644 docs/scarpet/resources/editors/idea/2.txt
 create mode 100644 docs/scarpet/resources/editors/idea/3.txt
 create mode 100644 docs/scarpet/resources/editors/idea/4.txt
 create mode 100644 docs/scarpet/resources/editors/idea/customize.png
 create mode 100644 docs/scarpet/resources/editors/idea/settings.png

diff --git a/docs/scarpet/resources/editors/idea/1.txt b/docs/scarpet/resources/editors/idea/1.txt
new file mode 100644
index 00000000..46b6a28b
--- /dev/null
+++ b/docs/scarpet/resources/editors/idea/1.txt
@@ -0,0 +1,92 @@
+abs
+acos
+acosh
+acot
+all
+asin
+asinh
+atan
+atan2
+atanh
+bool
+break
+call
+ceil
+continue
+copy
+cos
+cosh
+cot
+coth
+csc
+csch
+deg
+delete
+exit
+fact
+filter
+first
+floor
+for
+get
+has
+if
+join
+keys
+l
+length
+log
+log10
+log1p
+loop
+lower
+m
+mandelbrot
+map
+max
+min
+not
+number
+outer
+pairs
+print
+profile_expr
+put
+rad
+rand
+range
+reduce
+relu
+replace
+replace_first
+return
+round
+sec
+sech
+sin
+sinh
+sleep
+slice
+sort
+sort_key
+split
+sqrt
+str
+tan
+tanh
+task
+task_completed
+task_count
+task_join
+task_value
+throw
+time
+title
+try
+type
+undef
+upper
+values
+var
+vars
+while
\ No newline at end of file
diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt
new file mode 100644
index 00000000..a0e2ee1b
--- /dev/null
+++ b/docs/scarpet/resources/editors/idea/2.txt
@@ -0,0 +1,83 @@
+air
+biome
+blast_resistance
+block
+block_data
+block_light
+block_properties
+block_sound
+block_tick
+blocks_daylight
+blocks_movement
+chunk_tickets
+create_marker
+current_dimension
+destroy
+diamond
+drop_item
+emitted_light
+entity_area
+entity_event
+entity_id
+entity_list
+entity_selector
+escape_nbt
+flammable
+game_tick
+generation_status
+hardness
+harvest
+in_dimension
+inventory_find
+inventory_get
+inventory_remove
+inventory_set
+inventory_size
+item_category
+light
+liquid
+load_app_data
+loaded
+loaded_status
+logger
+map_colour
+material
+modify
+nbt
+neighbours
+opacity
+particle
+particle_line
+particle_rect
+place_item
+player
+plop
+pos
+pos_offset
+power
+property
+query
+random_tick
+rect
+remove_all_markers
+run
+save
+scan
+schedule
+see_sky
+set
+set_biome
+sky_light
+solid
+sound
+spawn
+stack_limit
+statistic
+store_app_data
+suffocates
+tick_time
+ticks_randomly
+top
+transparent
+update
+volume
\ No newline at end of file
diff --git a/docs/scarpet/resources/editors/idea/3.txt b/docs/scarpet/resources/editors/idea/3.txt
new file mode 100644
index 00000000..333d6259
--- /dev/null
+++ b/docs/scarpet/resources/editors/idea/3.txt
@@ -0,0 +1,11 @@
+_
+_a
+_i
+_x
+_y
+_z
+euler
+false
+null
+pi
+true
\ No newline at end of file
diff --git a/docs/scarpet/resources/editors/idea/4.txt b/docs/scarpet/resources/editors/idea/4.txt
new file mode 100644
index 00000000..4ffdeabe
--- /dev/null
+++ b/docs/scarpet/resources/editors/idea/4.txt
@@ -0,0 +1,27 @@
+__command
+__config
+__on_close
+__on_player_attacks_entity
+__on_player_breaks_block
+__on_player_clicks_block
+__on_player_deploys_elytra
+__on_player_drops_item
+__on_player_drops_stack
+__on_player_finishes_using_item
+__on_player_interacts_with_block
+__on_player_interacts_with_entity
+__on_player_jumps
+__on_player_places_block
+__on_player_releases_item
+__on_player_rides
+__on_player_right_clicks_block
+__on_player_starts_sneaking
+__on_player_starts_sprinting
+__on_player_stops_sneaking
+__on_player_stops_sprinting
+__on_player_uses_item
+__on_player_wakes_up
+__on_statistic
+__on_tick
+__on_tick_ender
+__on_tick_nether
\ No newline at end of file
diff --git a/docs/scarpet/resources/editors/idea/customize.png b/docs/scarpet/resources/editors/idea/customize.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e50aa2dccdbfba28a48d4260840bc7e88b198f4
GIT binary patch
literal 52601
zcmeFZ2UL^Ww=Wt(fCvatq^Oi&1C^#*0i`79c3Tld5u^nRqCjZUAqfEy6&3ep3o0UD
z0i*>f2|W~ntw>QyfB=C2(g~fAkmRkf%emv-GsZdRfA6^Oj`5B|i6r^fn%|sr&Gq}u
zIoJ2V^8Cq-lG`L95Xi>Ur+&7AKwvNkM63iZ4&Ismxn>r;h}^L{c?^=6_bqx)x|=JfourVL5rb2D17TKi+C?zBc12SJjV`z8QWS`tDP-$xo_9
z5Y3u5H_p4il+E7o^wrGSFVd%NO)^w3{Jy)*Vb;9ojYpJu+|5&k+R@`rM-=xSb=1f@
z?|*sub9Q#-*UaprYCnfTL(}Jd=5P4FUf^E7+(}~dWd&#vAoTDMPmR5N3<>@Vd9eu&
zexmQepy1`HI#KxEjZ;YB%ht{R$&XU|MTyDm{#ZqfV8$Y6{HMBD9LMz`i#=Gt<4(+e=!p~CoRxW7p3z%j4vq>1v%5PX;EF>yj(MK
zK?IyXB+I`vR~=2Duq(L)FRa?yH=Ff|pC&No+NcG^#l>2c-fKHQ(`cK>^5m`Lq!8Q`
z5DCvOLnUd=(&k+I*)N!suvM0VTCl4L1<$q4e+*<9-Wm2#O>zabsv)@Hm5P=YW$LfY
zohO2uN3Hcyi`XX_oParupkD2@;&@ipgSjWZBd;Y6QkLPGxaj+lER@gY1+m_`mpWg+Rj1JEYj=$B3qs
zqO%neP{M2(%6^SXU7{!o7+yT4u~N`lPs76&{Bl8LDQ_-W=Se@GE`@KbAQ*Jl;|jD8
z#e{$Zxaq0E$F%yC92^vw-`Sp{IV`(d8V+u`8Dq4MpS6Pjz$V})W8&`3v+LD$XXrqQ*3DP?N=Fe8h*GqoBP_yZ7(zkH
zWMC24UiCarB;wJujEK;2hp|aD{MMTAloj;As(WCJV3J~@$@gLe5LBht+5>xaO!;%M
z3049{Ocr-PVTANMN${9DXYd1j1k5yOn9kGrm+~Lu9@dR?bex!DSNAc;
z&KIs-}x)(ot4n!#gih*)dexH6B&4(s&HDCYWW+
z6_rxg5(K^_y%@nH!DKb0qoHzTf1L$^iQ3C+|1_=3>th<>*;?K8rrI#*{w+0GUAqun
zhtAzs5GC@T+&R~RxZhwnTmn``{oAvtgp8}`)==cEE@5_>i3(*{C=vuX>RUDnM}Nx{
z%wtg(dIeRoTh#co(WCqx4AoA%;-yTNtJU`787Bop%$4(DQw{v{
za~6U{h9dkN99Aj^0t6c0BgsE5vu;<0pjuZ!(6GWQsAGgOST7|+F(Itz7<-CmQ=O~m
zT>*x-Qc7hj3a+J(M8x776k`P6WYGRnVv_n}C8941?y@-P@tBh|v~&Lt8R~?k
zNubTM=zaAI7yIhJ4OcAslBX7nVwfY{ZSy7wntQ=xQz#_-xb;RzKW?RuIX|EGr<}Sb
z9G1MGqgGaduo6nhmlo&CvIHh|6^vP2ofpTPdRqrCk6aT>P-(m<>a5~XZN+jy86ikr
zx+?*lvUa8N%%1LLdWA
zqiRrhMbzQ&W18N;x_YOOvltYws16mfW+5-A>ucE};Ccatd2#(27sDng_{m;f!Mtul
z6rL^UAP^YbehToiEHMJVMX(x0uvle<&Cc|TL8X#aEjkJO;lX3y^m(5GKekS8ga6z(
zqci5FNUVCy-(bN{)|PWB6AXLwr%j}@CMT5Pm*_?BT0M_ex*=!7^3U{v@(1xjm2)h3MGySmfBdlrrhn773?J{pO(;%=T0-dcsW#S
z1Hrj`Gcsn=n>z+yPuX4*LqmSJ-3m0=Q5Sb
zbR-j{THUG@AE_g5#T||J7bQknd`sk{r;|Kjj-terMtox#>L%_oi#wsB>_|CqZ{2|M
zk^=TKqGe>gk(kWteo+#EU0W*-t^O7mc6QDk-$dH`p0B&cWeIpx!ZIdCuo5enL+O|<
zylDAK^O|RHs?t~XA#Uwgn9QsT(jlUY2t6~W#wOVj&!9w^QC2B}x|&UNL*`}onOA?)
z;eb^lbK$V`eG&8o!)kJ-z@R_qIvYLk6H8!SM+s}B{0>4ApGV`BVrVi$kr(E%@74tmGt#LtQ>9c+x7{Qk*hKvmd7OnRn>Kss-}Us|-@vWn`<>Ia(9t
zfODk7l9vxxT;{;Q+|N5IEw~Es
z?EHTAYxO+4IWY6neTC8F%gCpion?i%_vn`cBhu?iJ3Zz0cE
z;|qM|R9LI&aVNr(mvs;sTe=!0mx^Q4Tx1U-Y*PuG{PRe}*BEa1G<)uOPmc<1L;TX{
zbD^b|uc(Rf)T5x0rpE_ZxN(XCsd7OvhOzjX@m!0^Ees^0m$;+all`T4cpLmK4$=-I
zx`w$!bQzd}ll^y!i<(LITG`yBI5cL`pZ?2X#3_}~_9N0gR%#-Us>+Fir>Ng8o%7Jh
zUX@w3a(+4cC&p4fdwC^nvfP_6KYUuF;~F*Q0t|W<|Ah6+N2k5ZHJp}OPJzoYb;6%Hfqrdv{F^_F793Y_JV3C
zk;-j$jqwUwq1vq_GL|%AWXne@7HW7cyb=`cbWs=U8jXln{1Bm~!22)~X{p&yQh4PK
zgLb_6==Q7zuSi6Yo@D6h&j1YEs9ijHG#?=Qd?Vjh?=XmsjHI^
z^fB2~UI&xTe<1sNbrm;arJS^-@(f~a!fQ1*KZWs$Qa*PMS#|yr_4~J_>OTP?4In}O
zV>OOz42dv?(&CRr^COvxri&~^!c-(7KvmiSKg-z5A9fd94yIKJriw88_=|yp$+`qn
zfsNOedE6#=-bN|vp>K0#oOOh`K47~nPc{a%W+G^0#)gd%E^H9zJ8YF+o0F~F=hPfQ
zYy@}6?57K|Zm2U9iIC%xf#R14yRSVXHylggZ`}AlP44
z1X6Ws?0%}*m?qzb;S0tP>6p_t6B#%M|{VcD(es=Mey
z@k_w0;001|ffT;{r>WGxNWf@Lq2}uomHb8L!d!&Y9^54qB3xRi2nh1H&^C}io}$6e
z|NB02mg)~4RRPl8sL0z773qp-j}l62k?GVWPlR}wtqlpr?30C(FGT68O2Lpe!rS?S
zmQ)rf27S7J9si$2Lbk4B(n=Wg>4E>kTkhq=DhU`=@6iA2n)+?Lp&!k2$4Nj}&YzD_OkgP_6i}na
zeCNG%&p(L?^{Ra4APd5SDG_ZBcFJ6x*9s>|y1KJs(5bhTP$IoS9d0WvVwKx$@!KSb
zJai32#s>+gSppP;tTLV0iGW{41JpG!0dVbFVbGQtal_Xke!h0bMub34DcTvkP^No6
zHjX3;smg>w4gu?-P@rbBv`Mh
z>0YN-lCaJT)2>2IfN;@%NtDPHQpF*SWLMd^#*RAY`I^*F16lt68&I;^`WX
zscy4lVIP}T&Nq`{hvxk%`zzYI3uJ3(>P%{s%l_#^ltJpq~6#wKYL@_5()L0dNkBdVKFtSMT7p5r2*SKcRsrQdPeWYO`Rl4fp3G^#0$w8
zL>CGNgHjj{T3<;zbTysl`G|e(rdX;9J_i}L4-<;KT5hC1r5jeNDm8w)*s|Mc$2%}j
zb0aw#n;sDfIK;L5^TpedTX<3@xSyFME#tGwp@*e2yxw}SZjZ=BeM(a3Si*t07G4R5
zxxIuE-Kvw{4gIql1pb0zsR6{|
zCOB*)eW}QT3Mk|}vxu`dh^{f^KSGn*7LU=ak_+6RC5~vq_-BxFK6J@urk-*mNCj>?
zguNb+e#{Le3^wY8kuuPKJlEr+27_?Dq%g{z5+I~}|<&?&;C{1yRC6`h%b(_;6
z94>Kf-hs*xhc-&iP4cuo3ql@YDJv9t5JLVM
zUkVlxY}V&1QSD7cmztaT3$Rfk*O7U{#aTb-vmN0Tv_K@{F0)8g`V)QFON&1Lft_|#
z47#yJ>3$FS0&Ouyiq=pZww;D?$-tQ$6IvSrtlcO%VV1f#ZT1!?o)f(v_qh^8
zoxvB7gczz->o&Mn$^NSVNBe4^mkfvWFRKgJ7}-XE#JXq23vzs&toD|iWq
zb)~6`5;HjNkR>CLA7U%NSxj8~vLpDjt{hBw>!;-4?S4SDvLdgvX_uecV5FSxVW9B9
z4ZS7y%1y5~=;^ixD#Ht>BWnvDqmdc>LQJNu(~=C)ZO+ki0R$_BnayzODLpCW99{s#-T3G4_JgFDg~UK;VMXV=59}wICxS3U
zG+kR@j(KpuRQ395dDLk_KYQg2pqfn(Nb56n%FPb@(X6_#OS*qt-=tb@9BQchDV=KQ
zeK}V!f9-MxOAlcyy+`NE8$rfq>E6;ilwyMZMpLUmqr0@4(m|z3(t-1d63}PI*z@J{
zCj1Zcp9KZS$YGe>54$I58;(_n9l5f{R3as;qPKbVU2CNi#V#YEu|;yp(y$@fxV(Id
zwO{m`b?~ESM#_7*q3!C2Y^62(lkRCQT{liv4rSBbZnYiD&~rcDHB+!VPzR)rY|W
zzq_S6@ID#8@172!$uF>I36+KIp=-t#EnkdoGurw6L|9*W
zQ<2`=aiz&)nt9$0C%OWoE5#t;TZoVw*|F$>r$teq){w_qhbL$w;cggxZXL7~3UQ0~
zAOGS9V4UH98T<$@j3KOH*i4_`17M{2O%o6x?>_z2>yTZEobeO7M+JSBqw>@7S%l%M%sZQ7Y1CILd5`RWG~zN
zg_+;f7!$)>?QUbvMV5WWDwo=mP+G4sj?ZvD{{EMH2|NHW>3V5ofDlEAp&IFRF^z#S
zjon8c=x7L*nZw1!D?jW%F9FL>3nTOfSY~dn&cjg)RfUr;ec`S$C#0B}&3z8?s4aICO*c%7^eThj+=xEKpiuIni4JVp_ojm59jjr+{|Lm;-o
zFsF_vZgU!7lrDH%WjjfT9wXxWLU^8YL7h}6@v6r*crSjTI7q+jCje*5gZz5eo`usJ
zH0ok560448^0dHCm7)t&WDR1qUEw|l?rwxq|No3X-H-?^E4?5YT`&rQNW#xQO?aymXokt(Ma|Jcdtl{T*~!cv)`o9t+b30ytCvDRk0YO-T*
z(2SWIb*1HIb^VkG?qnQ4=mp&9N8@hj)5*$W`~;yS=?nijs=_$buGeDG+JV}%AVHff
zDtbSmxm-IH^hSq=LZx+^ep$Fc@3b~l)TVD8s+HwR!#F{vXtteMP=A%nv`AD!!f0JV
zTw;{B=I=v+lUa?JD9m9)liO?7ktauEu$6(nc${)V`ohvoQuAvZqEcp)KwHcHHe;=1
zgEl51<4h4{oXzCZ;n#qMK~nl=A9|oODSd&dw{$yzmnF8>Tny_^-)oMdD8_WQAHATp
z_7U5k
zU-MDP=8pSoPN_Ai8h5=@HT=D0*R3P6W<|xMOmQehLk!<`G=^BUl)h+QW3j(;Mcx`U
z;$`JU0xL0GeFMy`QwEla*`6Wa-Jyr{FxXP{(OWxadG<45sI-H$Q%fQHYTvku#5fwM
z@WqVR#bm`Z=!-yc$E4lcuBM0LGboW2a;&m=RBa+FNC>K0k
zzf(^Z;cdqR_q<1rBAzR^-3V>F({Sg0ARP982-$YZ!uFjY7Lg~_R^bPO3^^Rc{Sv0S%OJuYAo9MquNWZ7uc*m`RFQNyoRdI$3D8CMnqfU
z?J(TM&~4IMx=vZi5fogFlMTKiKf$Rnsu}r{pCYm%C?8^mMPxpW^MX6
z1NXgK-uXAP0`b7@8{O`y{ub(FVfwUZl*^C0rQdk|+BI~^RisX04+CtKMQZUyJBvLV
zo62CNFexb(@m{O52S*b2W+HIzE!jw1L2^94CQL=@M9^_$>*ZmI4z%+Xb$kW24tqKF
z6M^&<-F&zneZj@wZ%E)$vQAFF!5S{RYL!~xdnAy#=*q}ZLShx*8WxE98lt(x4C
z?%?^ozI{PNfA1NPS|00?#bU=xbIdt-#e32~jU+H)&smb
zpvRs_J>4_zC%hSA%$!eN;|2;fp#jlo24<^mky@|1-m3`
zygKr^S3!VARcV9m?!P?})azC^@Zt*2D7BWal{-6y~Q5)0|V?X4~DJ*5VtIBLLx-3rY)eQ{33I%XDR
zN67a4#LCT^{7vfTgQep5<#ViOz*iGRASwHS<&Gg|2RwcJ(kHI^2&&uWjn;hTQ5bSj
zE2;m4_XP#s$!8;8=42I5fox;D6vNWF(pU;*VAxG~U-fA6&@`1Z9u&kIxlv}YycPP`
z4)QG!spt43d#aJmIdrbXDJ>`HHOn=?w1yhR4|CW%L+`O#uGP8(-^Nv6wmxppfy0=q
zlGqGBR|l&Kza%->xbS6#o&H5b&?4ELkJ()3u`~%wb*_A+C6_E}S?T0C8fJA1L$cRy
zZya%r3ekKuWTEQhw7l|+IF@N#|3yV6j%PA~*rp}Eg?0Y;@0wpE2;e_L2CZ3ReSo~yp-v!A{~|~=5036mz|hpYtV#qYX>6ZiUQoh(P0Z<
zszDU_dwUm1TiYMDQNRo%LFA55cc2C{m#6`taA8RueVscU)=9l|inQLm7
zY3`dJj=Py*`h6^KujHeV4|$dwmC^z&&atXa<;Y>T!C}!s(f=dl|L7Gt>$PN2n|Kb@
zCmXn>9ret@>pEwAZP7D4%EdML^@=L|9QlH(`*gZYdf+ebV%Vj@iSAc_X*fU)P+q_mfrOX8Uq}B{3h#7)v}nB5QcbQf8vWm%TmJu{gvEpW?h|tp9a+qg
zxH8b`9*e!p%YKZ4?<
zM3X9=Wwf#UECkv?!OMlk826LC=i@?rf))qHA4l)JHxzp0_DP^Y#p~n7Wu~6D&AXRMA!`$LcHff3h8{<*+iq
zmMku_Y^wrR-xWEb`_?Fv0u!EmKH`1FlrNn@#5)bWyA`#B9gKfs1-y;3pmL)z*85o8$@-v9Vsmfr?4djzYk?&S|#`&-U$VbooKA2+rcv6RUn($`Yvx>%Ld@wh44I#CyMWQ|&F>LVG;=
zX3$vNT?}gE3Eav85EviEMpmDB?7As{Z@(FjY)PxLxRP=gnt9nltOHugVVR3r7G>Bi
zpB@KDwu{D-kd0{=+z%TRiBzPW2x;Ri;4pXnzhlR)Id%C<%XRL}Et|QXv96Z=2wQ(f
zqN)K%*|2|+ga3Ro4!V1brOU6sX}b*dU4JG_XhVne7x<4o>a69uB5TmAXU)
z(a@=DdrRU+;w$V&;|}*_`zdp=
zrdBaW`(I1Fl^-lkQrrV?yT@T+(2u%3JvNSMEM|xry?lx%cZiIO#Ce7E0tp7`7m#||
zcQN&>UK^>r(?kK=<8tpF$!tx9s+N|U^fOx?RM(63O%;uE3|0>4eroi7?BUOyOg=}HsSZ~*z$aiCSQ+$U&7E&Bqmf4BGSk!9hgbwbwdSg
zgBNZ%aqgmsyjEE03(b2!8nL#Q#6ITjTamAvM0Gp$UM?EQs&wMB@)3#T0;hqNn4+IW
z7?+Ub?#oC^Rn`>y3(x$C&)}%M23MB4Fh!Q_(u%?_2XWZr#;yso>HsStQ
zDhB)chl-7`_`V&@o?6_apOmJrCvu-o3WvHFx)uIa?QYuB?#y|)k%IA+mPv+zEXkUh
zWg4GyQ;psm?I2uNW1e16;_U64LEd(n&S_WCngMr3=$8~;6xe@#JB#>ZLUi&AVf(k0
zZ!7;yIJ3MDasR~Ej=Js|FMfduWyV-bH95)rVPjoQ{@Rg>Zr%OwI_dBKkvt`_0(TGi
zIV8_i=X;7q?f
z$kDz9gLkPD(W;<~TBQVFWxy%qQwg9yyLttCh@hdJYWqzItZ8N=X7$Y6Ky_peoGZzd=AJLw02xdEYoe}n^uSKF&;s^^4K-e?
zhoU}ZRH)ve4@m*V^mVbW5}-tbhq~rHN-+y+ypOu_$pp|DI8zZCDanO%A96Qh;n>rZ
zO^~sezeh|!59CnN9;d3^h>ZudJCp9g_V0B|G7fL5EByS@*k^RBK13B&;tOA9T@=C
znCD?C&Nk~x_tQX}(ha=d^Q5nLqq7lM7R5^g9!I?$9Jj=>{I(zRs^A0ob9lRVZu3L#
z=3CA`-;;sOBvl$!@Ij6hkURh2(oJwb%477vn6Rtq-9T9Ifh4t`uj1$Cnb|>W1D?JW
zpzP(TT2`{XYFRl9i8%Fw_;K4oL^1Ej>A7qAAMif&mwjJkS|_9%5z&FiLFR4doMe+7
zymi;t!>_&6l@RcEvFnoM!(q;ko~Rlpoja!slC|WO(_4mqx`p)iHLbYm^jcx1e+mK5
zE;a`0Dc!ygVfgZ^x>GZhG>=oAfd$Ry6%$51eGc6r1UNovgdNAcT{(;xyDr^$MEdr@
zv=U;lq|g8
z$Yr6O=eT2iqp}^7i%%D1h~a1?IN?x+M1-s8wQdG88y`(JFElb$_U;(D@)(^`1~Oo8
zHE0--Aii@^No|gi#VF>d;%#GPQ-Hx8T?X06aK}G}QzM#0&%e_AM5__gGydb|TQP;ZVbC{pQA36_&PXtN_j3`xMn|?it4D;=FXkwabHgJigS3E
za_&^>2e(|(NHforyDV#cH0(GGIyV?@W5ZHtd1BP7lE<9S2F;U>$;7IfK9L7U(25I3
zerDcY!F^S?y7N03*BOPYufcY-?#NEuCef&mx}xkAY2A?L((}VLS}$-vUH*rr0lA`!
zI=MKRIjZw=Wpb**3P=8BtcA1~_JlYGN@NnxW|OMFI9t);pI(+2-t&PMC@)dg9`LsP
z=M)dxZ%Yxg-tV~^aiv`+Y02^Jbq~%S5pf@nNn-}sb2sQ8!6cTuUf#N>X!^p}=4&i!^}muCSDE;cF}Uq*Ko78+#4
zMrJ*_>bSTW{>X3UvPtybjy%^6yyIx^i4JrMr~k<$9EL^#MX3q~p><_b=cTIzFvr#^I
zM@LURy5J}@K~Mj(9b;(r=pCYdOkmnwvLg%S5z6_@Z#rT_!}ksMHgT6cz6Zu(@0MJz
zAVlV3MV6D%&iWaLDpW6Nh~|i0)6Cf3Q{+jHblYCm&sWgOrIokjHqaJBELFlI+WGb5
zWd9c0F(X=7i_)zJpp}nlArXLkKJc)yKozX*S{T$IhLoFG=g14`YY1vRbaMQl*DZJY
z!4ca0wjWzM4(#)Hz&*Z-T`0i4F3YKKY7k0fJ$k{B_3n@bv33t4LwcY2i97VVqN7R_
zg+6yDTScoM@lt_(nQ?c?r`wj?wc~!9sG{o`N;o#xJ>`xMg<(0bKTthWn(UK_;mO;S
zb%7AvZSZU(RllvIm-P=OgTHYaXzy}ZoNcu|KVYFIf!hrcwrSHq4gRO;95*RFJe2q(
zE^5_x$;>6HI;j7NwItVH;+Z@xOQC0}`r}zO|BXm}6UD@t^w@=>@z6bB@h)wHe)rbIJ{m0v54M)c8;4%!8&+^Vp9hkuR49Rrhi;Id@m<-Dsh=RaEHe+uYlsbTav4GMklkOB!a^v$as$
zHD&k2PwP&x8^k6Mgo=WXTNf3(OT+Y)WP5&SVz1)DuyNO=YJ&V02SCp7a~m_5?GzmJ
zq{Sm_AN|?$laKZwYzr7eRMNGM*7udMvsq#tqss5Hdq|V7%7UpnM^qQK{1J_I9*#Ui
zTkgmybxOBD+mUx8ia%hFh-zQJtZUW)XcpvDefklFkGEobeyHLeN#qdGF4?w$T5eXJ
zWsM}n2H2S_(AT~=NNgK=?&Ugf>K3AUY2E2S^g2pJTSR`zU!omm;2SJBZ>?$W`wPpI
zhbqOOiLXex^jr4L=(FuM$boe626GU5NMP)*wkxHmQ+f3^t$w$t3o2-=d6KEgv
zPW$taYa!o;W=}69l`UX)zN8%S>5bkD*RrSTjvR+*h=rBY-`-|8a{Sxw7_e-J5WSs<
zE^o`z8{2VqE6;5lNzh2^_T+ke2N8l?~2D^lT_w)DNci_hZU_2u!p
z-eU|*0vGTABmD&EjKs6uaZ%l%
zpu;O2FPY58JHLjmBH)Whp6lMWDR!A!ja!!TK0}+P)h$JknZeyvUGHO;cO&5XCKyMd
zU(xi{k-8vX2tvOj;V9UMx?lad5h0yo8{IvNmkq+AjrNfQ1@3;Whx!)}s1`O|cw>0p
zq9JEO;Mwn*=)x`E^hS8^MQ^8zoVd8AlB!a0lEhpnO(KbU3<>0k#u7w{pPliS@R&@q
z5vbu}N`BB>g{H)lw_gT)-M_!~j?*Y4p%h0{JG#mt*Z#Im8G<
zJ$Q3)?BG4^wty+FaiA1;BV$^ZO2c$}_1^4t-FM%%la%E>}$KT=rqcU%{NeB?1B&)01EG?xy5aoKc
zp`H2ORZmbV#S`<3AQbdjf*zERiO{%%dbYlO)7On}CBD7XF^a}sA2`?%uKxa&+$Vhl
z7__lIPp9VzE*YR4D)uG0#LqKtuq1KC9VBdH??^vNMyI5k?S?Ck&&#d!L~$mVH|NWr
z+~$NXw8iMqV<$lqLh2unHUzjOWzaveK)YCWXl1E~(OCPv&(8KquR1kSK!H6BB)8_$
zMQcOf(Lr>xf6bpdi}dyzy|WOpHk8cw%Xe0@>T>NR+&Y{27ze+8ZMA*n(-O6@SZV2i
zs-FyO-w-3;rR;euu>gCXVzgCoGa1%G?*%0!Ah}C`3LJL)YhO*YVeEGD6@{s@gMTom003qC$L^*vhaYy2#RwZv(Hqp
zOt0$;T@jaG-n1;gvb_h<^PA`O*SV;rCHaGYqHp0i)r!kOki5n%%=B=0zsXbgwho|v$C#$mgNKr%uF
z5|xhNgZ+Pf0NQLZa+(DGc_oOj(e5vH0IF#_{~{Jh!1U_DdD_2*f`lIcm~)-30mkS2
z=s$mnrPgNZY~4`)tzo^Wh5f=&e-V!Q@zgH04=dnsh>q~CHLdl0yR2BEAf+ngb^nX!
zdjDfe3vLYj`476=r&^6z<;QOd#VTD*WdvvhV@JHB?z|4sZ3URUO6I+|sf_&u4uUp-
z64&6cd!XLem1@|91C2S}Rh8hLS4+-U$U?@_w!z=!Qk0(ry%vMku50nMx#~=Bg%OG-
z)Ic8`HovK*0PSomH0Z$(pCi$b6i`VC`?R2iP>L5)wR3Lsz#e1KXr$VlvDBY4smHwp
zCWdg-5r3RCZUN0BLdN{ZyFIdC6#Rb=*)0ZLX~|vhF|tv#hGL|5!}1^DpJKW{=85yZPX*ZV0-di}ubRAhw=>`~T@W5_(U2CctcP-RgC
zn%LVD3q|=8TQhU0F40Y(Kh}!VI{nNGDHgB^G}g^0H5hvF^E4bUL{`7TbUC
z3)$(lw&~}i(pD?Uue7x;n$DHxJhtz#uwJXY>Okpj$gj+%{8X6Q*_@{T$)EnNpNsv0
z^Byu(NY<-tuB;_r#1&4Bk1S9-KCem&aEF2g4g3wf4`^&c-HpT@3R_Gkv$Ii&iPQ~OKtWfxL{VtscV
zsi|Y?m>mZ7P?6PMdO^$Y4F_V0%Q>phnm%D!<<6ylE}2JvOK!_P{P%S84m=&d#2j4vse*%yqZt
zY=cit*k;Bj#USrWniH#R8_xgj!IREV;(WxBvJ`8n=cVKaXL(E&@tn6`@SaiWIyReG
zI@}kYqvJK(dshIrYSII+*RfT~4bKg4<4yH7NGYKD-PhXqA)7M_?7v6e
zV3z2ck65{w7<6yi0%ctse7gg}a19?I9l!*qbCSe!H=Ku;L1@?0zYE
z_iHZs^O(-__Tj5)q9Q{RzV#ja<%`n^zC05Zo5+tUXS?t9C>>Q{q?1mLe+=r0Kkzu|
z?|9kiBo4)XAr|>oXSoAclk#qjhv}Z%Wv4UTHtnZonJW=KN!H%tp)L2`MIYPdSApm3
zS_-jDvK9NldyGYm962rh$!zlHvYzHop$BX`@0sq=X*5;w`0mfRy1C2Gez@kw?r#z?
za?^_?(wwnqM-Z)RyF`il^&N%g^h1uMWYg~YAi!{)9UKqcyI$gXe1Yv`((jC^2e9nV
zurfIS5ctb?X}WlGxr7N=YNMFX;59~GQW~+~b68>l`5FD8SetlUyg$9&CRwYp^Prx!
z1m&KH-q^uaWnWYW{&v#WqH|i;jOgT#+0HZ9nFsyAabkMt&3?hzo=zM4fI8smTxC#c
z={PY-{y;Ll64q3_?Nb05dwu`V1pJB1vz04Ly*Z&@>3jZOw9_mban)Y!CpFVS-y);y
zhQ4UqnoaEJF;vR2RkGGi>ELDCJBuxtQ9SHNj;ZZ|?)S`cn|?z|H{Fn{v872aFIUu-
z@}SY1TQZX{68Cvk-%YMwXIff;As5rQbkOI6IkU8~h0_(-+9``2Ey*O2ryhbBxy;-z
zTHn#!i3P5<+2eY-6kw^7_}gl7k>6sob{fW8_q%4@mAL-T-lo!iT&&S$LKHuJtmlxD
ze+B!O4yjxIPo4aYtZ9nN1xz20(QR@mrRz$A(Ha8oK%Vq;lHBN>`pa^F7e9`~oi&Oi
zk8pIpyd95=rc)>rm9_J!#l?c*+jGXoa>y`6e=@$6Ln$3@qf~OP+N>`&UmRQWfY3=BFn
z@#fE4aU{DqRD8genAXP~P(Djrio_`&7lW?eUk~54fYXb&^4PnEZu=0Hsf~hu@A>?7
zVN*gp%p=<>%^iA{Kc1su3$+bCA)QQN-d0sMUYnc(869|?1SyMTnZOOdQ+8TV3{a*-
zv@deldkTlNTn*LF&1Ixja&~2?+P4|zj|WlKiLGCE!$C*NH?jlBo4)hbyc$)3QP=RO)1Mah+uFPA!u0La&9XTE7I;Tb{B~c2EIpV1
z`=yHH(y7q?jll%V+N
zz3W#-aGlE(6HrF|6C-tA6^9m#L~yFw4SlZ6MHo`yG#z#aeVf25F
zOC1{EfVi}0=ubY~1Ij1YX{&*sxE3VbpicYK
z%dr1UC}MhPHpJ3R``~89Znj;keu{QktCQl9#<=dxG^x-c$4RGbn$WkuyLi(R9-M70
zLe*-sTatUVZj}j>1GzcQtm8Cv%5BDisheT_L}(fb?R+1v^isGqxTz8K9lx*J-^0C}
z-ia?=9yNWGRc0C=HFS$hm*FNSQJnjzQCPXZH|J#oM25iFiam2@dh}O24f)SRXWy%@
z9MO$S8j;l(Ms|d_=O=TY;SM=wC~8xs-JlJCo?Z((f7vIveg@v*%vX
zx~cm`g!c>eYh_IG%S(Q@UGqFjqE0tViG-(OW9^@0?ejo|QK)N91Q+f{-U8Ou)(3M;&Q3(A8y{f@aVN9UdZ9qi{E$t|ScPx=;|v&#e2ycNgXH>%u#e
zadFsK@2%Bg!Ee;ROJ#K*?C>#MgPsgSr3ot2xk_zad;bYiF37yEi_ApTUiuy#GhB+N
zmCS&);`l*-$NVG?vNhx?>-v2DFNt54LdN2BBI%~)4iOXKj6MFjAQ@vz*@$hhmZvb%
z#w*AkjHMM1$5s4;2Fg`rUZHl;=k9&UKQ=ajuz6h;7Jnc&ZL3ZCqbvik#;<+D^kJ;w
zqBAypnF;LH$$yhZLI$|MpA2i8XD;x4Jq5Q&MQJe>PUH;5H}tM6a}!A|E3oIKBp40x51bO
zmv4Vul^ivAJ=xBMgnNR=2TX)C4z9;sEg|o#t9}ypu3rM;cX1;Ol+^y@ZD%%yDU;W~
z4}-3Pu6uAe!-f`hkk{73iRP;wQo}M&Z^sH9CIe4N1jS|xM-?y<1J^m)5
zJO5&wOy`wv6w_)EP@jw)9X$%FxG9Nl$fu?KzJ`CXBf#MSuPDB=GPCB8F4V@(zt`%2
z6Vd;j41BEb+d3Uwf7;gjtb*vzBM>552Y>|s#o=p5FFPj5uV4r}OQeTfXMUCa8)lwG
zqDjn8nfqkEthA(&Dh{2heFgRwaM5l=7vYC$@TPzEjz257A-_^fHB}ko`nSN*l)|9k
z!{(2YQF^ViA9`rI$;Mhw_Q_?fAHZpG`e{7E9T;B89f@e@c-GMQwkVM!zkRPY7cx+gTb$-NY9O4ozM9Pc56&`HmqTMI#JV#27Aj1}
znuYjvGu%&QzZg^+%Q+Vgo?#?x1Qfj!YYgh$e{6Hs{;z?|>AZBrg0%1u*DhO^Wp70f6P5V9>a0h6)Xh_2f(0
zF}^FV3~8qn=*QFVPkRPITF&q+k5v9XQSy@VKA&OE{Z<>%6)4n70@^vX$}PCc*&f+y
zbHG4N!gadXAJFF@-=^5>zm)Jkhji%Q!}b$=O`6SV)aQjCOH^==Db`t!-hMke1J_OS==B>EG<%T4b?fA<6yUVm?yq;)~x8o!(gA
zLEK+7J#qH~w(9g1<<306bB|jml!UN}LbEW2(h3FLH*H_egez;jd
z45FkuRxX}ds<26tJ+y&Eacnlp#b5*ur0*I_BTa!Y=#dBOcyYyIpnhl9zqS*T@mkPfM`tAj6-(#29<5KOVh((%@X_OYsqN
z&V_5ul|KPlO~s(qOa2BXWDf(xbNoS-`e<9f_#vzJmKESUxM!9!br1JdEG97bctqOu
zarbgZ!`D6fUzT;Yo-BJpYn1jeHVZcR#ihhP(5>NjrMHR?C+uz^$S9tlNs$wZmFj%I
zq@kvC|LaMA?x(QPmw)>_Na0kKT7fdR80r909BcM-o5tS8i2E+r%3dyS*Ot*TkSH`n
zh+`xFsORNXrzlHz#OehIJ%ECC?(WKOLZ^%`r5vpn`{48D=o78J7V)9!w4qzHxsVr?
zu^P9w6X+bubP#=UNmcUR^H2}pT-vl;?mupR1vJOWz07nGZL6u$+v-s&ZP|E9f=RB{
zEAA&Oz}`;2bMC`;`B}=`8#}3F1c1PlJt$3S7Y8>noRF9O~}t8y7;(MJPFSLOFFpIhI@HF3~}haVQBf7&Xpj456Y_DoRe}
z6otY#8*&OcB?jX-&NCS2VaAMie@FNIyYJusd7k%q{@3q)-{-yFuB)qQW`Fm0@3r?@
z>$BEgdoAo%n47~~K%VOy0q>_U;WzVnvPg`_1!N@J@RjroWb@xA<|o_zf5S1$M7rx4y(;n@|9MgTdmSh&Tx39unpm!%z2+2?CsN
z>H@PuoCz!Kb>4(J&0?2`sf>Z)$*Xzlu4!UjM+4qimnDx%7
z;=_!52E}drL4gTnk$0&N&zQ-81cr&b7W;lt7@(vRLPHMx;LyPxYL}Xvi$_8j*^n;AYLyh=PEK_g1xJ6`D@G>%ylM
z=0xe*NUu3s{mZn@QE;Pup!Ub8pC(?hk#_%2A#}ALqYn?d901?GR9O%?T?*GRIG-ae47`?#!YBGuheyPHzk)8!o8>E>>f=9(`;V5Md6z
z-S>F>?>Nun@nq_0>h2XH$dH_GU$2Jxc27FTKpJ?%=$^9IDL0&_(
z*_eQnwkh
z3u!s(@epBG{up~GXIwuqdd{;6kw^9}J3mk-lD9NnyxD_Ln&f<=G_$BKb-dUJKinMm
zhmd#)EbIUs7Y$fpAlEyQ&VvJ5jnS99L;rM`32w~L2%b7!_M%hy^ECu?$ooRMOk5JboXJ`yzO%r2Y}1)
z^-?XtxUMa0c5{!Dc4rYv0*vIh?O!@7v@mqcLV@@J==yT&+=;atk)D
zZ8NJStCvZeD2qB?3f=s0IU*DQllE0tn|emiJgAIPK;E7xv_7;)~sO+VmO|8ZCa%mjw;ABYjM8E##Q
z0+E@J{jecISa#8CXfABvZ0yeylnomJoalk0>0dhIU(h8Y2eL{U-#x1mZFbY%I70(@
zd44Xvs`>*S21-2&mRddg>+}sokyhmVJEjgW(*Cz*o4O~AsgRUewU}G=a}&2=Hkd!+
z7Ls-`>@x3i=<>=iX3NQr$YgsORwl%$JO3F3K%thL>+5UO?+1jbC--o%(Q6BN*;cz2
z^amdk&rwQ`B>c8E5gG7dWsTq_4l*)JUg
zFh84>n{&?!bU&N@8E;xqu9n5FZ@qj%ShIMcXtjC>I-U3MIFy{zQn=pw>WbthTN?@U
zO|q(fQarsy^wrgBxnrNZLjV37J4WDjA)C7b^g57rGxR)+O;fbijO|;vzOBK2mDWhh
z>;YwI8`$=2>#_sZx<#?zB2QaXxJO@RW-gIQj=vyC1_xS0YFR28dbQy0&a)zp*V}kp
zzEy`DDnYADO<2e4oG;hizh5QCuhz`b0j8tGz6spGboutMal<+SRzk<(P3f|?YlH=E
zFRMaFaBm2@>Eq`h!*y3gyh~>|!Qh2l-Mo~OF!!n|EC%_$pvm1KercvklvrD2G^Q*^?PPl*
z{dT*m1Npp7Y=BVi=yGE@_A(M2(ydyxbeXg@hUbDL3(Mh?ApNbK3Sk@F@364HeP_RV
z=6MCWHq*VCNc~PM9;FS{cbQ153*KC?yTE_1k+vtl>563WV!+QllqOSdzY2MgdVuj|
z#^(cXfnqde@^`IZdq(k05f8k4eedGAfW8^{nEMWMab%f_S@e;tW@b~N?|Z#VgriwA
zp0GF>yQoI7=miS+>L6%@vS%r5JGxoWw7tw%KQxnTyhQoh)zk_N*N=FK
z@t80lS!yqvm1+Hg_NGuf0aiV1h#I=NoapiFZ7EZ;trn~St}8Twc05DL>!9|&6UnIy
z)5)q4c#a>*I#KpE>U%S+=!n<-PtfYZ_o=7Oz8R(^#m&XM>FI$Jf0XHw>P)doJ=BNP
z_Qy-k^w+7RcKmx|d6n2juW?lOU@0eG<4;|yEff&J^P;{ylkDQ5B8Ji{@wD1PzR(hE
zWH=L%8J>Z@TiX#!xaP3yP?pN_8HPlIx`cUwdRBAfXHVTsLvNp^v-t&e3tjil*Sca)
zg1rpb;pFS5o!}@fT%TT3+8DCWqA)Q3JgfmPsWMYZG$f5xXjXgn=o(oRddoj?MkE%l
z`u@z9iJl~{RMF*-jn`JMFTt?J7p`0L_0a5eEkd{4Xg~CQ+xkz0b@o6fH@@y7)*<*|
z<9t9q)oYwu&oyp8r_;x<&^Rs*ALrQ(4n?wtE58nuB9=n47=`C;>fB({soBi_a76x>
zrjX$+Y5o-Nm
z<8k{N@7fL@${?)3Vy?7e5XfhU{9>u$JGL-mXENpUlgvtRj<;~l^&nGOz8Rf2=>uEt
z@!w&mVJR!z)%sKS|c+MqOTgUJcAMtQUA6SN`X>E
zomCM_NQ~_W*vI
zcGTd)vhXP+j}OjgZ18E&bdP;2>~a5I+p(FhnZ>n$lph`%?rIjS{F*v`Xu=moq968b
z*8my?dkpcgfpW50rErPwDxU8gvgl_`QTC?9$Z42OdPzz{0RP!o!NiL;3=3>pV^pFD
zeMeJuO4TYMZ-7psyzG~Eej9Bz(B76hezQETx+?W+{;ii3m`7nmW^KobVGwrdr4^fpoleVs*mxq?CFi<~OD82@(W^DZM*X;IW?t@{_PZC&
zbxWNN&t;%a^x(1GHh?bVNJM^_PHjgA-L4!yOah^PjR&SbX2wU-bJwky)aTTD$TDPI
z6B00IEC>`+&x-;&;$8PqgcELJSrg&3+J9As;6y2CxZ0
zEa0cFqxcmw-{MlKNb`U)H}f~GpAgnp15D1u#)t18Vpuc!#%RAiDU~pPoQbUM2(?qs
zQgL*~Thw*fmN#{;MyyNaF?W9r9Y54H0+`D<0SLJsuu0|vpVdA*ckX)OY~b@(56?yO
zohMXu)p=f(`u>J1Jh3rQbWsPfrBjEg0*_a1_x%2Fq1~QfOv%r>dQDF-i#(H=O`ZNd
zpuE=ST7ij%jyPN_OX?g`SJMUBCaS|3KsWjpf_;ldoA+2L=fz?RCVlwT86|3-?GVPG
zy)EqJ9T4)JpREnao1q1HAK6kSUD&SZv_x#Xx9Ni*+Xp_sJeR~tXRSH!VC*KR?i#@D
zB8y1O^zh0!+|>f-``zF?ENIo^+;i%@UttuL@)c)B|6i;iWD)^@n}G9G6x;3z$);pL#za>9uAtM&4s
zfsoI!Amg9?$Ap)#}OrlqKNvDkKd{YPRd^SSC_Ko|AF!T@Z55qhRk(Py2
zk!TMa=kkH##m3a}6xtT6RjLH`nXd_6K1lLycE;JPRhiYtmw1;HwsdweBW*GwH`0%cH
zb@HNCSWV%Za+N#=L&Chh4hDeOEtpkaCIVUBRJ{s2ChFM!bG?zNa+BU8QPTa>nw$NM
zm##*FrvF-d!i5V;p?_Sj8qWAyGle*-R^^t}sUkcyK$^6Rnrw+uvi>b~%djM$cwvf2
zbbZZdmv*I)w{FfJL)od-iUIJn1JdUCZeMRHrKWvAzBA(@$-Tf
zGntm%=0jy_mf7VAq~ZW@Lg}M*Cm7!SN|4g%y{7SG&qqmG+I)GhH}T6!wAXaBaq~G*
z>@%9BRc9LcZTJ_xot=vE*AJE!9Ea6*+y;s}B2yq6;Hd~7Se)Atgl;e?j{BrbBk^!-
zeBBr>{7Z`@7Cw~17L_n
z`hQ$mD=P?BMUNh=3Fa2U?w&e0b!1AbV?P@hIWU5%`nlO|mP%{il3nXHUa>4JQ6j3xyIz}+7qG|V`ji=Z7{B7U-Tiwra@DdEy#}HD$tv&
zC)%tR(i@Psef0wW(rH8aTE+Rfr$2#m$-H6Oo
zP3SdN;oxrsHZ3@j+PgM8hnSlmZIl#=mhl;H)Od9aapU_;g4KDxDRAtCuLEhVOB`S!
zp7f(x?Dyn^(|s0>fbum}=#|Lcn7sRhT~*UhmPW(g7VgsVzOIccRIs)-4o{vK9T|w%
zE418IHly*z$@7<4I8GvcEYzE)hU>F=wm?Q-clqN?HY<=khFOGWI=G&{jv5k2$*tP
z`<3US!ZS0&>jM|^3T1Tj3y&Z{_8sD!i`rqtj^?$?dqXBW!Tm%kgg%m{JYdICIgX0(
zd|w+J*EL@wsxpa>jT+k>)?ps2=`9b><;xy$Gc0NMKiKn0ODKHY#Xbtrw{(Jek
zYd%3UZNa(3QJ1($=UmDSY%i)C@0sxgT&Tv8chD7meGpf*QLVbI1A3O)V_%d%<5c6t
zY+mOVG#wCW(2dl4o4X?QtG#n#aojXTU8*3~Ntcit;=
zttr2Axz7tv_97Ja;Pa33kOhz5zWPZE>!l;EICSvDC_QVwKQ1e_-|aG5Niv#yHMaXC
zy7H-@I!M(XxxVta{%lP0m1rMw0n>IaZ2c@P?P*41{v>3*Vp2=>KYC**Cp51_Tk0Z;
ztic_$icUOax<+C42~x0cw&
zf3$hu;LFy#koP%z`lo8eP#WsVfyO>wlZS#2$^KfC;iM&7J*Spi-O&P0E|7s!Fq|N;
zd#FtK$9N&ias10eR}h98$4r+o=nlOzAm4AI(V0E%@Fvg1CbDyqdU1(b5pY7U(@4@_
zz&Kk3KYh*fEgvq$s-*Tl!=%NCMtM*L!eXy5ERSXN_couvmm=#rklB`2)V?JPkhHM2
z!#KOC@+%^AL8~>UXg2;+S>#t|_;BlfyKi4LuhXySmQor_DDrhMD~BkA&jZ|R__DZ5
zRV5cYNR!_phF*+hwn>Uatyd1qkCJUHhtr;3q5;#ue%tkuEXsSHuib%;#a-2jh8vy4`*fh^^uAxS#>|uvs``Qf<*P67Ru70&9M=$$q@zs9o0~+sOoNqRaD(othFzh)rb%}HM)1p{fJIpncWFNf&T(4SdRzKp5|i((Dki^>1Fng}!k_YLLqX4f
zzgi;b%NKmn`9#3N*X!m|Pf6nSkfmvu_s@nkybhSIS#?$m{;SHJ0F+f
z-W$`8PWXOY7$rqDH_V0M-#n6=w}X`xeMICJ=~!j?fV+F7V*IBp`i!pMeI=7BfXJH2|-a0>5JiMSk_KxXK
zo!qfY^mLkEh3+TUJxJ@!o>!R#cC-=F(g0-_7qDjs^zr0NK&&@lq?-I*9}KL#>l&$uV-`!r9moNz$P_rNZ?UJe
zp{P6AWEgeznZHf8yUNvo0kfBN#bbrq18zd-Bbi-!INMlo#Xkt>>h=Q7toh4l6XdWn?*(PGY|2rj_;>moU{Dl%!
zf+yU;9NZ<&pp-baLlm@{*T}752EiNl3!m*H7LrWlQl@SZFBRDy1A)0*dDikO$^%=-
zc3N&)S*-W0ZwzpHHM>SjSi7t@;68
zU`H0Ocsap7!Oomk%TjkLaYX`UYd7hEdS!Jt_7$Nsrn^q_XYwTMV@Zq3xPAF~qE1ia
zz;{6!A65|@sI5$m&xqOht%%eJ^{>L_m&}%qBZ{_{TP}j@H?rGcHY={FAMqSsCorF^
zz2B(lc7!_+60t67qzw;1`05uv&*+o;CdkCzI*=gq!o{VSFtCMy1K<+lZw>&DzHS63
znZNKoiL!})G-f@nV3$KHvgklmROt=?{LJhm&13W6IC8mpIZB>}Zg*ZdWmzS0WH6?C
zIX?T&&agLmz*QJHY-<5ZUgc$YTg|mmtxK0jFPk}tKThSV
zBZeS6+A_4$lS|KTI0G7hGhm5$P31B+1w^^jkWpcLF27s>)JCJ&$OGcTmi7ZMJ;h=t
zt%Y!(Fus|uA?VJr)`H0BUO$*A~XJgJbsCp5FoCy
z8vn608^i_&JU#KGRc}r^`$*9aGYCX{jx(k#r8^bPQil9uMwe3NDG1zWD=T@IU4p}R
zh&yk?;JwZ2bsff8mR8FfDwUQz`Nk5D?Zwu9H?B=WwiqtWyqNVJre|F;H6K_YM>KXU
zHQIMFSSSe#d1QZ9+rK6me$GP8Wxla??`i*5$UGWXUe1Y3=n7Yo3199cCq1fteMW>IzOe
zuE0Bb4CU7>b)LB#W;jLF@Ue31f3q)U0dB1FrsMvxlYD&_4eG`f+-Nd#=++RRE6bZ7ENwZiwBZ)O9tRkp4}@j^0SB@kjeDjaI&$4%
zSI-LU{PJs>-<_WE(#OsbjREUTQ}1xLj{lL50Lw={@XJR~V2rLBi^!}}%lc73nx^Vn
zxsJJUy&?cI(e>7T8L-m-z5!dyup|Bu3U2kBbejl9AbD!dXjjVu7^}QC4&NW+c38N!
zaA0H<{ygc@An`w-9qqOw{+>VJ;vK0dRRTyeK@MtDiZA0Pj=5xDL_wY~Df_|u=
z@}IeE#ctq*khqUMhvu-ehoxkaOy)b#`|r|@AREzw&z+gKZNc#!_;c%0pX%B+{gG-ST!2#&*7TiS94i)gnCSt-(`0)O(kI@~&+xwR
zkf2Z?!aI3g%~TmSyi5SqWY#h&hp!=|c-QR7R|s!;cM_LL@GVc`-!|cu@dQfi@q&9(2^LCInT*S>s#ANg8XxtX4DOW4a&AYI`3`vM=)raA-7UZ!bxYn%X1W2S
z2qwu-XNGP{viQ_*tj758b)^R>XQR42Ja4wdX4@^r7LKWIYE4u$O-Ct%XxcEo8t-mq
zgD08(iHp5OzHY~()t`Nw3nuH%jLYR$i!u{osbV}=@MT+Xo$n0jott^A{y`5E{s}aQ
z&WQB1=fqUB`+#H@o=iuO1oz6CxxoX{{6*3-Gc|iB3{69;D}EoAU(P2U|BTBTszVN5
zy|6B9Get#dYhec~ahETjpz%NG53EGcN=
z)Nuqkz-)=kX4R|UX}1-2@LOz9P%8c_uI46=wuG@*GpEQtAXhJa#lG53K1qtAr3Svs
zAnW$b?A3fzDrSJ0JnT@Wtp!FDh>!r8t(6xEkNRjHqfrZlx5omAHj4d{x=oR;SR~dz
z#WXvN3lZmgvHXIpsgqn~3jl@`8W`|{n16zftAknz1E
zK}R?`yZ?~zx^mtm?FlB_h`*syCcEKg(MF;SguQF$HmUN9jssKWAA{UkB*(m
zo?J@*kWK+%k@W0CBNjjE6!8odh>N?t-t%(?%{tw)tUR%PPfN7+VOXD3$SL#}>&rts
zsq1SWi@dYnh*u32aYn5tTt`XoJpW3upwBd-ZZwr1;JwG9P=>z$;-VLTrSUp1Xq
zUCqAh{pf8$&ufqko?v7?4v+vHKGdTx`=B5_?NxZfw>o_AWH4v;`lsorsSuNI(W3a1
zOHqu}QSpLqrlRjLQH5w++j97=#MWcN3eo2lTm0!!On%&6Qzpe%R_)+gT6T!1S?66Z
z&~3#@2_z_>fO-?Zaz(e-=&6E#LYPT^wCHLkil}2#J|spDX-%wBcY`EK`JCu_Jv!`W
zS<*Bp+G^`taFQ|3VbH2J4I=+`+}GlX5A*zq&+Kc0x@GoUlg)AN(BgmNI?WC7(-Kq2
z-!Byt$UU+N$hFTd92jr<`j@aRfU_&)8V(D`=$&r?865zhABfeL)z(+le&EJ@S{jeUhnjx_Auiz0|JJys|BKWUAk9Ci-v4m$n)*<>
z$9NFD1i7orn^DCJ6XTB()@wB$*)T_K;^|`}I5e|ONZiXBT*DBgk9YQgdbINnIP0|^
z8s$aqS?Ebg8&%Y8kF3jNcg>l#silDxRmR5!0XA?+$laC|nv>1)hi~B&tp0>Y7p}a%
zjo$8aDP2c3M(^?BHL
zV=8W})MuOU-FHLXopTMGl&{Ap>_;s~>ZO_X-aRC&5Y8;YkIy&vMTMB2P4bS(@Z#2N
zVXFY463e}9QDiOlpv+7@FP>d7!aRA~=^eX?<1!$LclW0=dgg2A_wiVGfAUECrh%J$
z^3>omPD>Wb)L|gPGxeDj++{w)3vNDuEXZrI`h#j~BQ03;yp8f+QQ5^Bq`mYgL*S7o7k{MfRrE_@q@VN2m3BGZ%x%v
zwBy9ojP&>pwyyn{3JkdIQAceMA}r$fmRqk~QrZ@vJYt(%&JGpi`}MF-5t2Hd#b;Pk
zbuvA^J;R1po9rmMvMVB0%MSz(R;YvJi2!lD9benL8idYVmQ~YfkrOrDJ5z$?#(;z~
zfpCzoQ3B+zoY5{W4}nRzcYQVIn$e~e5yu@iC!a#BHzi0uT_HfJE(v>uHPzTLRbsl=
z*1&ot>@XGMx6#|mb!)G#>h4*#dd5A*_sB()GymwdV(0*0h<7Z)J8*DM%_-L&*JBQA
zL<7#?RQ)ruAfaOvi#mc)6kaFELT8xHK#`TaF@&X1iW_dj*>C2-&P$|Mq44
z6in}FGkwU^CzOpX2jsVbdRCf~yEQ6OFRp9oGNe9VCYm5J*W~73#?M9c;rH77B4H=`
z{XBUaZ%r@+?|u=NN|7lx9>fFcBNP`kC6vesOg!h4#PBL)!6eQ-+<0FZ>_I}>tHyN&9gfo1cSy0o^+6!0zU_|f*^l}!T$R|ItSVnB0{D*M17
z{Z&R%*oLgymk~mb^q)LeR&Esh);A8Fi
zf9kXg*{c;$0J4R4^o~vedh>-h_eoFTul?_J`yC;3-h#qt199jF<8N|h8sGgHX=Z6e#_JXSA=5|6xHesZ{
ze)91$EEN70s=MUO4mLpGM;=aJ)9KbTg-dZD=C>{Cw(PHouig@PUxso&A3>F{sLV<
z&reBR`xn>)E)Awx3yonaMvwA)cbd-Hh|`-kRZT}NeCa|Xer((M{S~Xw7?hb0%o?jm
z*8rtJO5Ayw
z0~2J3t-wJn^uSsO21_AxTj36?-IEno_7j9U3p)d*)cPz_J0_drz;n;XeeiJmxbV?}
zEr9Y>yTKGDzGWqlyl5XPy0Ncx#6c+()wxOL0l5%;@UW~Z82kMv{2{Af2s3tb(!7id
zHaiMkm`j1_)2<+Tfs1;bH-I%uaE~yN`}2|EcBZO)2$C_*7!#ss=_$v50_C)4>jUn@
z4w-XUe@9=)3D5#XZ2CaO!6wf>UEQMoCnXT~eSwIXZ;-Zmnb<2{f611Iq3vyHmmiEjOpw;LDF$_X*#x1t|5te8e+i@gpX;<+
zj*FcVK=IoQ?FMiG@=vKEbyIfmAVlDt`~L|F`KI-2=_$T5pO0WCW%QYGFe(P=77n*{Iu=5VA>io1uS4S-l4wqrbxx7LVYvY=l!@JMmF@M#DIIZ`e&x{D-eSYjpsiti4j0n=fH!6b34H4td>hA3|~n-wY+$Q#?%niC0~UfpiqWBQt*
zBt(&3(E#0Z&d!6
zUTFZ2vu*#d)AwwNU;5z32e`MQ)k_JZv3mC?pxkOFsPv8}E4gO-YYx>r&D~tiTc2Ng
z1+U?j3UyB^?!BkgD8nVefpL0zsJnTxY51T)i2JyKff^tfC>jHeTa1UZ{j2w!!)n%7
z6MzEV
zyMZ4`PsiI@+tNb=Vk94nh7foNdogH7KqRX)P1fG
zJ#|{v%s|LU7W%m7>7VFe>sin*3lLTCKrmwiQ2cl7R^m0mEnZYLi)H`3%*tvGKLb?*
z2iPO9>KSW35}$!GhbRzueq$=9&qLFF8p$F@#RJyd=6|(i)lS#f-Jsu|{SYsGI|FUS
zW>6#&)KScBUm(_umMqAVqfPJ$YgABGi`dUwGdryj8Ga@TZe?w)m!juNhRTTFTe~{v
zGT+m&YUII~@N{fny%iUd#;|eQlYgP1EUI0y4!PsWK^OT_^=>AFg!&RemcN2yKJbub
z@KQBvXx+2~I8!&fDXbYJ1(ceug(VIeD)bw)5#&S*13aw7X4~HdeEz0l5N3pt;hV(j
z54PPZ%4u_BshHjdK
z_h|{-s4S^D;>8Pkn#u>1O>WaOkQJN!fDaPhc^_2D3gNnVxk8wCF)L*0p9EIxkRZmm
z0PN<96&BY5h%j$kX2!d!ZZ-2;`W;IY%E4e&YJE5)oB!j@?$6wZge_90!D}K+pmos%
zwO{-K2Nu;=>v17rn?i3Eq$tc>I;xu6oHk{(EE#`X_(_s4Y$1%dGyd*V$X5GfJwa--
zB=6Cxd150<>?*`iJpjhei7{5IR(sen+xdv8Hart#bFQmfv{-F^
zWA$HbV7qFvxmL}V7FfB@a4tDUsIg4bN%d=E*jfl9G;LiTYc4hzomNwZ4Uj4jUpu5^
zQ5+{2Qu>b({wcP;{6%afDF|lauk~85x_^Z#EKfPDkCK%MkAzO}51m35O?tl4<5%Ni
zZ1bBworc$6S6UPN1hKeiy?SzxH-}Es^9kWec|NGeLS?4ge
z|7!&!hp(rP8B}7{1~5rr#)jC^cg6W!DlKF!P^&R(RJO7#Ie+z+D0`p}1{`R%A@jIc
zTi=$Y*Fa668L0%(mJ2Q6;?Wc_aHH-`$(vuIEY_{hBCY-((yXtmb9B{dZer!r1tD6A
zRL?!#YYw1RVF7}LsZR25%AmW7V7sw8;9V>kn%55G&}y<~f@qEEg}=%z$aa!Cg(1j~
z+i%iS?uit)J_t!JJ=JPUcFdWm(XYA*aZ0Xx3cWn8V<+bq$DENf5L0ao`8~5if2A7N
zE>Fu<8#H|PAiG%OT9&e~0>`7q_Rf-R4X1Dh3M}CBt2sJUU+D*^(*r7Tr_8$YN}Ng;
zp1JDXIV8p;)TQOJ-86D%wN88wZ94`JXVx2>dd}~11F4O1JZ6or#32lk^9cG8p?xK1
znGH9OWzGuYX4NW8uM~jn$Lzr>H|P3CyV=@)B%YE5jVpM6Y4;a69%1Q0ao+XnV74l<
zy@jyuLm5y~HDI&tOZ~xqC&v7@o&Wd5HIVuX~YtP1q}*Ktz3)a
zx^++JI?MJOnTE1=s7r;xt=5ZAMYlq8se*hB0N}|g=)n`VliJKcQtWwi?$pg5D=*4u
zz63ZesTFnagkq0_m)LJNVpT7=aS0ipDk15Gcr%=NGPlnp8GlGHzU@09oPvyVkvqhv9U-7sZBw
z6?N>?Cf2*@dm&}=6BzD{vAH~1Jw2oH{?oG1z;z)kyOVK*v!R5iQ{fxSdYp=amKvFy|m;3@Y!TZwz)L{E{dvqjUs9!cOv-ifIj#N8;w@HKUV6t4*MqC3vd`
zi!p&;dL_?az2XbVnVuWW`auu|QRoRsSFS=4E*w&iB6)vtW`cj10dUA!*a=B_AZ)=$wwT}l6=;1j480P@qI!-qYZE{d-!K|j
zPL;s_oKc{+XpkTVO}-)vf^(}c|Li6?5=8@rm%vXOFNl`|AODk9#~RBl`)9l5-&4OB
zG3o`D%V0xo0(u3OZ|w5xEQ7r371&mLG5UNMXaodkM{RgT|AQ%dO7ryo>5oVoz(@Yg
zuju4K8Ck6LRH^a=QuEAEer6_deo?c?)!pyMtH%1n9ZSKPjqM}z$btcFMe0^?N?ptt
zL(EOB^@U7_+WC3@=oJJ5nUC67Q=mXWEv4qeC*{|(?@Gdi-=xIk=sZkni6T=iuX
zdtpD>S{3d0rSDAI_(D*rvhZ2O0>UBT2d**+ujnOjcbV@v^;Q)-*%otS)F^FgD_5n)GyjiU*VTD(~hv_SK$#xw_>7hYSH6u*^-
z;^#b>a4z;6WvSWP9|_W+iQr{u*P=Mt&8KZ7V+M?b%dLgWeOrgqW?}>E6N|bcF%@4*
zAZz~{ONg*=`h>Nx?wpVir;?tN%{HFjhLVDA#F0G5gtlv2Q=+^#76an6#Y&+7M^NNr
z<;r^7YDxQ7y^A?v_{JPr(Ge*Q%!^smN@HmvR7RG~RuW>catgiN4KxQXM|)7?X#OQe
zrBk_rwUsv{7{KHf{9dco<=OhOz#lPl)&g$HVqdHr;Q2|0%*wJ9P_VpXw#=N0SG!R!
z-A~Gb-YYCv2FZTm7*Sf|qag{d^D=5(+jzb|qL}7sFsf~GTsN^!t2aggigI!mm^7#1
z*wqvtko80~(L95I$6dfCy*Z~NAlR>L{kFfie|p$x&Pr@Kvrmdu&zh|(l%>@`zNtJ@
zo3+;!nV{g#Xtv;aJ}PillE|tT?$n@04|238sA-$5Ee`t3O(io9ZXP0Yb|8z>0sbGc
zz`{xwlHibUWS-@Z`Bw@BBZvsCa`1pE{0wl5lR!=U>waWDnSEc@O=ZG;Z}26psw{X~|tIS>x1BT$qnMjsGh!}epx
zY=sV**jNUUk*wNHXb%PYv#^{taCG@!($>;ZwT4~5W$U4f!3`6exACIXs|ul%xVQaX
z&Guc*U_U67dLqqWpu!hkz}2M3@3Xa{!bnIiK(i*Mt2FG;(Ff
z2yVWshPJRhcd_*M!VMGTBTMPu3#*v>v0FWKQ#&_5cqEsoB|2@aHz)qlQj-sI3UBaz
zpU#!p5r5i2wy0BB<`K+77+ZXTSj#KXn$IioT-+2f0E=BI%X7(&Dtz>g89|=Eyc+-p
z+w1A7%=3ePKx;#Hg-4m$IL!~+>A69gq67aknc?)Bc8FVU>OsJ^`{m&$zkT%xg7$OS
ziw!LV#`rHn7XK9?(ogTFf>UcC+VKz>|81Gl00EOdk2Ul_Txq6hhfLmU>`T
zWtQ3}T>GtC9sE>GBEg=AX=|Yi3O}y-b#>-O4Ueb;LVROs;tL!Y;ODe|#w0G@yOa*F
zHz7$4y%lwAaK6<0=cW5+0(#|I&HW&Fu&HA7mR6GS`ug%r{_*Dr%0yPYK1-oadVAV5
zg*NfGiZ4A*?dW@c{nEKRn_N{m1Ww!9;&Zs(z271+H7ik-C;Q-`m5t-EuKw4L1LSpK
zt~%G^Qm&AG8h&cX_}DNIZgcd~=;$rdgVu$XsPQRePu@k|-Rhp6G65>0V5o@)%?$7#
z+OqjaOz>x5zq@bC=8x!!-z}_gdduE|?(U|luo8pQ(7AG};D?>X7ak`V$fEDyyi`}O
zbtjJrOQh%+$_f*f{Av;%voAt8<^B}`tF&$qesV@4Rj*#(_NnzqC294)3ALpYTj4exgF?nb)Rn
z+b|V{1XdXCVBw`>_u^7Tcp^;I!uk)R_i(b`__>cav$pTA52kEoCm4hey<3^NFrjf>
z_NiW(OwLc6B--lVd(rqX*z9Tzqab;Sj~o2xl5s8bLB3RLPp@iou2UBuj3?<&#_$mc
zady%lrJwQ&{C#lw`m#zcUXO@nVLo!!U6Cn_`D@IQ&0g9|s%R8C4J{}AZpB1dQsNv}
zKhEpkQs9>;Y#Pt@jEqYCLqBX=p)HnoE+aIn{R#(=4;yQ^!O{W%tdTc1I2UkmA~!-P
zIDkSt!BXIfn;;6Xc(|1fA|Q+Ej=-Z~CC{SWQDFLHMd^cH*>(c+3;*A@+X{Y*uKwnk
z8Qt&8%hcQi6iu-JM^!5+$&Kp;XgIJNKzH&{b4*2F8N&tbCBNGJv8SuMDLAmK&#&8(
z5dFj-jiy**5p#o3?8f(0Xk!*_;S^JuxkY`iAO9XCalO1)=NMS#H~EZ>k3cO>s(2eB
z3!1`#GzKJg%<-?Tdb*WOk}7?hP8Z58NofPlK(_DkEK=$lfZFA5_whAL^>1LFLmF-vzzqUvjAneeDl`Dic(gn5|kQ+r7
zQX+D7E+(tOK6-@&-i*i4wX7jz8Dr1d{{o!-J$)_Vi*)KuF2=M$ji=}sb-`=GE4Scu
zj3Ij09&n*PKKRBOwb+EB1@AfgQP}-Q8qKFm7~V4=C27_7cGS|AC6>f`an
z?3msB-o1F}rH)xFvTkPYOQKfEcf|fY$T93W>E&0ugNFy2eh;ur@J_$);lzfCRT<7n
z)y$@2^qGsOic9Da(m2!=JEkyRGhquS;K?x?h&>ngZ}07%)?J+ut(JUAUDh~}FuHkZ
zrfh2F0m!oYPPoMY^W%^>wm_>++d@Zn`%bXV!=ToA_I~Z}GZg;vnc>nI@Lv79zlgxY
zM~J)WnXR?AJV)jneKdE?i*Jai=ySsn)2qn5+{jh?97Cl@S?MHBB~L4!3dy+h**fB=
zM4s`Ib`{IUzHRycy2t?3WcwxH5^u0Lo%)C5z{Qp!=Pr3zf)-=ocrmLTwwc|Fx}3}C
ziyLvso%qz(yu>2nb=EEbD3e%UtPdIoUi&2u)FAPx@3$docd`yNTcueN7Q@A|QSw;b
z{^Y#!W;<5qL*Q;}hR(0%H4eK62$CTyk6c$Q5_$|-Cy~+#X
z`uYN5reBuJ)D;8irhWR_apA76BClj)Kfkz^P#6@nmdhFz$ZKCP`1lmvIxVM9_lnDz
z8z{Z20uSDK-IpI3mXHG%ZIoOF8aV>Xni21e{o>T&FLm)CR+*S`WKI5i+OdtZ+o
zqj_3`|Eya9LiKAa>XTI>KSkLEvF=~=i``z!6zATnZeRQ&||Kxkl
zM_bv0A2BXIfnK!$y{hT7tlHOVUl9<^kT*W~62mm4DNIXE!bFN)!Awbza{n1&wE1Av
z3^J@9kO$9T?&ZKB@}RIuwhF{AZuur((
z@!SjV8;Tlwd`UDcO00Gmgr$OR0*8SI5BcVISyR!^@6X@Yc&KmN`&Zo2zJ>F&LX3gi
zYur|Lj2dZMh}p2~UmyIzgPBe;bh+s7CBG=CEc}gcV$(Us_KbwclE2~{-zeUhsj-?R
z>$InR>7@m@wpAt7bT5j%*BOOJe1>xIVeBb(DlTqbPkeHG^$#4CaDbv#fz1g*F|yi!
zvSV^``V?RZgg0sh*e$`jn>2A+HsnK7uV8W2}JDUpbTgg`|5Wa5iZ~7
zHS4fVlyGWwizOXDb>7<|PwqF%Oni)+yaebr#t7Q3=>O5&m&ZfBzWq;Q?8+43970D$
z$#xP#W>TnRCmqVDjwso)#bDZqEG0|!P)JPK*BMz$GT9OngY4T_#tgHV=N`V_?{m)c
zeO|BUkKgio{Nv>_w-|IO%fJ}3EKp!B4Y-QcUZgNy4JqJMt
z4F$o^1&%uTi>ELHZcB*Wf_PNjw&WfN0Oa313nyNVT>RhhLQ(=`w_YR@$@yis-2qT(
z+xrpQ_Iw1ly`G2L9*_REx3k?$ux$I{nEyrpmJu-ac#<2M*O@{1rm0bygbF-Z>oe7P
zrn!17&1=y*6%gr|p{@+q3fjCzoh`(l7h8yjPsMEAA_{@5W?#iL6wFhNRn{U`#n~%<
z6}ajbMQ*oyk96*yI?^fW7EzH)Fk
zNLZjOJbx?u@RbLO5!jLvxBvc;gum?4csh2=Z6lIG-_#?PsG-O`%Kmk
z*oV~AvRqM!k2n%}v4=H(irSZ+!+3p^6d=dQFA0sH2CI)tV9`TE&g?nO6>O3YElbO^
z3pcCBDn@^=HeCDD>tyWW=sO<@BXFFy^i%U$zxhWpt1aDC&--K(t%#uqs1OBr$n@~R
zGJ@&Rrn>{G%!?xRL&lL=R?HBa!{eVV8R9D=FRirlsEWi;QS00oi(RnDImCCer>yxd
zZTgJ(Z%?xM3@zJ~L_ZjKWbUV_P+WWBHT6#H$$q{-_FuHWg-_wsBqKqDbFCXxr}K!K
z5p;;wnX>+w5;Dr7yu47<6wzOhdVgU|t3Ho{CVE#Xuy9riDoGVVB|de`PyS@BnK3Hp
zhgh)g0Rp&04q!+wGLQF^woTx4vz5|>!uN)iFJvAZi>g6Y%*+TlogRrvCs
zo93zQZG}v!U96*um~-<))*sUK&hb?oBLw=~MV{k@*6ZU4Q!g*8K01X#hP>UK;gBcr
zc|{FZ6Yp*;;g{BA5Wt2~M+Sw(2~IgU@2B4Dcj>W_`Ryo`=~C9qv3l*nQ8l6+4GqRS
zyPMDY!tZbegoU*F6U6hVrK=bu{#uBmTF{e<2d52g9}J$3hD%6zOQm@@uAARlRaiJ8
zb=M9tnK#QSW_d+YYqq!q>{8@o9%!3_Z1~>!`vR1bVL$ocnk%~$-aNdm0+(3oWPI4*
zsnn#z_&;gf^om@ySlbC}my_4-A12=n{bLBU^Mqu{V2~}q##ltHtIqR#;q~!vNPcZM
zjU_0520d>q*CKgI<-zq9*K(V|VWL$->R?;upQx5#KH*(h%Q$VnwVIm3GnCM5)D~6K
zpog?t0*H)v%N!Epd-63=)umZK2Oyc)yrcO3oVR6PW_E{P%WfrcLgTq1m6Gt!AR}A?8O5ClvT;K?;GO}P>AVz!#Hve8P|V@1N76k
z8K~9C_$f!&zm$w=$ntwFO8%TzA#)I})me^+`RQObYW|+&jJM#z=s!4tO)!*t&h`9n
zj5~dCmx5wUj|WkN7kU~R{^pdy@>xuS8sM<*;^FE0xTuT(Y7tme(0F3$VWxf0KO&a8Q16ypEg(m|Cze;K`VLlL-Hd9Xn{6<
znEqw^&0L&i1g$u<0WE1jn+c)aH9Qf5J=vGplH3LoCOl<&PR?U5z^Y-@f1s}Lg=!Jhx1%&>cC*D
zVbPeBSMgX~*CWnd(>)f_mYaQH{A}<)j-opSVW!T`1XPCudd;?eEVz5@N7o~3;_Dg5
zL-a0ZaJ~eH>968^53HOC&U2Ef1D~;V&%o^PsYsvJYAd&t*U5L@1!Vr%DoB5FS`Ktr
ze9S+)rKh{nlhqfqz7ymdgVehmck>9P@^R2a!-MeT5{tw)f{ox0NGph)ohA-0znS~$
zpHwJ`>)=o#m4xJc_P@x4|DX98X1dD{wkR4jl;senM9DK_zWCdd|Nq`ia$H`gLq~=~
zT|&BD&@r8Qmgc|!(Z9458}c-r)kkWg7@+1UpQcm0jB>DsnI>yaj(QxkeT&-r>eW1D
zGARAt9J%|Ugt|>0!H^WKmo`gmxXlTOdM7$I=6kGgdE)sNE()q$@_pajvYMphdgJ#sFb!;
zhNfN#_1ClyVcWZ;ZNJZJy5~of%vlQSTmZdyW`1R?@3z}@IpW}OX9X%?$FK7A8|)jdDy
zL%+SE1%Wg*kGmE?XMfDGBsjAo92)HAbtNRhE;JAoJ!re&jm?2j55ix)G|0#P8rq=
z7bu!b$71J$(-9Br1Ew?wxRbM|?{|skm>H6e()y-r3(RHdcW3>xlr7BNPO_OV@dF-i
zoXu=M5WSZARiaBi$0Lz(i!yZR5!7cdU-Q{8#r|U93p+i0L*Qz`*MEL1n!n*(yRHc`
zU4&Qjlan{}dVe04!OJ!BAnPqupdlb5vRmme~KTR52ZjSUdfT4UF&U?Cpz>f`0t?(LQzHY&kE)
z1#4C4A$2%ejI`l~&5Fz`E@%|wEN53}j*2bAf1A*v1P3mS-^2b8L03%UyOONX!FD&m
zlGc0b+2gCbYTxfS=ho(O}yA&@T1VC|l-V@4U829R{Kny~{)#
zT{+!Wpr@yFOq}niL+x=oZXQc%^xwxraI+`f{?Pd0b4zUrRv^?
zy{|NJ7sTwp-s$oO)@GaI7nwu#cYOf2Pi)VXM_(`Nu$G0NrbMMm6hbd&PX75@e^O~*
zcdcw{WrdOjA4JKY+NTmDdck17?{X*NP?VBO&2%lA3uC%X__8KVU7Dv+>kLVW?!}=R
z9B2z~3^QFu`+khv5x)lu7hQ-nmz~r&TP_1h4mFB=6_XtoSw3vlBF1?G90qAL>won}
zBpzf|JC0x)_@ARhB1Siw5{1*sCi?E1kKA~x6nJBQ;66x0u<>4F=#CrdNQkMa>{9YI
z=!db^mXBfa$_Fnctq8BT4&Gg{gM@7)9!Z2jJG3#7v^3<1TJsX)+Hp+sv8=;beu`Db
zi4~wq#*goStSZ_Z<%cEvLU(ALz%*QsILL}j)#&4g8Tq15prC4llExw_W&k@p_}8zg
zUBQ)TeM2!@<`f4~J@D}?mdBWQ=Wk)jCKQhRZ2UTzzP*dfJ2*H5lo
zkV&gImq2&%IT+N_8;ZFeFxjC`w!s99g>(mU4F}9E%xAI}81pnXjlENp*j!O?U8-%c
z^~1+UtKyj^4ssCHP|KEQ$gn@;;bHM2d{Rw)bH??lzTLLmiy`zsO4el#P|xjiwSF(4
zU-vtF0X4@QvFhi8bYxn;KLB_9#t$1A2mMWEV|Go8^=MYQAM}{amzEb&NK+S8U^j?&
zqAoZnLR3+Io#Bbg^5EKVbWKG`O5KZ`h?ndFeYTeA3LRNDX@0q_yFGfm912~6jd+{K!&s9->v^PMf_qBDbf)pD6X>R-n{}A*Dz-6OFG_EY+WXVa?YCp
z&wNFFeEn60OiOqBE%IGu2i&u|8xY5k+{l9%NU5nTG9GkZE(FnV->XGcMsghafTAFi
z<$=?+{Lb#_r^OQ!TQvGuW0wltjJm5I*~eZqUILefbl^FB)55j%ZIvpF5np6-t3Cqd{1nFbGi0q5zdG=J+zKzPk{4&%eRoXh$Y`&
z*Px_8Gr0V3n!*m4vsaEmR1uuTalC^FW%&;zCBU;X`FL?mN6!y>w`9$Slu6WDY|QO`
z(17>u8TeACGwIOju;<|b%)W
z1jU512_*T-eSPJf<)Zz*qutuAfDl4|NIE)M;_1=^Z)4c+
zn1%qr%aFVV#I(OKJ}~sP0P!Yx3ES&X%x7D%AWfHL*eY*Yv!squ(h=qmo1QdYkrU~9
zxOk4U&HqIcPgFk)XNJ>ch0lLh!L^H_$YN7~o&5u2ye!n=vwN4DpcrfTs0}6uq!w&M
z%RbaWK=We>Y%6H9$Ior0`Of`4Y!tzs>#FAEDY~Hgrs{Q7g=@O&g)2G`RT<9eWZ^^1
zrfH$fE2Mr%OerA?DZBTKkhVuEKdg0XrItjcr`kfKWB;)ru23%@jmpY+&3C4n?(R28
zA+%b#s|~}#Y`yLuTurx!O1eRo@DztHl%%8WGq1yb1qi%T>$$3EYSa$O-ln-z6kxGEpNWih8YjkVXu}3kP=a>
zU~?oib678MzdcNd5u1@O-r`kx7BT&^;NGSzJYugXT`s*=tiL67DFfCmoy8$397DFDj7F-YCT*Lo_^Ys?0VH&EV2vm3TI=#4>$3H!%
zuzoQQcCe`#g|t&XWEiQ#(jG
z@IU2Gx>A+BF=#uG)Ys3whp{FIv&@{x4Dyu)ajtYMV;FsYuhyH{^pL&SVI{~
zB$X!yu60fgU{)NBaut1D4u8s5`Q-Wv)`74|jjs)_TcHQo?p3fS{kVI_#Qu{j4=0ty
z+5i3Ia?GiR8(!33L^<1jq;E?@S&5d89>{_1+B=SRKuB1Z#o8s)i0*rQ_$Z)dFxHS8
z8r7dvqdBuNRjPQrQ%?1;S}0QO<;dDZ!uWBZ<+n^Ok8$*#kL>Rx_G#*bILavs>n}(F
zwJQKrEKtoNF9
z?S#Z{>CctivAvjCDd=*2Z-u@u`{4+YkPtniku7#%wvmW0>QJ~yJkvvV0h
zXVbLVhWvQR3Q�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
Gp#K1n>B}hq

literal 0
HcmV?d00001


From c82c9649383ae320bcaf789270f0445071c33c1c Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Tue, 17 Mar 2020 12:01:22 -0300
Subject: [PATCH 5/9] updated idea specs

---
 docs/scarpet/resources/editors/idea/1.txt     |  7 ++++
 docs/scarpet/resources/editors/idea/2.txt     | 12 ++++++-
 docs/scarpet/resources/editors/idea/4.txt     |  1 +
 .../scarpet/resources/editors/npp/scarpet.xml | 33 +++++++++++++++----
 4 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/docs/scarpet/resources/editors/idea/1.txt b/docs/scarpet/resources/editors/idea/1.txt
index 46b6a28b..caf38e5c 100644
--- a/docs/scarpet/resources/editors/idea/1.txt
+++ b/docs/scarpet/resources/editors/idea/1.txt
@@ -30,7 +30,9 @@ floor
 for
 get
 has
+hash_code
 if
+import
 join
 keys
 l
@@ -49,6 +51,7 @@ not
 number
 outer
 pairs
+perlin
 print
 profile_expr
 put
@@ -63,12 +66,16 @@ return
 round
 sec
 sech
+simplex
 sin
 sinh
 sleep
 slice
 sort
 sort_key
+synchronize
+system_variable_get
+system_variable_set
 split
 sqrt
 str
diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt
index a0e2ee1b..2167ebad 100644
--- a/docs/scarpet/resources/editors/idea/2.txt
+++ b/docs/scarpet/resources/editors/idea/2.txt
@@ -9,6 +9,7 @@ block_sound
 block_tick
 blocks_daylight
 blocks_movement
+brightness
 chunk_tickets
 create_marker
 current_dimension
@@ -28,6 +29,7 @@ generation_status
 hardness
 harvest
 in_dimension
+in_slime_chunk
 inventory_find
 inventory_get
 inventory_remove
@@ -52,6 +54,7 @@ particle_rect
 place_item
 player
 plop
+poi
 pos
 pos_offset
 power
@@ -60,13 +63,17 @@ query
 random_tick
 rect
 remove_all_markers
+reset_chunk
 run
 save
 scan
 schedule
 see_sky
+seed
 set
 set_biome
+set_poi
+set_structure
 sky_light
 solid
 sound
@@ -74,10 +81,13 @@ spawn
 stack_limit
 statistic
 store_app_data
+structures
+structure_references
 suffocates
 tick_time
 ticks_randomly
 top
 transparent
 update
-volume
\ No newline at end of file
+volume
+without_updates
\ No newline at end of file
diff --git a/docs/scarpet/resources/editors/idea/4.txt b/docs/scarpet/resources/editors/idea/4.txt
index 4ffdeabe..6c37a65a 100644
--- a/docs/scarpet/resources/editors/idea/4.txt
+++ b/docs/scarpet/resources/editors/idea/4.txt
@@ -1,5 +1,6 @@
 __command
 __config
+__on_chunk_generated
 __on_close
 __on_player_attacks_entity
 __on_player_breaks_block
diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml
index e77cbbf0..531e245f 100644
--- a/docs/scarpet/resources/editors/npp/scarpet.xml
+++ b/docs/scarpet/resources/editors/npp/scarpet.xml
@@ -76,13 +76,32 @@
             
                 __command
                 __config
-                __on_player_jumps __on_player_deploys_elytra __on_player_wakes_up __on_player_rides __on_player_uses_item
-                __on_player_clicks_block __on_player_right_clicks_block __on_player_breaks_block
-                __on_player_interacts_with_entity __on_player_attacks_entity
-                __on_player_starts_sneaking __on_player_stops_sneaking __on_player_starts_sprinting __on_player_stops_sprinting
-                __on_player_releases_item __on_player_finishes_using_item
-                __on_player_drops_item __on_player_drops_stack
-                __on_tick __on_tick_ender __on_tick_nether
+                __on_chunk_generated
+                __on_close
+                __on_player_attacks_entity
+                __on_player_breaks_block
+                __on_player_clicks_block
+                __on_player_deploys_elytra
+                __on_player_drops_item
+                __on_player_drops_stack
+                __on_player_finishes_using_item
+                __on_player_interacts_with_block
+                __on_player_interacts_with_entity
+                __on_player_jumps
+                __on_player_places_block
+                __on_player_releases_item
+                __on_player_rides
+                __on_player_right_clicks_block
+                __on_player_starts_sneaking
+                __on_player_starts_sprinting
+                __on_player_stops_sneaking
+                __on_player_stops_sprinting
+                __on_player_uses_item
+                __on_player_wakes_up
+                __on_statistic
+                __on_tick
+                __on_tick_ender
+                __on_tick_nether
             
             $
             00' 01\ 02' 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23

From fdb1b5383415aa67844af15a95311d68a998ed64 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Tue, 17 Mar 2020 12:25:54 -0300
Subject: [PATCH 6/9] documentation head

---
 docs/scarpet/Documentation.md | 39 +++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 docs/scarpet/Documentation.md

diff --git a/docs/scarpet/Documentation.md b/docs/scarpet/Documentation.md
new file mode 100644
index 00000000..4e5305a4
--- /dev/null
+++ b/docs/scarpet/Documentation.md
@@ -0,0 +1,39 @@
+#API Reference
+
+## Language Specification
+
+[Overview](/docs/scarpet/language/Overview.md)
+
+[Variables and Constants](/docs/scarpet/language/VariablesAndConstants.md)
+
+[Operators](/docs/scarpet/language/Operators.md)
+
+[Mathematical Functions](/docs/scarpet/language/Math.md)
+
+[System Functions](/docs/scarpet/language/SystemFunctions.md)
+
+[Loops and Higher Order Functions](/docs/scarpet/language/LoopsAndHigherOrderFunctions.md)
+
+[User Defined Functions and Control Flow](/docs/scarpet/language/FunctionsAndControlFlow.md)
+
+[Container Types](/docs/scarpet/language/Containers.md)
+
+## Minecraft API
+
+[Overview](/docs/scarpet/api/Overview.md)
+
+[Blocks and World Access](/docs/scarpet/api/BlocksAndWorldAccess.md)
+
+[Block Iterations](/docs/scarpet/api/BlockIterations.md)
+
+[Entities](/docs/scarpet/api/Entities.md)
+
+[Inventories](/docs/scarpet/api/Inventories.md)
+
+[Events](/docs/scarpet/api/Events.md)
+
+[Auxiliary Functions](/docs/scarpet/api/Auxiliary.md)
+
+[`/script` Command](/docs/scarpet/api/ScriptCommand.md)
+
+

From 14a573822c14af2898939fc7a1885f3d559fd0a9 Mon Sep 17 00:00:00 2001
From: gnembon 
Date: Wed, 18 Mar 2020 00:41:29 -0300
Subject: [PATCH 7/9] added one page doc

---
 docs/scarpet/Documentation.md |    3 +-
 docs/scarpet/Full.md          | 3150 +++++++++++++++++++++++++++++++++
 mergedoc.bat                  |    2 +
 3 files changed, 3154 insertions(+), 1 deletion(-)
 create mode 100644 docs/scarpet/Full.md
 create mode 100644 mergedoc.bat

diff --git a/docs/scarpet/Documentation.md b/docs/scarpet/Documentation.md
index 4e5305a4..fcc8dc42 100644
--- a/docs/scarpet/Documentation.md
+++ b/docs/scarpet/Documentation.md
@@ -1,4 +1,4 @@
-#API Reference
+# API Reference
 
 ## Language Specification
 
@@ -36,4 +36,5 @@
 
 [`/script` Command](/docs/scarpet/api/ScriptCommand.md)
 
+## [One Page](/docs/scarpet/Full.md)
 
diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md
new file mode 100644
index 00000000..478888a7
--- /dev/null
+++ b/docs/scarpet/Full.md
@@ -0,0 +1,3150 @@
+# Fundamental components of `scarpet` programming language (towards version 1.7).
+
+Scarpet (a.k.a. Carpet Script, or Script for Carpet) is a programming language 
+designed to provide the ability to write custom programs to run within Minecraft 
+and interact with the world.
+
+The project was initially built based on the EvalEx project, however it now diverged 
+so far away from the original implementation, it would be hard to tell it without 
+this mention. EvalEx is a handy expression evaluator for Java, that allows to evaluate 
+simple mathematical and boolean expressions. For more information, 
+see: [EvalEx GitHub repository](https://github.com/uklimaschewski/EvalEx)
+
+This specification is divided into two sections: this one is agnostic to any 
+Minecraft related features and could function on its own, and CarpetExpression 
+for Minecraft specific routines and world manipulation functions.
+
+# Synopsis
+
+
+script run print('Hello World!')
+
+ +or an OVERLY complex example: + +
+/script run
+    block_check(x1, y1, z1, x2, y2, z2, block_to_check) ->
+    (
+        l(minx, maxx) = sort(l(x1, x2));
+        l(miny, maxy) = sort(l(y1, y2));
+        l(minz, maxz) = sort(l(z1, z2));
+        'Need to compute the size of the area of course';
+        'Cause this language doesn\'t support comments in the command mode';
+        xsize = maxx - minx + 1;
+        ysize = maxy - miny + 1;
+        zsize = maxz - minz + 1;
+        total_count = 0;
+        loop(xsize,
+            xx = minx + _ ;
+            loop(ysize,
+                yy = miny + _ ;
+                loop(zsize,
+                    zz = minz + _ ;
+                    if ( block(xx,yy,zz) == block_to_check,
+                        total_count += ceil(rand(1))
+                    )
+                )
+            )
+        );
+        total_count
+    );
+    check_area_around_closest_player_for_block(block_to_check) ->
+    (
+        closest_player = player();
+        l(posx, posy, posz) = query(closest_player, 'pos');
+        total_count = block_check( posx-8,1,posz-8, posx+8,17,posz+8, block_to_check);
+        print('There is '+total_count+' of '+block_to_check+' around you')
+    )
+/script invoke check_area_around_closest_player_for_block 'diamond_ore'
+
+ +or simply + +
+/script run print('There is'+for(rect(x,9,z,8,8,8), _ == 'diamond_ore')+' diamond ore around you')
+
+ +It definitely pays to check what higher level `scarpet` functions have to offer. + +# Programs + +You can think of an program like a mathematical expression, like `"2.4*sin(45)/(2-4)"` or `"sin(y)>0 & max(z, 3)>3"`. +Writing a program, is like writing a `2+3`, just a bit longer. + +## Basic language components + +Programs consist of constants, like `2`, `3.14`, `pi`, or `'foo'`, operators like `+`, `/`, `->`, variables which you +can define, like `foo` or special ones that will be defined for you, like `_x`, or `_` , which I specific to a each +built in function, and functions with name, and arguments in the form of `f(a,b,c)`, where `f` is the function name, +and `a, b, c` are the arguments which can be any other expression. And that's all the parts of the language, so all +in all - sounds quite simple. + +## Code flow + +Like any other proper programming language, `scarpet` needs brackets, basically to identify where stuff begins and +where it ends. In the languages that uses much more complicated constructs, like Java, they tend to use all sort of +them, round ones to indicate function calls, curly to indicate section of code, square to access lists, pointy for +generic types etc... I mean - there is no etc, cause they have exhausted all the bracket options... + +`Scarpet` is different, since it runs everything based on functions (although its not per se a functional +language like lisp) only needs the round brackets for everything, and it is up to the programmer to organize +its code so its readable, as adding more brackets does not have any effect on the performance of the programs +as they are compiled before they are executed. Look at the following example usage of `if()` function: + +
+if(x<y+6,set(x,8+y,z,'air');plop(x,top('surface',x,z),z,'birch'),sin(query(player(),'yaw'))>0.5,plop(0,0,0,'boulder'),particle('fire',x,y,z))
+
+ +Would you prefer to read + +
+if(   x<y+6,
+           set(x,8+y,z,'air');
+           plop(x,top('surface',x,z),z,'birch'),
+      sin(query(player(),'yaw'))>0.5,
+           plop(0,0,0,'boulder'),
+      particle('fire',x,y,z)
+)
+
+ +Or rather: + +
+if
+(
+    x<y+6,
+    (
+        set(x,8+y,z,'air');
+        plop(x,top('surface',x,z),z,'birch')
+    ),
+    sin(query(player(),'yaw'))>0.5,
+    (
+        plop(0,0,0,'boulder')
+    ),
+    particle('fire',x,y,z)
+)
+
+ +Whichever style you prefer it doesn't matter. It typically depends on the situation and the complexity of the +subcomponents. No matter how many whitespaces and extra brackets you add - the code will evaluate to exactly the +same expression, and will run exactly the same, so make sure your programs are nice and clean so others don't +have problems with them + +## Functions and scoping + +Users can define functions in the form `fun(args....) -> expression` and they are compiled and saved for further +execution in this but also subsequent calls of /script command. Functions can also be assigned to variables, +passed as arguments, called with `call` function, but in most cases you would want to call them directly by +name, in the form of `fun(args...)`. This means that once defined functions are saved with the world for +further use. For variables, there are two types of them, global - which are shared anywhere in the code, +and those are all which name starts with 'global_', and local variables which is everything else and those +are only visible inside each function. This also means that all the parameters in functions are +passed 'by value', not 'by reference'. + +## Outer variables + +Functions can still 'borrow' variables from the outer scope, by adding them to the function signature wrapped +around built-in function `outer`. It adds the specified value to the function call stack so they behave exactly +like capturing lambdas in Java, but unlike java captured variables don't need to be final. Scarpet will just +attach their new values at the time of the function definition, even if they change later. Most value will be +copied, but mutable values, like maps or lists, allow to keep the 'state' with the function, allowing them to +have memory and act like objects so to speak. . Check `outer(var)` for details. + +## Code delivery, line indicators + +Note that this should only apply to pasting your code to execute with commandblock. Scarpet recommends placing +your code in apps (files with `.sc` extension that can be placed inside "/scripts" folder in the world files and +loaded as a scarpet app with command `/script load [app_name]`. Scarpet apps loaded from disk should only +contain code, no need to start with "/script run" prefix + +The following is the code that could be provided in a `foo.sc` app file located in world `/scripts` folder + +
+run_program() -> (
+  loop( 10,
+    // looping 10 times
+    // comments are allowed in scripts located in world files
+    // since we can tell where that line ends
+    foo = floor(rand(10));
+    check_not_zero(foo);
+    print(_+' - foo: '+foo);
+    print('  reciprocal: '+  _/foo )
+  )
+);
+check_not_zero(foo) -> (
+  if (foo==0, foo = 1)
+)
+
+ +Which we then call in-game with: + +
+/script load foo
+/script in foo invoke run_program
+
+ +However the following code can also be input as a command, or in a command block. + +Since the maximum command that can be input to the chat is limited in length, you will be probably inserting your +programs by pasting them to command blocks or reading from world files, however pasting to command blocks will +remove some whitespaces and squish your newlines making the code not readable. If you are pasting a program that +is perfect and will never cause an error, I salute you, but for the most part it is quite likely that your program +might break, either at compile time, when its initially analyzed, or at execute time, when you suddenly attempt to +divide something by zero. In these cases you would want to get a meaningful error message, but for that you would +need to indicate for the compiler where did you put these new lines, since command block would squish them. For that, +place at the beginning of the line to let the compiler know where are you. This makes so that `$` is the only +character that is illegal in programs, since it will be replaced with new lines. As far as I know, `$` is not +used anywhere inside Minecraft identifiers, so this shouldn't hinder the abilities of your programs. + +Consider the following program executed as command block command: + +
+/script run
+run_program() -> (
+  loop( 10,
+    foo = floor(rand(_));
+    check_not_zero(foo);
+    print(_+' - foo: '+foo);
+    print('  reciprocal: '+  _/foo )
+  )
+);
+check_not_zero(foo) -> (
+   if (foo==0, foo = 1)
+)
+
+ +Lets say that the intention was to check if the bar is zero and prevent division by zero in print, but because +the `foo` is passed as a variable, it never changes the original foo value. Because of the inevitable division +by zero, we get the following message: + +
+Your math is wrong, Incorrect number format for NaN at pos 98
+run_program() -> ( loop( 10, foo = floor(rand(_)); check_not_zero(foo); print(_+' - foo: '+foo);
+HERE>> print(' reciprocal: '+ _/foo ) ));check_not_zero(foo) -> ( if (foo==0, foo = 1))
+
+ +As we can see, we got our problem where the result of the mathematical operation was not a number +(infinity, so not a number), however by pasting our program into the command made it squish the newlines so +while it is clear where the error happened and we still can track the error down, the position of the error (98) +is not very helpful and wouldn't be useful if the program gets significantly longer. To combat this issue we can +precede every line of the script with dollar signs `$`: + +
+/script run
+$run_program() -> (
+$  loop( 10,
+$    foo = floor(rand(_));
+$    check_not_zero(foo);
+$    print(_+' - foo: '+foo);
+$    print('  reciprocal: '+  _/foo )
+$  )
+$);
+$check_not_zero(foo) -> (
+$   if (foo==0, foo = 1)
+$)
+
+ +Then we get the following error message + +
+Your math is wrong, Incorrect number format for NaN at line 7, pos 2
+  print(_+' - foo: '+foo);
+   HERE>> print(' reciprocal: '+ _/foo )
+  )
+
+ +As we can note not only we get much more concise snippet, but also information about the line number and position, +so means its way easier to locate the potential problems problem + +Obviously that's not the way we intended this program to work. To get it `foo` modified via a function call, +we would either return it as a result and assign it to the new variable: + +
+foo = check_not_zero(foo);
+...
+check_not_zero(foo) -> if(foo == 0, 1, foo)
+
+ +.. or convert it to a global variable, which in this case passing as an argument is not required + +
+global_foo = floor(rand(10));
+check_foo_not_zero();
+...
+check_foo_not_zero() -> if(global_foo == 0, global_foo = 1)
+
# Variables and Constants + +`scarpet` provides a number of constants that can be used literally in scripts + +* `null`: nothing, zilch, not even false +* `true`: pure true, or just 1 (one) +* `false`: false truth, or true falsth, 0 (zero) actually +* `pi`: for the fans of perimeters, its a perimeter of an apple pi of diameter 1\. About 3.14 +* `euler`: clever guy. Derivative of its exponent is goto 1\. About 2.72 + +Apart from that, there is a bunch of system variables, that start with `_` that are set by `scarpet` built-ins, +like `_`, typically each consecutive value in loops, `_i` indicating iteration, or `_a` like an accumulator +for `reduce` function. Certain calls to Minecraft specific calls would also set `_x`, `_y`, `_z`, indicating +block positions. All variables starting with `_` are read-only, and cannot be declared and modified in client code. + +## Literals + +`scarpet` accepts numeric and string liters constants. Numbers look like `1, 2.5, -3e-7, 0xff,` and are internally +represented as Java's `double` but `scarpet` will try to trim trailing zeros as much as possible so if you need to +use them as intergers, you can. Strings using single quoting, for multiple reasons, but primarily to allow for +easier use of strings inside doubly quoted command arguments (when passing a script as a parameter of `/script fill` +for example, or when typing in jsons inside scarpet to feed back into a `/data merge` command for example. +Strings also use backslashes `\` for quoting special characters, in both plain strings and regular expressions + +
+'foo'
+print('This doesn\'t work')
+nbt ~ '\\.foo'   // matching '.' as a '.', not 'any character match'
+
+# Operators + +There is a number of operators you can use inside the expressions. Those could be considered generic type operators +that apply to most data types. They also follow standard operator precedence, i.e. `2+2*2` is understood +as `2+(2*2)`, not `(2+2)*2`, otherwise they are applied from left to right, i.e. `2+4-3` is interpreted +as `(2+4)-3`, which in case of numbers doesn't matter, but since `scarpet` allows for mixing all value types +the associativity would matter, and may lead to unintended effects: + +Important operator is function definition `->` operator. It will be covered +in [User Defined Functions and Program Control Flow](docs/scarpet/language/FunctionsAndControlFlow.md) + +
+'123'+4-2 => ('123'+4)-2 => '1234'-2 => '134'
+'123'+(4-2) => '123'+2 => '1232'
+3*'foo' => 'foofoofoo'
+1357-5 => 1352
+1357-'5' => 137
+3*'foo'-'o' => 'fff'
+l(1,3,5)+7 => l(8,10,12)
+
+ +As you can see, values can behave differently when mixed with other types in the same expression. +In case values are of the same types, the result tends to be obvious, but `Scarpet` tries to make sense of whatever +it has to deal with + +## Operator Precedence + +Here is the complete list of operators in `scarpet` including control flow operators. Note, that commas and brackets +are not technically operators, but part of the language, even if they look like them: + +* Match, Get `~ :` +* Unary `+ - !` +* Exponent `^` +* Multiplication `* / %` +* Addition `+ -` +* Comparison `== != > >= <= <` +* Logical And`&&` +* Logical Or `||` +* Assignment `= += <>` +* Definition `->` +* Next statement`;` +* Comma `,` +* Bracket `( )` + +### `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 straightforward and immediate, and +the source object should behave like a container and support full container API, +meaning `get(...)`, `put(...)`, `delete(...)`, and `has(...)` functions + +For certain operators and functions (get, put, delete, has, =, +=) objects can use `:` annotated fields as l-values, +meaning construct like `foo:0 = 5`, would act like `put(foo, 0, 5)`, rather than `get(foo, 0) = 5`, +which would result in an error. + +TODO: add more information about l-value behaviour. + +### `Matching Operator ~` + +This operator should be understood as 'matches', 'contains', 'is_in', or 'find me some stuff about something else. +For strings it matches the right operand as a regular expression to the left, returning the first match. +This can be used to extract information from unparsed nbt's in a more convoluted way (use `get(...)` for +more appropriate way of doing it). For lists it checks if an element is in the list, and returns the +index of that element, or `null` if no such element was found, especially that the use of `first(...)` +function will not return the index. Currently it doesn't have any special behaviour for numbers - it checks for +existence of characters in string representation of the left operand with respect of the regular expression on +the right hand side. + +In Minecraft API portion `entity ~ feature` is a shortcode for `query(entity,feature)` for queries that do not take +any extra arguments. + +
+l(1,2,3) ~ 2  => 1
+l(1,2,3) ~ 4  => null
+'foobar' ~ '.b'  => 'ob'
+player('*') ~ 'gnembon'  // null unless player gnembon is logged in (better to use player('gnembon') instead
+p ~ 'sneaking' // if p is an entity returns whether p is sneaking
+
+ +Or a longer example of an ineffective way to searching for a squid + +
+entities = entities_area('all',x,y,z,100,10,100);
+sid = entities ~ 'Squid';
+if(sid != null, run('execute as '+query(get(entities,sid),'id')+' run say I am here '+query(get(entities,sid),'pos') ) )
+
+ +Or an example to find if a player has specific enchantment on a held axe (either hand) and get its level +(not using proper NBTs query support via `get(...)`): + +
+global_get_enchantment(p, ench) -> (
+$   for(l('main','offhand'),
+$      holds = query(p, 'holds', _);
+$      if( holds,
+$         l(what, count, nbt) = holds;
+$         if( what ~ '_axe' && nbt ~ ench,
+$            lvl = max(lvl, number(nbt ~ '(?<=lvl:)\\d') )
+$         )
+$      )
+$   );
+$   lvl
+$);
+/script run global_get_enchantment(players(), 'sharpness')
+
+ +### `Basic Arithmetic Operators + - * /` + +Allows to add the results of two expressions. If the operands resolve to numbers, the result is arithmetic operation. +In case of strings, adding or subtracting from a string results in string concatenation and removal of substrings +from that string. Multiplication of strings and numbers results in repeating the string N times and division results +in taking the first k'th part of the string, so that `str*n/n ~ str` In case first operand is a list, either it +results in a new list with all elements modified one by one with the other operand, or if the operand is a list +with the same number of items - element-wise addition/subtraction + +Examples: + +
+2+3 => 5
+'foo'+3+2 => 'foo32'
+'foo'+(3+2) => 'foo5'
+3+2+'bar' => '5bar'
+'foo'*3 => 'foofoofoo'
+'foofoofoo' / 3 => 'foo'
+'foofoofoo'-'o' => 'fff'
+l(1,2,3)+1  => l(2,3,4)
+b = l(100,63,100); b+l(10,0,10)  => l(110,63,110)
+
+ +### `Just Operators % ^` + +The modulo and exponent (power) operators work only if both operands are numbers + +
pi^pi%euler  => 1.124....
+-9 % 4  => -1
+9 % -4  => 0 ¯\_(ツ)_/¯ Java
+-3 ^ 2  => 9
+-3 ^ pi => // Error
+
+ +### `Comparison Operators == != < > <= >=` + +Allows to compare the results of two expressions. For numbers it is considers arithmetic order of numbers, for +strings - lexicographical, nulls are always 'less' than everything else, and lists check their elements - +if the sizes are different, the size matters, otherwise, pairwise comparisons for each elements are performed. +The same order rules than with all these operators are used with the default sortographical order as used by `sort` +function. All of these are true: + +
+null == null
+null != false
+0 == false
+1 == true
+null < 0
+null < -1000
+1000 < 'a'
+'bar' < 'foo'
+3 == 3.0
+
+ +### `Logical Operators && ||` + +These operator compute respective boolean operation on the operands. What it important is that if calculating of the +second operand is not necessary, it won't be evaluated, which means one can use them as conditional statements. In +case of success returns first positive operand (`||`) or last one (`&&`). + +
+true || false  => 1
+null || false => 0
+null != false || run('kill gnembon')  => 1 // gnembon survives
+null != false && run('kill gnembon')  => 0 // when cheats not allowed
+null != false && run('kill gnembon')  => 1 // gnembon dies, cheats allowed
+
+ +### `Assignment Operators = <> +=` + +A set of assignment operators. All require bounded variable on the LHS, `<>` requires bounded arguments on the +right hand side as well (bounded, meaning being variables). Additionally they can also handle list constructors +with all bounded variables, and work then as list assignment operators. When `+=` is used on a list, it extends +that list of that element, and returns the list (old == new). `scarpet` doesn't support currently removal of items. +Removal of items can be obtaine via `filter` command, and reassigning it fo the same variable. Both operations would +require rewriting of the array anyways. + +
+a = 5  => a == 5
+l(a,b,c) = l(3,4,5) => a==3, b==4, c==5
+l(minx,maxx) = sort(xi,xj);  // minx assumes min(xi, xj) and maxx, max(xi, xj)
+l(a,b,c,d,e,f) = l(range(6)); l(a,b,c) <> l(d,e,f); l(a,b,c,d,e,f)  => [3,4,5,0,1,2]
+a = l(1,2,3); a += 4  => [1,2,3,4]
+a = l(1,2,3,4); a = filter(a,_!=2)  => [1,3,4]
+
+ +### `Unary Operators - +` + +Require a number, flips the sign. One way to assert it's a number is by crashing the script. gg. + +
+-4  => -4
++4  => 4
++'4'  // Error message
+
+ +### `Negation Operator !` + +flips boolean condition of the expression. Equivalent of `bool(expr)==false` + +
+!true  => 0
+!false  => 1
+!null  => 1
+!5  => 0
+!l() => 1
+!l(null) => 0
+
+# Arithmetic operations + +## Basic Arithmetic Functions + +There is bunch of them - they require a number and spit out a number, doing what you would expect them to do. + +### `fact(n)` + +Factorial of a number, a.k.a `n!`, just not in `scarpet`. Gets big... quick... + +### `sqrt(n)` + +Square root. For other fancy roots, use `^`, math and yo noggin. Imagine square roots on a tree... + +### `abs(n)` + +Absolut value. + +### `round(n)` + +Closest integer value. Did you know the earth is also round? + +### `floor(n)` + +Highest integer that is still no larger then `n`. Insert a floor pun here. + +### `ceil(n)` + +First lucky integer that is not smalller than `n`. As you would expect, ceiling is typically right above the floor. + +### `ln(n)` + +Natural logarithm of `n`. Naturally. + +### `ln1p(n)` + +Natural logarithm of `n+1`. Very optimistic. + +### `log10(n)` + +Decimal logarithm of `n`. Its ceiling is the length of its floor. + +### `log(n)` + +Binary logarithm of `n`. Finally, a proper one, not like the previous 11. + +### `log1p(n)` + +Binary logarithm of `n+1`. Also always positive. + +### `mandelbrot(a, b, limit)` + +Computes the value of the mandelbrot set, for set `a` and `b` spot. Spot the beetle. Why not. + +### `min(arg, ...), min(list), max(arg, ...), max(list)` + +Compute minimum or maximum of supplied arguments assuming default sorthoraphical order. +In case you are missing `argmax`, just use `a ~ max(a)`, little less efficient, but still fun. + +Interesting bit - `min` and `max` don't remove variable associations from arguments, which means can be used as +LHS of assignments (obvious case), or argument spec in function definitions (far less obvious). + +
+a = 1; b = 2; min(a,b) = 3; l(a,b)  => [3, 2]
+a = 1; b = 2; fun(x, min(a,b)) -> l(a,b); fun(3,5)  => [5, 0]
+
+ +Absolutely no idea, how the latter might be useful in practice. But since it compiles, can ship it. + +### `relu(n)` + +Linear rectifier of `n`. 0 below 0, n above. Why not. `max(0,n)` with less moral repercussions. + +## Trigonometric / Geometric Functions + +### `sin(x)` + +### `cos(x)` + +### `tan(x)` + +### `asin(x)` + +### `acos(x)` + +### `atan(x)` + +### `atan2(x,y)` + +### `sinh(x)` + +### `cosh(x)` + +### `tanh(x)` + +### `sec(x)` + +### `csc(x)` + +### `sech(x)` + +### `csch(x)` + +### `cot(x)` + +### `acot(x)` + +### `coth(x)` + +### `asinh(x)` + +### `acosh(x)` + +### `atanh(x)` + +### `rad(deg)` + +### `deg(rad)` + +Use as you wish +# System functions + +## Type conversion functions + +### `copy(expr)` + +Returns the deep copy of the expression. Can be used to copy mutable objects, like maps and lists + +### `type(expr)` + +Returns the string value indicating type of the expression. Possible outcomes +are `null, number, string, list, iterator`, as well as minecraft related concepts like `block, entity, nbt` + +### `bool(expr)` + +Returns a boolean context of the expression. Note that there are no true/false values in scarpet. `true` is +alias of 1, and `false` is 0\. Bool is also interpreting string values as boolean, which is different from other +places where boolean context can be used. This can be used in places where API functions return string values to +represent binary values + +
+bool(pi) => 1
+bool(false) => 0
+bool('') => 0
+bool(l()) => 0
+bool(l('')) => 1
+bool('foo') => 1
+bool('false') => 0
+bool('nulL') => 0
+if('false',1,0) => 1
+
+ +### `number(expr)` + +Returns a numeric context of the expression. Can be used to read numbers from strings + +
+number(null) => null
+number(false) => 0
+number('') => null
+number('3.14') => 3.14
+number(l()) => 0
+number(l('')) => 1
+number('foo') => null
+number('3bar') => null
+number('2')+number('2') => 4
+
+ +### `str(expr, params? ... ), str(expr, param_list)` + +Returns a formatted string representing expression. Accepts formatting style accepted by `String.format`. +Supported types (with `"%?"` syntax): + +* d, o, x: integers +* a, e, f, g: floats +* b: booleans +* s: strings + +
+str(null) => null
+str(false) => 0
+str('') => null
+str('3.14') => 3.14
+str(l()) => 0
+str(l('')) => 1
+str('foo') => null
+str('3bar') => null
+str(2)+str(2) => 22
+str('pi: %.2f',pi) => 'pi: 3.14'
+str('player at: %d %d %d',pos(player())) => 'player at: 567, -2423, 124'
+
+ +* * * +## Threading and Parallel Execution + +Scarpet allows to run threads of execution in parallel to the main script execution thread. In Minecraft, the main +thread scripts are executed on the main server thread. Since Minecraft is inherently NOT thread safe, it is not that +beneficial to parallel execution in order to access world resources faster. Both `GetBlockState` and `setBlockState` +are not thread safe and require the execution to park on the server thread, where these requests can be executed in +the off-tick time in between ticks that didn't take 50ms. There are however benefits of running things in parallel, +like fine time control not relying on the tick clock, or running things independent on each other. You can still run +your actions on tick-by-tick basis, either taking control of the execution using `game_tick()` API function +(nasty solution), or scheduling tick using `schedule()` function (much nicer solution), but threading often gives +the neatest solution to solve problems in parallel (see scarpet camera). + +Due to limitations with the game, there are some limits to the threading as well. You cannot for +instance `join_task()` at all from the main script and server thread, because any use of Minecraft specific +function that require any world access, will require to park and join on the main thread to get world access, +meaning that calling join on that task would inevitably lead to a typical deadlock. You can still join tasks +from other threads, just because the only possibility of a deadlock in this case would come explicitly from your +bad code, not the internal world access behaviour. Some things tough like player or entity manipulation, can be +effectively parallelized. + +### `task(function, ?args...., ?executor)` + +Creates and runs a parallel task, returning the handle to the task object. Task will return the return value of the +function when its completed, or will return `null` immediately if task is still in progress, so grabbing a value of +a task object is non-blocking. Function can be either function value, or function lambda, or a name of an existing +defined function. In case function needs arguments to be called with, they should be supplied after the function +name, or value. Optional `executor` identifier is to place the task in a specific queue identified by this value. +The default thread value is the `null` thread. There is no limits on number of parallel tasks for any executor, +so using different queues is solely for synchronization purposes. Also, since `task` function knows how many extra +arguments it requires, the use of tailing optional parameter for the custom executor thread pool is not ambiguous. + +
+task( _() -> print('Hello Other World') )  => Runs print command on a separate thread
+foo(a, b) -> print(a+b); task('foo',2,2)  => Uses existing function definition to start a task
+task('foo',3,5,'temp');  => runs function foo with a different thread executor, identified as 'temp'
+a = 3; task( _(outer(a), b) -> foo(a,b), 5, 'temp')  
+    => Another example of running the same thing passing arguments using closure over anonymous function as well as passing a parameter.
+
+ +### `task_count(executor?)` + +If no argument provided, returns total number of tasks being executed in parallel at this moment using scarpet +threading system. If the executor is provided, returns number of active tasks for that provider. Use `task_count(null)` +to get the task count of the default executor only. + +### `task_value(task)` + +Returns the task return value, or `null` if task hasn't finished yet. Its a non-blocking operation. Unlike `join_task`, +can be called on any task at any point + +### `task_join(task)` + +Waits for the task completion and returns its computed value. If the task has already finished returns it immediately. +Unless taking the task value directly, i.e. via `task_value`, this operation is blocking. Since Minecraft has a +limitation that all world access operations have to be performed on the main game thread in the off-tick time, +joining any tasks that use Minecraft API from the main thread would mean automatic lock, so joining from the main +thread is not allowed. Join tasks from other threads, if you really need to, or communicate asynchronously with +the task via globals or function data / arguments to monitor its progress, communicate, get partial results, +or signal termination. + +### `task_completed(task)` + +Returns true if task has completed, or false otherwise. + +### `synchronize(lock, expression)` + +Evaluates `expression` synchronized with respect to the lock `lock`. Returns the value of the expression. + +* * * + +## Auxiliary functions + +### `lower(expr), upper(expr), title(expr)` + +Returns lowercase, uppercase or titlecase representation of a string representation of the passed expression + +
+lower('aBc') => 'abc'
+upper('aBc') => 'ABC'
+title('aBc') => 'Abc'
+
+ +### `replace(string, regex, repl?); replace_first(string, regex, repl?)` + +Replaces all, or first occurence of a regular expression in the string with `repl` expression, +or nothing, if not specified + +
+replace('abbccddebfg','b+','z')  // => azccddezfg
+replace_first('abbccddebfg','b+','z')  // => azccddebfg
+
+ +### `length(expr)` + +Returns length of the expression, the length of the string, the length of the integer part of the number, +or length of the list + +
+length(pi) => 1
+length(pi*pi) => 1
+length(pi^pi) => 2
+length(l()) => 0
+length(l(1,2,3)) => 3
+length('') => 0
+length('foo') => 3
+
+ +### `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. 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]
+map(range(10), str('%.1f',rand(_))) => [0.0, 0.4, 0.6, 1.9, 2.8, 3.8, 5.3, 2.2, 1.6, 5.6]
+
+ +### `perlin(x), perlin(x, y), perlin(x, y, z), perlin(x, y, z, seed)` + +returns a noise value from `0.0` to `1.0` (roughly) for 1, 2 or 3 dimensional coordinate. The default seed it samples +from is `0`, but seed can be specified as a 4th argument as well. In case you need 1D or 2D noise values with custom +seed, use `null` for `z`, or `y` and `z` arguments respectively. + +Perlin noise is based on a square grid and generates rougher maps comparing to Simplex, which is creamier. +Querying for lower-dimensional result, rather than affixing unused dimensions to constants has a speed benefit, + +Thou shall not sample from noise changing seed frequently. Scarpet will keep track of the last 256 perlin seeds +used for sampling providing similar speed comparing to the default seed of `0`. In case the app engine uses more +than 256 seeds at the same time, switching between them can get much more expensive. + +### `simplex(x, y), simplex(x, y, z), simplex(x, y, z, seed)` + +returns a noise value from `0.0` to `1.0` (roughly) for 2 or 3 dimensional coordinate. The default seed it samples +from is `0`, but seed can be specified as a 4th argument as well. In case you need 2D noise values with custom seed, +use `null` for `z` argument. + +Simplex noise is based on a triangular grid and generates smoother maps comparing to Perlin. To sample 1D simplex +noise, affix other coordinate to a constant. + +Thou shall not sample from noise changing seed frequently. Scarpet will keep track of the last 256 simplex seeds +used for sampling providing similar speed comparing to the default seed of `0`. In case the app engine uses more +than 256 seeds at the same time, switching between them can get much more expensive. + +### `print(expr)` + +prints the value of the expression to chat. Passes the result of the argument to the output unchanged, +so `print`-statements can be weaved in code to debug programming issues + +
+print('foo') => results in foo, prints: foo
+a = 1; print(a = 5) => results in 5, prints: 5
+a = 1; print(a) = 5 => results in 5, prints: 1
+print('pi = '+pi) => prints: pi = 3.141592653589793
+print(str('pi = %.2f',pi)) => prints: pi = 3.14
+
+ +### `sleep(expr)` + +Halts the execution of the program (and the game itself) for `expr` milliseconds. All in all, its better to +use `game_tick(expr)` to let the game do its job while the program waits + +
+sleep(50)
+
+ +### `time()` + +Returns the number of milliseconds since 'some point', like Java's `System.nanoTime()`. +It returns a float, which has 1 microsecond precision (0.001 ms) + +
+start_time = time();
+flip_my_world_upside_down();
+print(str('this took %d milliseconds',time()-start_time))
+
+ +### `profile_expr(expression)` + +Returns number of times given expression can be run in 50ms time. Useful to profile and optimize your code. +Note that, even if its only a number, it WILL run these commands, so if they are destructive, you need to be careful. + +* * * + +## Access to variables and stored functions (use with caution) + +### `var(expr)` + +Returns the variable under the name of the string value of the expression. Allows to manipulate variables in more +programmatic manner, which allows to use local variable set with a hash map type key-value access, +can also be used with global variables + +
+a = 1; var('a') = 'foo'; a => a == 'foo'
+
+ +### `undef(expr)` + +Removes all bindings of a variable with a name of `expr`. Removes also all function definitions with that name. +It can affect global variable pool, and local variable set for a particular function. + +
+inc(i) -> i+1; foo = 5; inc(foo) => 6
+inc(i) -> i+1; foo = 5; undef('foo'); inc(foo) => 1
+inc(i) -> i+1; foo = 5; undef('inc'); undef('foo'); inc(foo) => Error: Function inc is not defined yet at pos 53
+undef('pi')  => bad idea - removes hidden variable holding the pi value
+undef('true')  => even worse idea, unbinds global true value, all references to true would now refer to the default 0
+
+ +### `vars(prefix)` + +It returns all names of variables from local scope (if prefix does not start with 'global') or global variables +(otherwise). Here is a larger example that uses combination of `vars` and `var` functions to be +used for object counting + +
+/script run
+$ count_blocks(ent) -> (
+$   l(cx, cy, cz) = query(ent, 'pos');
+$   scan(cx, cy, cz, 16, 16, 16, var('count_'+_) += 1);
+$   for ( sort_key( vars('count_'), -var(_)),
+$     print(str( '%s: %d', slice(_,6), var(_) ))
+$   )
+$ )
+/script run count_blocks(player())
+
+ +* * * + +## System key-value storage + +Scarpet runs apps in isolation. The can share code via use of shared libraries, but each library that is imported to +each app is specific to that app. Apps can store and fetch state from disk, but its restricted to specific locations +meaning apps cannot interact via disk either. To facilitate communication for interappperability, scarpet hosts its +own key-value storage that is shared between all apps currently running on the host, providing methods for getting an +associated value with optional setting it if not present, and an operation of modifying a content of a system +global value. + +### `system_variable_get(key, default_value ?)` + +Returns the variable from the system shared key-value storage keyed with a `key` value, optionally if value is +not present, and default expression is provided, sets a new value to be associated with that key + +### `system_variable_set(key, new_value)` + +Returns the variable from the system shared key-value storage keyed with a `key` value, and sets a new +mapping for the key# Loops, and higher order functions + +Efficient use of these functions can greatly simplify your programs and speed them up, as these functions will +internalize most of the operations that need to be applied on multiple values at the same time. Most of them take +a `list` argument which can be any iterable structure in scarpet, including generators, like `rect`, or `range`, +and maps, where the iterator returns all the map keys + +## Loops + +### `break(), break(expr), continue(), continue(expr)` + +These allow to control execution of a loop either skipping current iteration code, using `continue`, or finishing the +current loop, using `break`. `break` and `continue` can only be used inside `for, while, loop, map, filter and reduce` +functions, while `break` can be used in `first` as well. Outside of the internal expressions of these functions, +calling `break` or `continue` will cause an error. In case of the nexted loops, and more complex setups, use +custom `try` and `throw` setup. + +Please check corresponding loop function description what `continue` and `break` do in their contexts, but in +general case, passed values to `break` and `continue` will be used in place of the return value of the internal +iteration expression. + +### `for(list,expr(_,_i))` + +Evaluates expression over list of items from the `list`. Supplies `_`(value) and `_i`(iteration number) to the `expr`. + +Returns the number of times `expr` was successful. Uses `continue` and `break` argument in place of the returned +value from the `expr`(if supplied), to determine if the iteration was successful. + +
+check_prime(n) -> !first( range(2, sqrt(n)+1), !(n % _) );
+for(range(1000000,1100000),check_prime(_))  => 7216
+
+ +From which we can learn that there is 7216 primes between 1M and 1.1M + +### `while(cond, limit)` + +Evaluates expression `expr` repeatedly until condition `cond` becomes false, but not more than `limit` times. +Returns the result of the last `expr` evaluation, or `null` if nothing was successful. Both `expr` and `cond` will +recveived a bound variable `_` indicating current iteration, so its a number. + +
+while(a<100,10,a=_*_)  => 81 // loop exhausted via limit
+while(a<100,20,a=_*_)  => 100 // loop stopped at condition, but a has already been assigned
+while(_*_<100,20,a=_*_)  => 81 // loop stopped at condition, before a was assigned a value
+
+ +### `loop(num,expr(_),exit(_)?)` + +Evaluates expression `expr`, `num` number of times. code>expr receives `_` system variable indicating the iteration. + +
+loop(5, game_tick())  => repeat tick 5 times
+list = l(); loop(5, x = _; loop(5, list += l(x, _) ) ); list
+  // double loop, produces: [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [1, 0], [1, 1], ... , [4, 2], [4, 3], [4, 4]]
+
+ +In this small example we will search for first 10 primes, apparently including 0: + +
+check_prime(n) -> !first( range(2, sqrt(n)+1), !(n % _) );
+primes = l();
+loop(10000, if(check_prime(_), primes += _ ; if (length(primes) >= 10, break())));
+primes
+// outputs: [0, 1, 2, 3, 5, 7, 11, 13, 17, 19]
+
+ +## Higher Order Functions + +### `map(list,expr(_,_i))` + +Converts a `list` of values, to another list where each value is result of an expression `v = expr(_, _i)` +where `_` is passed as each element of the list, and `_i` is the index of such element. If `break` is called the +map returns whatever collected thus far. If `continue` and `break` are used with supplied argument, it is used in +place of the resulting map element, otherwise current element is skipped. + +
+map(range(10), _*_)  => [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
+map(players('*'), _+' is stoopid') [gnembon is stoopid, herobrine is stoopid]
+
+ +### `filter(list,expr(_,_i))` + +filters `list` elements returning only these that return positive result of the `expr`. 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(entity_list('*'),_=='Witch'), query(_,'pos') )  => [[1082.5, 57, 1243.5]]
+
+ +### `first(list,expr(_,_i))` + +Finds and returns the first item in the list that satisfies `expr`. It sets `_` for current element value, +and `_i` for index of that element. `break` can be called inside the iteration code, using its argument value +instead of the current item. `continue` has no sense and cannot be called inside `first` call. + +
+first(range(1000,10000), n=_; !first( range(2, sqrt(n)+1), !(n % _) ) )  => 1009 // first prime after 1000
+
+ +Notice in the example above, that we needed to rename the outer `_` to be albe to use in in the inner `first` call + +### `all(list,expr(_,_i))` + +Returns `true` if all elements on the list satisfy the condition. Its roughly equivalent +to `all(list,expr) <=> for(list,expr)==length(list)`. `expr` also receives bound `_` and `_i` variables. `break` +and `continue` have no sense and cannot be used inside of `expr` body. + +
+all([1,2,3], check_prime(_))  => 1
+all(neighbours(x,y,z), _=='stone')  => 1 // if all neighbours of [x, y, z] are stone
+map(filter(rect(0,4,0,1000,0,1000), l(x,y,z)=pos(_); all(rect(x,y,z,1,0,1),_=='bedrock') ), pos(_) )
+  => [[-298, 4, -703], [-287, 4, -156], [-269, 4, 104], [242, 4, 250], [-159, 4, 335], [-208, 4, 416], [-510, 4, 546], [376, 4, 806]]
+    // find all 3x3 bedrock structures in the top bedrock layer
+map( filter( rect(0,4,0,1000,1,1000,1000,0,1000), l(x,y,z)=pos(_);
+        all(rect(x,y,z,1,0,1),_=='bedrock') && for(rect(x,y-1,z,1,1,1,1,0,1),_=='bedrock')<8),
+   pos(_) )  => [[343, 3, -642], [153, 3, -285], [674, 3, 167], [-710, 3, 398]]
+    // ditto, but requiring at most 7 bedrock block in the 18 blocks below them
+
+ +### `reduce(list,expr(_a,_,_i), initial)` + +Applies `expr` for each element of the list and saves the result in `_a` accumulator. Consecutive calls to `expr` +can access that value to apply more values. You also need to specify the initial value to apply for the +accumulator. `break` can be used to terminate reduction prematurely. If a value is provided to `break` or `continue`, +it will be used from now on as a new value for the accumulator. + +
+reduce([1,2,3,4],_a+_,0)  => 10
+reduce([1,2,3,4],_a*_,1)  => 24
+
# User-defined functions and program control flow + +## Writing programs with more than 1 line + +### `Operator ;` + +To effectively write programs that have more than one line, a programmer needs way to specify a sequence of commands +that execute one after another. In `scarpet` this can be achieved with `;`. Its an operator, and by separating +statements with semicolons. And since whitespaces and +`$` (commandline visible newline separator) +sign are all treats as whitespaces, how you layout your code doesn't matter, as long as it is readable to everyone involved. + +
+expr;
+expr;
+expr;
+expr
+
+ +Notice that the last expression is not followed by a semicolon. Since instruction separation is functional +in `scarpet`, and not barely an instruction delimiter, terminating the code with a dangling operator wouldn't +be valid. Having said that, since many programming languages don't care about the number of op terminators +programmers use, carpet preprocessor will remove all unnecessary semicolons from scripts when compiled. + +In general `expr; expr; expr; expr` is equivalent to `(((expr ; expr) ; expr) ; expr)`. + +Result of the evaluated expression is the same as the result of the second expression, but first expression +is also evaluated for side-effects + +
+expr1 ; expr2 => expr2  // with expr1 as a side-effect
+
+ +## Global variables + +All defined functions are compiled, stored persistently, and available globally - accessible to all other scripts. +Functions can only be undefined via call to `undef('fun')`, which would erase global entry for function `fun`. +Since all variables have local scope inside each function, one way to share large objects is via global variables + +Any variable that is used with a name that starts with `'global_'` will be stored and accessible globally, not, +inside current scope. It will also persist across scripts, so if a procedure needs to use its own construct, it +needs to define it, or initialize it explicitly, or undefine it via `undef` + +
+a() -> global_list+=1; global_list = l(1,2,3); a(); a(); global_list  // => [1,2,3,1,1]
+
+ +### `Operator ->` + +To organize code better than a flat sequence of operations, one can define functions. Definition is correct +if has the following form + +
+fun(args, ...) -> expr
+
+ +Where `fun(args, ...)` is a function signature indicating function name, number of arguments, and their names, +and expr is an expression (can be complex) that is evaluated when `fun` is called. Names in the signature don't +need to be used anywhere else, other occurrences of these names will be masked in this function scope. Function +call creates new scope for variables inside `expr`, so all non-global variables are not visible from the caller +scope. All parameters are passed by value to the new scope, including lists and other containers, however their +copy will be shallow. + +The function returns its name as a string, which means it can be used to call it later with the `call` function + +Using `_` as the function name creates anonymous function, so each time `_` function is defined, it will be given +a unique name, which you can pass somewhere else to get this function `call`ed. + +
+a(lst) -> lst+=1; list = l(1,2,3); a(list); a(list); list  // => [1,2,3]
+
+ +In case the inner function wants to operate and modify larger objects, lists from the outer scope, but not global, +it needs to use `outer` function in function signature + +### `outer(arg)` + +`outer` function can only be used in the function signature, and it will cause an error everywhere else. It +saves the value of that variable from the outer scope and allows its use in the inner scope. This is a similar +behaviour to using outer variables in lambda function definitions from Java, except here you have to specify +which variables you want to use, and borrow + +This mechanism can be used to use static mutable objects without the need of using `global_...` variables + +
+list = l(1,2,3); a(outer(list)) -> list+=1;  a(); a(); list  // => [1,2,3,1,1]
+
+ +The return value of a function is the value of the last expression. This as the same effect as using outer or +global lists, but is more expensive + +
+a(lst) -> lst+=1; list = l(1,2,3); list=a(list); list=a(list); list  // => [1,2,3,1,1]
+
+ +Ability to combine more statements into one expression, with functions, passing parameters, and global and outer +scoping allow to organize even larger scripts + +### `import(module_name, symbols ...)` + +Imports symbols from other apps and libraries into the current one: global variables or functions, allowing to use +them in the current app. This include other symbols imported by these modules. Scarpet supports cicular dependencies, +but if symbols are used directly in the module body rather than functions, it may not be able to retrieve them. +Returns full list of available symbols that could be imported from this module, which can be used to debug import +issues, and list contents of libraries. + +### `call(function, args.....)` + +calls a user defined function with specified arguments. It is equivalent to calling `function(args...)` directly +except you can use it with function value, or name instead. This means you can pass functions to other user defined +functions as arguments and call them with `call` internally. And since function definitions return the defined +function, they can be defined in place as anonymous functions. + +Little technical note: the use of `_` in expression passed to built in functions is much more efficient due to not +creating new call stacks for each invoked function, but anonymous functions is the only mechanism available for +programmers with their own lambda arguments + +
+my_map(list, function) -> map(list, call(function, _));
+my_map(l(1,2,3), _(x) -> x*x);    // => [1,4,9]
+profile_expr(my_map(l(1,2,3), _(x) -> x*x));   // => ~32000
+sq(x) -> x*x; profile_expr(my_map(l(1,2,3), 'sq'));   // => ~36000
+sq = (_(x) -> x*x); profile_expr(my_map(l(1,2,3), sq));   // => ~36000
+profile_expr(map(l(1,2,3), _*_));   // => ~80000
+
+ +## Control flow + +### `return(expr?)` + +Sometimes its convenient to break the organized control flow, or it is not practical to pass the final result value of +a function to the last statement, in this case a return statement can be used + +If no argument is provided - returns null value. + +
+def() -> (
+   expr1;
+   expr2;
+   return(expr3); // function terminates returning expr3
+   expr4;     // skipped
+   expr5      // skipped
+)
+
+ +In general its cheaper to leave the last expression as a return value, rather than calling +returns everywhere, but it would often lead to a messy code. + +### `exit(expr?)` + +It terminates entire program passing `expr` as the result of the program execution, or null if omitted. + +### `try(expr, catch_expr(_)?) ... throw(value?)` + +`try` function evaluates expression, and continues further unless `throw` function is called anywhere +inside `expr`. In that case the `catch_expr` is evaluates with `_` set to the argument `throw` was called with. +This mechanic accepts skipping thrown value - it throws null instead, and catch expression - then try returns +null as well This mechanism allows to terminate large portion of a convoluted call stack and continue program +execution. There is only one level of exceptions currently in carpet, so if the inner function also defines +the `try` catchment area, it will received the exception first, but it can technically rethrow the value its +getting for the outer scope. Unhandled throw acts like an exit statement. + +### `if(cond, expr, cond?, expr?, ..., default?)` + +If statement is a function that takes a number of conditions that are evaluated one after another and if any of +them turns out true, its `expr` gets returned, otherwise, if all conditions fail, the return value is `default` +expression, or `null` if default is skipped + +`if` function is equivalent to `if (cond) expr; else if (cond) expr; else default;` from Java, +just in a functional form +# Lists, Maps and API support for Containers + +Scarpet supports basic container types: lists and maps (aka hashmaps, dicts etc..) + +## Container manipulation + +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, ...), get(lvalue), ':' 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 + +for maps, retrieves the value under the key specified in the `address` or null otherwise + +[Minecraft specific usecase]: In case `value` is of `nbt` type, uses address as the nbt path to query, returning null, +if path is not found, one value if there was one match, or list of values if result is a list. Returned elements can +be of numerical type, string texts, or another compound nbt tags + +In case to simplify the access with nested objects, you can add chain of addresses to the arguments of `get` rather +than calling it multiple times. `get(get(foo,a),b)` is equivalent to `get(foo, a, b)`, or `foo:a:b`. + +
+get(l(range(10)), 5)  => 5
+get(l(range(10)), -1)  => 9
+get(l(range(10)), 10)  => 0
+l(range(10)):93  => 3
+get(player() ~ 'nbt', 'Health') => 20 // inefficient way to get player health, use player() ~ 'health' instead
+get(m( l('foo',2), l('bar',3), l('baz',4) ), 'bar')  => 3
+
+ +### `has(container, address, ...), has(lvalue)` + +Similar to `get`, but returns boolean value indicating if the given index / key / path is in the container. +Can be used to determine if `get(...)==null` means the element doesn't exist, or the stored value for this +address is `null`, and is cheaper to run than `get`. + +Like get, it can accept multiple addresses for chains in nested containers. In this case `has(foo:a:b)` is +equivalent to `has(get(foo,a), b)` or `has(foo, a, b)` + +### `delete(container, address, ...), delete(lvalue)` + +Removes specific entry from the container. For the lists - removes the element and shrinks it. For maps, it +removes the key from the map, and for nbt - removes content from a given path. For lists and maps returns previous +entry at the address, for nbt's - number of removed objects, with 0 indicating that the original value was unaffected. + +Like with the `get` and `has`, `delete` can accept chained addresses, as well as l-value container access, removing +the value from the leaf of the path provided, so `delete(foo, a, b)` is the +same as `delete(get(foo,a),b)` or `delete(foo:a:b)` + +Returns true, if container was changed, false, if it was left unchanged, and null if operation was invalid. + +### `put(container, address, value), put(container, address, value, mode), put(lvalue, value)` + +**Lists** + +Modifies the container by replacing the value under the address with the supplied `value`. For lists, a valid +index is required, but can be negative as well to indicate positions from the end of the list. If `null` is +supplied as the address, it always means - add to the end of the list. + +There are three modes that lists can have items added to them: + +* `replace`(default): Replaces item under given index(address). Doesn't change the size of the array +unless `null` address is used, which is an exception and then it appends to the end +* `insert`: Inserts given element at a specified index, shifting the rest of the array to make space for the item. +Note that index of -1 points to the last element of the list, thus inserting at that position and moving the previous +last element to the new last element position. To insert at the end, use `+=` operator, or `null` address in put +* `extend`: treats the supplied value as an iterable set of values to insert at a given index, extending the list +by this amount of items. Again use `null` address/index to point to the end of the list + +Due to the extra mode parameter, there is no chaining for `put`, but you can still use l-value container access to +indicate container and address, so `put(foo, key, value)` is the same as `put(foo:key, value)` or `foo:key=value` + +Returns true, if container got modified, false otherwise, and null if operation was invalid. + +**Maps** + +For maps there are no modes available (yet, seems there is no reason to). It replaces the value under the supplied +key (address), or sets it if not currently present. + +**NBT Tags** + +The address for nbt values is a valid nbt path that you would use with `/data` command, and tag is any tag that +would be applicable for a given insert operation. Note that to distinguish between proper types (like integer types, +you need to use command notation, i.e. regular ints is `123`, while byte size int would be `123b` and an explicit +string would be `"5"`, so it helps that scarpet uses single quotes in his strings. Unlike for lists and maps, it +returns the number of affected nodes, or 0 if none were affected. + +There are three modes that NBT tags can have items added to them: + +* `replace`(default): Replaces item under given path(address). Removes them first if possible, and then adds given +element to the supplied position. The target path can indicate compound tag keys, lists, or individual elements +of the lists. +* ``: Index for list insertions. Inserts given element at a specified index, inside a list specified with the +path address. Fails if list is not specified. It behaves like `insert` mode for lists, i.e. it is not removing any +of the existing elements. Use `replace` to remove and replace existing element. +* `merge`: assumes that both path and replacement target are of compound type (dictionaries, maps, `{}` types), +and merges keys from `value` with the compound tag under the path + +
+a = l(1, 2, 3); put(a, 1, 4); a  => [1, 4, 3]
+a = l(1, 2, 3); put(a, null, 4); a  => [1, 2, 3, 4]
+a = l(1, 2, 3); put(a, 1, 4, 'insert'); a  => [1, 4, 2, 3]
+a = l(1, 2, 3); put(a, null, l(4, 5, 6), 'extend'); a  => [1, 2, 3, 4, 5, 6]
+a = l(1, 2, 3); put(a, 1, l(4, 5, 6), 'extend'); a  => [1, 4, 5, 6, 2, 3]
+a = l(l(0,0,0),l(0,0,0),l(0,0,0)); put(a.1, 1, 1); a  => [[0, 0, 0], [0, 1, 0], [0, 0, 0]]
+a = m(1,2,3,4); put(a, 5, null); a  => {1: null, 2: null, 3: null, 4: null, 5: null}
+tag = nbt('{}'); put(tag, 'BlockData.Properties', '[1,2,3,4]'); tag  => {BlockData:{Properties:[1,2,3,4]}}
+tag = nbt('{a:[{lvl:3},{lvl:5},{lvl:2}]}'); put(tag, 'a[].lvl', 1); tag  => {a:[{lvl:1},{lvl:1},{lvl:1}]}
+tag = nbt('{a:[{lvl:[1,2,3]},{lvl:[3,2,1]},{lvl:[4,5,6]}]}'); put(tag, 'a[].lvl', 1, 2); tag
+     => {a:[{lvl:[1,2,1,3]},{lvl:[3,2,1,1]},{lvl:[4,5,1,6]}]}
+tag = nbt('{a:[{lvl:[1,2,3]},{lvl:[3,2,1]},{lvl:[4,5,6]}]}'); put(tag, 'a[].lvl[1]', 1); tag
+     => {a:[{lvl:[1,1,3]},{lvl:[3,1,1]},{lvl:[4,1,6]}]}
+
+ +## List operations + +### `l(values ...), l(iterator)` + +Creates a list of values of the expressions passed as parameters. It can be used as an L-value and if all +elements are variables, you coujld use it to return multiple results from one function call, if that +function returns a list of results with the same size as the `l` call uses. In case there is only one +argument and it is an iterator (vanilla expression specification has `range`, but Minecraft API implements +a bunch of them, like `diamond`), it will convert it to a proper list. Iterators can only be used in high order +functions, and are treated as empty lists, unless unrolled with `l` + +
+l(1,2,'foo') => [1, 2, foo]
+l() => [] (empty list)
+l(range(10)) => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+l(1, 2) = l(3, 4) => Error: l is not a variable
+l(foo, bar) = l(3,4); foo==3 && bar==4 => 1
+l(foo, bar, baz) = l(2, 4, 6); l(min(foo, bar), baz) = l(3, 5); l(foo, bar, baz)  => [3, 4, 5]
+
+ +In the last example `l(min(foo, bar), baz)` creates a valid L-value, as min(foo, bar) finds the lower of the +variables (in this case `foo`) creating a valid assignable L-list of [foo, baz], and these values +will be assigned new values + +### `join(delim, list), join(delim, values ...)` + +Returns a string that contains joined elements of the list, iterator, or all values, +concatenated with `delim` delimiter + +
+join('-',range(10))  => 0-1-2-3-4-5-6-7-8-9
+join('-','foo')  => foo
+join('-', 'foo', 'bar')  => foo-bar
+
+ +### `split(delim, expr)` + +Splits a string undr `expr` by `delim` which can be a regular expression + +
+split('',foo)  => [f, o, o]
+split('.','foo.bar')  => []
+split('\\.','foo.bar')  => [foo, bar]
+
+ +### `slice(expr, from, to?)` + +extracts a substring, or sublist (based on the type of the result of the expression under expr with +starting index of `from`, and ending at `to` if provided, or the end, if omitted + +
+slice(l(0,1,2,3,4,5), 1, 3)  => [1, 2, 3]
+slice('foobar', 0, 1)  => 'f'
+slice('foobar', 3)  => 'bar'
+slice(range(10), 3, 5)  => [3, 4, 5]
+slice(range(10), 5)  => [5, 6, 7, 8, 9]
+
+ +### `sort(list), sort(values ...)` + +Sorts in the default sortographical order either all arguments, or a list if its the only argument. +It returns a new sorted list, not affecting the list passed to the argument + +
sort(3,2,1)  => [1, 2, 3]
+sort('a',3,11,1)  => [1, 3, 11, 'a']
+list = l(4,3,2,1); sort(list)  => [1, 2, 3, 4]
+
+ +### `sort_key(list, key_expr)` + +Sorts a copy of the list in the order or keys as defined by the `key_expr` for each element + +
+sort_key([1,3,2],_)  => [1, 2, 3]
+sort_key([1,3,2],-_)  => [3, 2, 1]
+sort_key(l(range(10)),rand(1))  => [1, 0, 9, 6, 8, 2, 4, 5, 7, 3]
+sort_key(l(range(20)),str(_))  => [0, 1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 2, 3, 4, 5, 6, 7, 8, 9]
+
+ +### `range(to), range(from, to), range(from, to, step)` + +Creates a range of numbers from `from`, no greater/larger than `to`. The `step` parameter dictates not only the +increment size, but also direction (can be negative). The returned value is not a proper list, just the iterator +but if for whatever reason you need a proper list with all items evaluated, use `l(range(to))`. +Primarily to be used in higher order functions + +
+range(10)  => [...]
+l(range(10))  => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+map(range(10),_*_)  => [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
+reduce(range(10),_a+_, 0)  => 45
+range(5,10)  => [5, 6, 7, 8, 9]
+range(20, 10, -2)  => [20, 18, 16, 14, 12]
+
+ +### `element(list, index)(deprecated)` + +Legacy support for older method that worked only on lists. Please use `get(...)` for equivalent support, or `.` +operator. Also previous unique behaviours with `put` on lists has been removed to support all type of +container types. + +## Map operations + +Scarpet supports map structures, aka hashmaps, dicts etc. Map structure can also be used, with `null` values as sets. +Apart from container access functions, (`. , get, put, has, delete`), the following functions: + +### `m(values ...), m(iterator), m(key_value_pairs)` + +creates and initializes a map with supplied keys, and values. If the arguments contains a flat list, these are all +treated as keys with no value, same goes with the iterator - creates a map that behaves like a set. If the +arguments is a list of lists, they have to have two elements each, and then first is a key, and second, a value + +
+m(1,2,'foo') => {1: null, 2: null, foo: null}
+m() => {} (empty map)
+m(range(10)) => {0: null, 1: null, 2: null, 3: null, 4: null, 5: null, 6: null, 7: null, 8: null, 9: null}
+m(l(1, 2), l(3, 4)) => {1: 2, 3: 4}
+reduce(range(10), put(_a, _, _*_); _a, m())
+     => {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
+
+ +### `keys(map), values(map), pairs(map)` + +Returns full lists of keys, values and key-value pairs (2-element lists) for all the entries in the map +# Minecraft specific API and `scarpet` language add-ons and commands + +Here is the gist of the Minecraft related functions. Otherwise the CarpetScript could live without Minecraft. + +## Dimension warning + +One note, which is important is that most of the calls for entities and blocks would refer to the current +dimension of the caller, meaning, that if we for example list all the players using `player('all')` function, +if a player is in the other dimension, calls to entities and blocks around that player would point incorrectly. +Moreover, running commandblocks in the spawn chunks would mean that commands will always refer to the overworld +blocks and entities. In case you would want to run commands across all dimensions, just run three of them, +using `/execute in overworld/the_nether/the_end run script run ...` and query players using `player('*')`, +which only returns players in current dimension, or use `in_dimension(expr)` function.# Blocks / World API + +## Specifying blocks + +### `block(x, y, z)`, `block(l(x,y,z))`, `block(state)` + +Returns either a block from specified location, or block with a specific state (as used by `/setblock` command), +so allowing for block properties, block entity data etc. Blocks otherwise can be referenced everywhere by its simple +string name, but its only used in its default state. + +
+block('air')  => air
+block('iron_trapdoor[half=top]')  => iron_trapdoor
+block(0,0,0) == block('bedrock')  => 1
+block('hopper[facing=north]{Items:[{Slot:1b,id:"minecraft:slime_ball",Count:16b}]}') => hopper
+
+ +Retrieving a block with `block` function has also a side-effect of evaluating its current state and data. +So if you use it later it will reflect block state and data of the block that was when block was called, rather than +when it was used. Block values passed in various places like `scan` functions, etc, are not fully evaluated unless +its properties are needed. This means that if the block at the location changes before its queried in the program this +might result in getting the later state, which might not be desired. Consider the following example: + +
set(10,10,10,'stone');
+scan(10,10,10,0,0,0, b = _);
+set(10,10,10,'air');
+print(b); // 'air', block was remembered 'lazily', and evaluated by `print`, when it was already set to air
+set(10,10,10,'stone');
+scan(10,10,10,0,0,0, b = block(_));
+set(10,10,10,'air');
+print(b); // 'stone', block was evaluated 'eagerly' but call to `block`
+
+ +## World Manipulation + +All the functions below can be used with block value, queried with coord triple, or 3-long list. All `pos` in the +functions referenced below refer to either method of passing block position. + +### `set(pos, block, property?, value?, ...)` + +First part of the `set` function is either a coord triple, list of three numbers, or other block with coordinates. +Second part, `block` is either block value as a result of `block()` function string value indicating the block name, +and optional `property - value` pairs for extra block properties. If `block` is specified only by name, then if a +destination block is the same the `set` operation is skipped, otherwise is executed, for other potential extra +properties. + +The returned value is either the block state that has been set, or `false` if block setting was skipped + +
+set(0,5,0,'bedrock')  => bedrock
+set(l(0,5,0), 'bedrock')  => bedrock
+set(block(0,5,0), 'bedrock')  => bedrock
+scan(0,5,0,0,0,0,set(_,'bedrock'))  => 1
+set(pos(players()), 'bedrock')  => bedrock
+set(0,0,0,'bedrock')  => 0   // or 1 in overworlds generated in 1.8 and before
+scan(0,100,0,20,20,20,set(_,'glass'))
+    // filling the area with glass
+scan(0,100,0,20,20,20,set(_,block('glass')))
+    // little bit faster due to internal caching of block state selectors
+b = block('glass'); scan(0,100,0,20,20,20,set(_,b))
+    // yet another option, skips all parsing
+set(x,y,z,'iron_trapdoor')  // sets bottom iron trapdoor
+set(x,y,z,'iron_trapdoor[half=top]')  // Incorrect. sets bottom iron trapdoor - no parsing of properties
+set(x,y,z,'iron_trapdoor','half','top') // correct - top trapdoor
+set(x,y,z, block('iron_trapdoor[half=top]')) // also correct, block() provides extra parsing
+set(x,y,z,'hopper[facing=north]{Items:[{Slot:1b,id:"minecraft:slime_ball",Count:16b}]}') // extra block data
+
+ +### `without_updates(expr)` + +Evaluates subexpression without causing updates when blocks change in the world + +Consider following scenario: We would like to generate a bunch of terrain in a flat world following a perling noise +generator. The following code causes cascading effect as blocks placed on chunk borders will cause other chunks to get +loaded to full, thus generated: + +
+__config() -> m(l('scope', 'global'));
+__on_chunk_generated(x, z) -> (
+  scan(x,0,z,0,0,0,15,15,15,
+    if (perlin(_x/16, _y/8, _z/16) > _y/16,
+      set(_, 'black_stained_glass');
+    )
+  )
+)
+
+ +The following addition resolves this issue, by not allowing block updates pass chunk borders: + +
+__config() -> m(l('scope', 'global'));
+__on_chunk_generated(x, z) -> (
+  without_updates(
+    scan(x,0,z,0,0,0,15,15,15,
+      if (perlin(_x/16, _y/8, _z/16) > _y/16,
+        set(_, 'black_stained_glass');
+      )
+    )
+  )
+)
+
+ +### `place_item(item, pos, facing?, sneak?)` + +Places a given item in the world like it was placed by a player. Item names are default minecraft item name, +less the minecraft prefix. Default facing is 'up', but there are other options: 'down', 'north', 'east', 'south', +'west', but also there are other secondary directions important for placement of blocks like stairs, doors, etc. +Try experiment with options like 'north-up' which is placed facing north with cursor pointing to the upper part of the +block, or 'up-north', which means a block placed facing up (player looking down) and placed smidge away of the block +center towards north. Optional sneak is a boolean indicating if a player would be sneaking while placing the +block - this option only affects placement of chests and scaffolding at the moment. Returns true if placement was +successful, false otherwise. + +
+place_item('stone',x,y,z) // places a stone block on x,y,z block
+place_item('piston,x,y,z,'down') // places a piston facing down
+place_item('carrot',x,y,z) // attempts to plant a carrot plant. Returns true if could place carrots at that position.
+
+ +### `set_poi(pos, type, occupancy?)` + +Sets a Point of Interest (POI) of a specified type with optional custom occupancy. By default new POIs are not occupied. +If type is `null`, POI at position is removed. In any case, previous POI is also removed. Available POI types are: + +* `'unemployed', 'armorer', 'butcher', 'cartographer', 'cleric', 'farmer', 'fisherman', 'fletcher', 'leatherworker', 'librarian', 'mason', 'nitwit', 'shepherd', 'toolsmith', 'weaponsmith', 'home', 'meeting', 'beehive', 'bee_nest', 'nether_portal'` + +Interestingly, `unemployed`, and `nitwit` are not used in the game, meaning, they could be used as permanent spatial +markers for scarpet apps. `meeting` is the only one with increased max occupancy of 32. + +### `set_biome(pos, biome_name)` + +changes biome at that block position. + +### `update(pos)` + +Causes a block update at position. + +### `block_tick(pos)` + +Causes a block to tick at position. + +### `random_tick(pos)` + +Causes a random tick at position. + +### `destroy(pos), destroy(pos, -1), destroy(pos, ), destroy(pos, tool, nbt?)` + +Destroys the block like it was mined by a player. Add -1 for silk touch, and positive number for fortune level. +If tool is specified, and optionally its nbt, it will use that tool and will attempt to mine the block with this tool. +If called without item context, this function, unlike harvest, will affect all kinds of blocks. If called with item +in context, it will fail to break blocks that cannot be broken by a survival player. + +Without item context it returns `false` if failed to destroy the block and `true` if block breaking was successful. +In item context, `true` means that breaking item has no nbt to use, `null` indicating that the tool should be +considered broken in process, and `nbt` type value, for a resulting NBT tag on a hypothetical tool. Its up to the +programmer to use that nbt to apply it where it belong + +Here is a sample code that can be used to mine blocks using items in player inventory, without using player context +for mining. Obviously, in this case the use of `harvest` would be much more applicable: + +
+mine(x,y,z) ->
+(
+   p = player();
+   slot = p~'selected_slot';
+   item_tuple = inventory_get(p, slot);
+   if (!item_tuple, destroy(x,y,z,'air'); return()); // empty hand, just break with 'air'
+   l(item, count, tag) = item_tuple;
+   tag_back = destroy(x,y,z, item, tag);
+   if (tag_back == false, // failed to break the item
+	     return(tag_back)
+   );
+   if (tag_back == true, // block broke, tool has no tag
+	     return(tag_back)
+   );
+   if (tag_back == null, //item broke
+	     delete(tag:'Damage');
+	     inventory_set(p, slot, count-1, item, tag);
+	     return(tag_back)
+   );
+   if (type(tag_back) == 'nbt', // item didn't break, here is the effective nbt
+	     inventory_set(p, slot, count, item, tag_back);
+	     return(tag_back)
+   );
+   print('How did we get here?');
+)
+
+ +### `harvest(player, pos)` + +Causes a block to be harvested by a specified player entity. Honors player item enchantments, as well as damages the +tool if applicable. If the entity is not a valid player, no block gets destroyed. If a player is not allowed to break +that block, a block doesn't get destroyed either. + +## Block and World querying + +### `pos(block), pos(entity)` + +Returns a triple of coordinates of a specified block or entity. Technically entities are queried with `query` function +and the same can be achieved with `query(entity,'pos')`, but for simplicity `pos` allows to pass all positional objects. + +
+pos(block(0,5,0))  => l(0,5,0)
+pos(players()) => l(12.3, 45.6, 32.05)
+pos(block('stone'))  => Error: Cannot fetch position of an unrealized block
+
+ +### `pos_offset(pos, direction, amount?)` + +Returns a coords triple that is offset in a specified `direction` by `amount` of blocks. The default offset amount is +1 block. To offset into opposite facing, use negative numbers for the `amount`. + +
+pos_offset(block(0,5,0), 'up', 2)  => l(0,7,0)
+pos_offset(l(0,5,0), 'up', -2 ) => l(0,3,0)
+
+ +### `block_properties(pos)` + +Returns a list of available block properties for a particular block. If a block has no properties, returns an empty list. + +### `property(pos, name)` + +Returns property of block at `pos`, or specified by `block` argument. If a block doesn't have that property, `null` +value is returned. Returned values are always strings. It is expected from the user to know what to expect and convert +values to numbers using `number()` function or booleans using `bool()` function. + +
+set(x,y,z,'iron_trapdoor','half','top'); property(x,y,z,'half')  => top
+set(x,y,z,'air'); property(x,y,z,'half')  => null
+property(block('iron_trapdoor[half=top]'),'half')  => top
+property(block('iron_trapdoor[half=top]'),'powered')  => false
+bool(property(block('iron_trapdoor[half=top]'),'powered'))  => 0
+
+ +### `block_data(pos)` + +Return NBT string associated with specific location, or null if the block does not carry block data. Can be currently +used to match specific information from it, or use it to copy to another block + +
    block_data(x,y,z) => '{TransferCooldown:0,x:450,y:68, ... }'
+
+ +### `poi(pos), poi(pos, radius), poi(pos, radius, status)` + +Queries a POI (Point of Interest) at a given position, returning `null` if none is found, or tuple of poi type and its +occupancy load. With optional `radius` and `status`, returns a list of POIs around `pos` within a given `radius`. +If `status` is specified (either 'available', or 'occupied') returns only POIs with that status. The return format is +again, poi type, occupancy load, and extra tripple of coordinates. + +Querying for POIs using the radius is intended use of POI mechanics and ability of accessing individual POIs +via `poi(pos)` in only provided for completness. + +
+poi(x,y,z) => null  // nothing set at position
+poi(x,y,z) => ['meeting',3]  // its a bell-type meeting point occupied by 3 villagers
+poi(x,y,z,5) => []  // nothing around
+poi(x,y,z,5) => [['nether_portal',0,[7,8,9]],['nether_portal',0,[7,9,9]]] // two portal blocks in the range
+
+ +### `biome(pos)` + +returns biome at that block position. + +### `solid(pos)` + +Boolean function, true if the block is solid + +### `air(pos)` + +Boolean function, true if a block is air.... or cave air... or void air.... or any other air they come up with. + +### `liquid(pos)` + +Boolean function, true if the block is liquid, or liquidlogged + +### `flammable(pos)` + +Boolean function, true if the block is flammable + +### `transparent(pos)` + +Boolean function, true if the block is transparent + +### `opacity(pos)` + +Numeric, returning opacity level of a block + +### `blocks_daylight(pos)` + +Boolean function, true if the block blocks daylight + +### `emitted_light(pos)` + +Numeric, returning light level emitted from block + +### `light(pos)` + +Integer function, returning total light level at position + +### `block_light(pos)` + +Integer function, returning block light at position. From torches and other light sources. + +### `sky_light(pos)` + +Numeric function, returning sky light at position. From the sky access. + +### `see_sky(pos)` + +Boolean function, returning true if the block can see sky. + +### `hardness(pos)` + +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 +heightmap specified by `type`. Valid options are: + +* `light`: topmost light blocking block (1.13 only) +* `motion`: topmost motion blocking block +* `terrain`: topmost motion blocking block except leaves +* `ocean_floor`: topmost non-water block +* `surface`: topmost surface block + +
+top('motion', x, y, z)  => 63
+top('ocean_floor', x, y, z)  => 41
+
+ +### `loaded(pos)` + +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. + +To check if block is truly loaded, I mean in memory, use `generation_status(x) != null`, as chunks can still be loaded +outside of the playable area, just are not used any of the game mechanics processes. + +
+loaded(pos(players()))  => 1
+loaded(100000,100,1000000)  => 0
+
+ +### `(Deprecated) loaded_ep(pos)` + +Boolean function, true if the block is loaded and entity processing, as per 1.13.2 + +Deprecated as of scarpet 1.6, use `loaded_status(x) > 0`, or just `loaded(x)` with the same effect + +### `loaded_status(pos)` + +Returns loaded status as per new 1.14 chunk ticket system, 0 for inaccessible, 1 for border chunk, 2 for ticking, +3 for entity ticking + +### `generation_status(pos), generation_status(pos, true)` + +Returns generation status as per new 1.14 chunk ticket system. Can return any value from several available but chunks +can only be valid in a few states: `full`, `features`, `liquid_carvers`, and `structure_starts`. Returns `null` +if the chunk is not in memory unless called with optional `true`. + +### `structures(pos), structures(pos, structure_name)` + +Returns structure information for a given block position. Note that structure information is the same for all the +blocks from the same chunk. `structures` function can be called with a block, or a block and a structure name. In +the first case it returns a map of structures at a given position, keyed by structure name, with values indicating +the bounding box of the structure - a pair of two 3-value coords (see examples). When called with an extra structure +name, returns list of components for that structure, with their name, direction and two sets of coordinates +indicating the bounding box of the structure piece. + +### `structure_references(pos), structure_references(pos, structure_name)` + +Returns structure information that a chunk with a given block position is part of. `structure_references` function +can be called with a block, or a block and a structure name. In the first case it returns a list of structure names +that give chunk belongs to. When called with an extra structure name, returns list of positions pointing to the +lowest block position in chunks that hold structure starts for these structures. You can query that chunk structures +then to get its bounding boxes. + +### `set_structure(pos, structure_name), set_structure(pos, structure_name, null)` + +Creates or removes structure information of a structure associated with a chunk of `pos`. Unlike `plop`, blocks are +not placed in the world, only structure information is set. For the game this is a fully functional structure even +if blocks are not set. To remove structure a given point is in, use `structure_references` to find where current +structure starts. + +### `suffocates(pos)` + +Boolean function, true if the block causes suffocation. + +### `power(pos)` + +Numeric function, returning redstone power level at position. + +### `ticks_randomly(pos)` + +Boolean function, true if the block ticks randomly. + +### `blocks_movement(pos)` + +Boolean function, true if block at position blocks movement. + +### `block_sound(pos)` + +Returns the name of sound type made by the block at position. One of: + +* `wood` +* `gravel` +* `grass` +* `stone` +* `metal` +* `glass` +* `wool` +* `sand` +* `snow` +* `ladder` +* `anvil` +* `slime` +* `sea_grass` +* `coral` + +### `material(pos)` + +Returns the name of material of the block at position. very useful to target a group of blocks. One of: + +* `air` +* `void` +* `portal` +* `carpet` +* `plant` +* `water_plant` +* `vine` +* `sea_grass` +* `water` +* `bubble_column` +* `lava` +* `snow_layer` +* `fire` +* `redstone_bits` +* `cobweb` +* `redstone_lamp` +* `clay` +* `dirt` +* `grass` +* `packed_ice` +* `sand` +* `sponge` +* `wood` +* `wool` +* `tnt` +* `leaves` +* `glass` +* `ice` +* `cactus` +* `stone` +* `iron` +* `snow` +* `anvil` +* `barrier` +* `piston` +* `coral` +* `gourd` +* `dragon_egg` +* `cake` + +### `map_colour(pos)` + +Returns the map colour of a block at position. One of: + +* `air` +* `grass` +* `sand` +* `wool` +* `tnt` +* `ice` +* `iron` +* `foliage` +* `snow` +* `clay` +* `dirt` +* `stone` +* `water` +* `wood` +* `quartz` +* `adobe` +* `magenta` +* `light_blue` +* `yellow` +* `lime` +* `pink` +* `gray` +* `light_gray` +* `cyan` +* `purple` +* `blue` +* `brown` +* `green` +* `red` +* `black` +* `gold` +* `diamond` +* `lapis` +* `emerald` +* `obsidian` +* `netherrack` +* `white_terracotta` +* `orange_terracotta` +* `magenta_terracotta` +* `light_blue_terracotta` +* `yellow_terracotta` +* `lime_terracotta` +* `pink_terracotta` +* `gray_terracotta` +* `light_gray_terracotta` +* `cyan_terracotta` +* `purple_terracotta` +* `blue_terracotta` +* `brown_terracotta` +* `green_terracotta` +* `red_terracotta` +* `black_terracotta` +# Iterating over larger areas of blocks + +These functions help scan larger areas of blocks without using generic loop functions, like nested `loop`. + +### `scan(cx, cy, cz, dx, dy, dz, px?, py?, pz?, expr)` + +Evaluates expression over area of blocks defined by its center (`cx, cy, cz`), expanded in all directions +by `dx, dy, dz` blocks, or optionally in negative with `d` coords, and `p` coords in positive values. `expr` +receives `_x, _y, _z` as coords of current analyzed block and `_`, which represents the block itself. + +### `volume(x1, y1, z1, x2, y2, z2, expr)` + +Evaluates expression for each block in the area, the same as the `scan`function, but using two opposite corners of +the rectangular cuboid. Any corners can be specified, its like you would do with `/fill` command. + +### `neighbours(x, y, z), neighbours(block), neighbours(l(x,y,z))` + +Returns the list of 6 neighbouring blocks to the argument. Commonly used with other loop functions like `for`. + +
+for(neighbours(x,y,z),air(_)) => 4 // number of air blocks around a block
+
+ +### `rect(cx, cy, cz, dx?, dy?, dz?, px?, py?, pz?)` + +returns an iterator, just like `range` function that iterates over rectangular cubarea of blocks. If only center +point is specified, it iterates over 27 blocks. If `d` arguments are specified, expands selection of respective +number of blocks in each direction. If `p` arguments are specified, it uses `d` for negative offset, and `p` for positive. + +### `diamond(cx, cy, cz, radius?, height?)` + +Iterates over a diamond like area of blocks. With no radius and height, its 7 blocks centered around the middle +(block + neighbours). With a radius specified, it expands shape on x and z coords, and with a custom height, on y. +Any of these can be zero as well. radius of 0 makes a stick, height of 0 makes a diamond shape pad. +# Entity API + +## Entity Selection + +Entities have to be fetched before using them. Entities can also change their state between calls to the script if +game happens either in between separate calls to the programs, or if the program calls `game_tick` on its own. +In this case - entities would need to be re-fetched, or the code should account for entities getting dead. + +### `player(), player(type), player(name)` + +With no arguments, it returns the calling player or the player closest to the caller. Note that the main context +will receive `p` variable pointing to this player. With `type` or `name` specified it will try first to match a type, +returning a list of players matching a type, and if this fails, will assume its player name query retuning player with +that name, or `null` if no player was found. With `'all'`, list of all players in the game, in all dimensions, so end +user needs to be cautious, that you might be referring to wrong blocks and entities around the player in question. +With `type = '*'` it returns all players in caller dimension, `'survival'` returns all survival and adventure players, +`'creative'` returns all creative players, `'spectating'` returns all spectating players, and `'!spectating'`, +all not-spectating players. If all fails, with `name`, the player in question, if is logged in. + +### `entity_id(uuid), entity_id(id)` + +Fetching entities wither by their ID obtained via `entity ~ 'id'`, which is unique for a dimension and current world +run, or by UUID, obtained via `entity ~ 'uuid'`. It returns null if no such entity is found. Safer way to 'store' +entities between calls, as missing entities will be returning `null`. Both calls using UUID or numerical ID are `O(1)`, +but obviously using UUIDs takes more memory and compute. + +### `entity_list(type)` + +Returns global lists of entities in the current dimension of a specified type. Currently the following +selectors are available: + +* `*`: all entites +* `living` +* `items` +* `players` +* `!players` + +### `entity_area(type, cx, cy, cz, dx, dy, dz)` + +Returns entities of a specified type in an area centered on `cx, cy, cz` and at most `dx, dy, dz` blocks away from +the center point. Uses same selectors as `entities_list` + +### `entity_selector(selector)` + +Returns entities satisfying given vanilla entity selector. Most complex among all the methods of selecting entities, +but the most capable. Selectors are cached so should be as fast as other methods of selecting entities. + +### `spawn(name, pos, nbt?)` + +Spawns and places an entity in world, like `/summon` vanilla command. Requires a position to spawn, and optional +extra nbt data to merge with the entity. What makes it different from calling `run('summon ...')`, is the fact that +you get the entity back as a return value, which is swell. + +## Entity Manipulation + +Unlike with blocks, that use plethora of vastly different querying functions, entities are queried with `query` +function and altered via `modify` function. Type of information needed or values to be modified are different for +each call. + +Using `~` (in) operator is an alias for `query`. Especially useful if a statement has no arguments, +which in this case can be radically simplified + +
+query(p, 'name') <=> p ~ 'name'     // much shorter and cleaner
+query(p, 'holds', 'offhand') <=> p ~ l('holds', 'offhand')    // not really but can be done
+
+ +### `query(e,'removed')` + +Boolean. True if the entity is removed + +### `query(e,'id')` + +Returns numerical id of the entity. Most efficient way to keep track of entites in a script. +Ids are only unique within current game session (ids are not preserved between restarts), +and dimension (each dimension has its own ids which can overlap. + +### `query(e,'uuid')` + +Returns UUID (unique id) of the entity. Can be used to access entities with the other vanilla commands and +remains unique regardless of the dimension, and is preserved between game restarts. Apparently players cannot be +accessed via UUID, but name instead. + +
+map(entities_area('*',x,y,z,30,30,30),run('kill '+query(_,'id'))) // doesn't kill the player
+
+ +### `query(e,'pos')` + +Triple of entity position + +### `query(e,'location')` + +Quin-tuple of entity position (x, y, and z coords), and rotation (yaw, pitch) + +### `query(e,'x'), query(e,'y'), query(e,'z')` + +Respective entity coordinate + +### `query(e,'pitch'), query(e,'yaw')` + +Pitch and Yaw or where entity is looking. + +### `query(e,'look')` + +Returns a 3d vector where the entity is looking. + +### `query(e,'motion')` + +Triple of entity motion vector, `l(motion_x, motion_y, motion_z)` + +### `query(e,'motion_x'), query(e,'motion_y'), query(e,'motion_z')` + +Respective component of the motion vector + +### `query(e,'name'), query(e,'custom_name'), query(e,'type')` + +String of entity name + +
query(e,'name')  => Leatherworker
+query(e,'custom_name')  => null
+query(e,'type')  => villager
+
+ +### `query(e,'is_riding')` + +Boolean. True if riding another entity. + +### `query(e,'is_ridden')` + +Boolean. True if another entity is riding it. + +### `query(e,'passengers')` + +List of entities riding the entity. + +### `query(e,'mount')` + +Entity that `e` rides. + +### `query(e,'tags')` + +List of entity tags. + +### `query(e,'has_tags',tag)` + +Boolean, True if the entity is marked with `tag`. + +### `query(e,'is_burning')` + +Boolean, True if the entity is burning. + +### `query(e,'fire')` + +Number of remaining ticks of being on fire. + +### `query(e,'silent')` + +Boolean, True if the entity is silent. + +### `query(e,'gravity')` + +Boolean, True if the entity is affected by gravity, like most entities do. + +### `query(e,'immune_to_fire')` + +Boolean, True if the entity is immune to fire. + +### `query(e,'dimension')` + +Name of the dimension entity is in. + +### `query(e,'height')` + +Height of the entity. + +### `query(e,'width')` + +Width of the entity. + +### `query(e,'eye_height')` + +Eye height of the entity. + +### `query(e,'age')` + +Age, in ticks, of the entity, i.e. how long it existed. + +### `query(e,'breeding_age')` + +Breeding age of passive entity, in ticks. If negative it it time to adulthood, if positive, breeding cooldown + +### `query(e,'despawn_timer')` + +For living entities - the number of ticks they fall outside of immediate player presence. + +### `query(e,'item')` + +The item triple (name, count, nbt) if its an item entity, `null` otherwise + +### `query(e,'count')` + +Number of items in a stack from item entity, `null` otherwise + +### `query(e,'pickup_delay')` + +Retrieves pickup delay timeout for an item entity, `null` otherwise + +### `query(e,'is_baby')` + +Boolean, true if its a baby. + +### `query(e,'target')` + +Returns mob's attack target or null if none or not applicable. + +### `query(e,'home')` + +Returns creature's home position or null if none or not applicable. + +### `query(e,'sneaking')` + +Boolean, true if entity is sneaking. + +### `query(e,'sprinting')` + +Boolean, true if entity is sprinting. + +### `query(e,'swimming')` + +Boolean, true if entity is swimming. + +### `query(e,'jumping')` + +Boolean, true if entity is jumping. + +### `query(e,'gamemode')` + +String with gamemode, or `null` if not a player. + +### `query(e,'gamemode_id')` + +Good'ol gamemode id, or null if not a player. + +### `query(e,'player_type')` + +Returns `null` if the argument is not a player, otherwise: + +* `singleplayer`: for singleplayer game +* `multiplayer`: for players on a dedicated server +* `lan_host`: for singleplayer owner that opened the game to LAN +* `lan_player`: for all other players that connected to a LAN host +* `fake`: any carpet-spanwed fake player +* `shadow`: any carpet-shadowed real player +* `realms`: ? + +### `query(e,'permission_level')` + +Player's permission level, or `null` if not applicable for this entity. + +### `query(e,'effect',name?)` + +Without extra arguments, it returns list of effect active on a living entity. Each entry is a triple of short +effect name, amplifier, and remaining duration. With an argument, if the living entity has not that potion active, +returns `null`, otherwise return a tuple of amplifier and remaining duration. + +
+query(p,'effect')  => [[haste, 0, 177], [speed, 0, 177]]
+query(p,'effect','haste')  => [0, 177]
+query(p,'effect','resistance')  => null
+
+ +### `query(e,'health')` + +Number indicating remaining entity health, or `null` if not applicable. + +### `query(e,'holds',slot?)` + +Returns triple of short name, stack count, and NBT of item held in `slot`. Available options for `slot` are: + +* `mainhand` +* `offhand` +* `head` +* `chest` +* `legs` +* `feet` + +If `slot` is not specified, it defaults to the main hand. + +### `query(e,'selected_slot')` + +Number indicating the selected slot of entity inventory. Currently only applicable to players. + +### `query(e,'facing', order?)` + +Returns where the entity is facing. optional order (number from 0 to 5, and negative), indicating primary directions +where entity is looking at. From most prominent (order 0) to opposite (order 5, or -1) + +### `query(e,'trace', reach?, options?...)` + +Returns the result of ray tracing from entity perspective, indicating what it is looking at. Default reach is 4.5 +blocks (5 for creative players), and by default it traces for blocks and entities, identical to player attack tracing +action. This can be customized with `options`, use 'blocks' to trace for blocks, 'liquids' to include liquid blocks +as possible results, and 'entities' to trace entities. Any combination of the above is possible. When tracing +entities and blocks, blocks will take over the priority even if transparent or non-colliding +(aka fighting chickens in tall grass). + +Regardless of the options selected, the result could be `null` if nothing is in reach, entity, if look targets an +entity, and block value if block is in reach. + +### `query(e,'nbt',path?)` + +Returns full NBT of the entity. If path is specified, it fetches only that portion of the NBT, that corresponds to the +path. For specification of `path` attribute, consult vanilla `/data get entity` command. + +Note that calls to `nbt` are considerably more expensive comparing to other calls in Minecraft API, and should only +be used when there is no other option. Returned value is of type `nbt`, which can be further manipulated with nbt +type objects via `get, put, has, delete`, so try to use API calls first for that. + +## Entity Modification + +Like with entity querying, entity modifications happen through one function. Most position and movements modifications +don't work currently on players as their position is controlled by clients. + +Currently there is no ability to modify NBT directly, but you could always use `run('data modify entity` + +### `modify(e,'remove')` + +Removes (not kills) entity from the game. + +### `modify(e,'kill')` + +Kills the entity. + +### `modify(e, 'pos', x, y, z), modify(e, 'pos', l(x,y,z) )` + +Moves the entity to a specified coords. + +### `modify(e, 'location', x, y, z, yaw, pitch), modify(e, 'location', l(x, y, z, yaw, pitch) )` + +Changes full location vector all at once. + +### `modify(e, 'x', x), modify(e, 'y', y), modify(e, 'z', z)` + +Moves the entity in.... one direction. + +### `modify(e, 'pitch', pitch), modify(e, 'yaw', yaw)` + +Changes entity's pitch or yaw. + +### `modify(e, 'move', x, y, z), modify(e, 'move', l(x,y,z) )` + +Moves the entity by a vector from its current location. + +### `modify(e, 'motion', x, y, z), modify(e, 'motion', l(x,y,z) )` + +Sets the motion vector (where and how much entity is moving). + +### `modify(e, 'motion_z', x), modify(e, 'motion_y', y), modify(e, 'motion_z', z)` + +Sets the corresponding component of the motion vector. + +### `modify(e, 'accelerate', x, y, z), modify(e, 'accelerate', l(x, y, z) )` + +Adds a vector to the motion vector. Most realistic way to apply a force to an entity. + +### `modify(e, 'custom_name'), modify(e, 'custom_name', name )` + +### `modify(e, 'age', number)` + +Modifies entity's internal age counter. Fiddling with this will affect directly behaviours of complex +entities, so use it with caution. + +### `modify(e, 'pickup_delay', number)` + +### `modify(e, 'breeding_age', number)` + +### `modify(e, 'despawn_timer', number)` + +Sets a custom despawn timer value. + +### `modify(e, 'dismount')` + +Dismounts riding entity. + +### `modify(e, 'mount', other)` + +Mounts the entity to the `other`. + +### `modify(e, 'drop_passengers')` + +Shakes off all passengers. + +### `modify(e, 'mount_passengers', passenger, ? ...), modify(e, 'mount_passengers', l(passengers) )` + +Mounts on all listed entities on `e`. + +### `modify(e, 'tag', tag, ? ...), modify(e, 'tag', l(tags) )` + +Adds tag / tags to the entity. + +### `modify(e, 'clear_tag', tag, ? ...), modify(e, 'clear_tag', l(tags) )` + +Removes tag from entity. + +### `modify(e, 'talk')` + +Make noises. + +### `modify(e, 'ai', boolean)` + +If called with `false` value, it will disable AI in the mob. `true` will enable it again. + +### `modify(e, 'no_clip', boolean)` + +Sets if the entity obeys any collisions, including collisions with the terrain and basic physics. Not affecting +players, since they are controlled client side + +### `modify(e, 'effect', name, duration?, amplifier?, show_particles?, show_icon?)` + +Applies status effect to the living entity. Takes several optional parameters, which default to `0`, `true` +and `true`. If no duration is specified, or it is null or 0, the effect is removed. + +### `modify(e, 'home', null), modify(e, 'home', block, distance?), modify(e, 'home', x, y, z, distance?)` + +Sets AI to stay around the home position, within `distance` blocks from it. `distance` defaults to 16 blocks. +`null` removes it. _May_ not work fully with mobs that have this AI built in, like Villagers. + +## Entity Events + +There is a number of events that happen to entities that you can attach your own code to in the form of event handlers. +The event handler is any function that runs in your package that accepts certain expected parameters, which you can +expand with your own arguments. When it comes to the moment when the given command needs to be executed, it does so +providing that number of arguments it accepts is equal number of event arguments, and extra arguments passed when +defining the callback with `entity_event` + +The following events can be handled by entities. + +* `'on_tick'`: executes every tick right before entity is ticked in the game. Required arguments: `entity` +* `'on_death'`: executes once when a living entity dies. Required arguments: `entity, reason` +* `'on_removed'`: execute once when an entity is removed. Required arguments: `entity` +* `'on_damaged'`: executed every time a living entity is about to receive damage. +Required arguments: `entity, amount, source, attacking_entity` + +It doesn't mean that all entity types will have a chance to execute a given event, but entities will not error +when you will attach inapplicable event to it. + +### `entity_event(e, event, call_name, args...)` + +Attaches specific function from the current package to be called upon the `event`, with extra `args` curried to the +original required arguments for the event handler + +
+protect_villager(entity, amount, source, source_entity, healing_player) ->
+(
+   if(source_entity && source_entity~'type' != 'player',
+      modify(entity, 'health', amount + entity~'health' );
+      particle('end_rod', pos(entity)+l(0,3,0));
+      print(str('%s healed thanks to %s', entity, healing_player))
+   )
+);
+__on_player_interacts_with_entity(player, entity, hand) ->
+(
+   if (entity~'type' == 'villager',
+      entity_event(entity, 'on_damage', 'protect_villager', player~'name')
+   )
+)
+
+ +In this case this will protect a villager from entity damage (zombies, etc.) except players by granting all the +health back to the villager after being harmed. +# Inventory and Items API + +## Manipulating inventories of blocks and entities + +Most functions in this category require inventory as the first argument. Inventory could be specified by an entity, +or a block, or position (three coordinates) of a potential block with inventory. Player enderchest inventory require +two arguments, keyword `'enderchest'`, followed by the player entity argument. If the entity or a block doesn't have +an inventory, they typically do nothing and return null. + +Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item. +Manipulating of the nbt data can be costly, but retrieving them from the tuple to match other aspects is cheap + +### `stack_limit(item)` + +Returns number indicating what is the stack limit for the item. Its typically 1 (non-stackable), 16 (like buckets), +or 64 - rest. It is recommended to consult this, as other inventory API functions ignore normal stack limits, and +it is up to the programmer to keep it at bay. As of 1.13, game checks for negative numbers and setting an item to +negative is the same as empty. + +
+stack_limit('wooden_axe') => 1
+stack_limit('ender_pearl') => 16
+stack_limit('stone') => 64
+
+ +### `item_category(item)` + +Returns the string representing the category of a given item, like `building_blocks`, `combat`, or `tools`. + +
+item_category('wooden_axe') => tools
+item_category('ender_pearl') => misc
+item_category('stone') => building_blocks
+
+ +### `inventory_size(inventory)` + +Returns the size of the inventory for the entity or block in question. Returns null if the block or entity don't +have an inventory + +
+inventory_size(player()) => 41
+inventory_size('enderchest', player()) => 27 // enderchest
+inventory_size(x,y,z) => 27 // chest
+inventory_size(block(pos)) => 5 // hopper
+
+ +### `inventory_has_items(inventory)` + +Returns true, if the inventory is not empty, false if it is empty, and null, if its not an inventory. + +
    inventory_has_items(player()) => true
+    inventory_has_items(x,y,z) => false // empty chest
+    inventory_has_items(block(pos)) => null // stone
+
+ +### `inventory_get(inventory, slot)` + +Returns the item in the corresponding inventory slot, or null if slot empty or inventory is invalid. You can use +negative numbers to indicate slots counted from 'the back'. + +
+inventory_get(player(), 0) => null // nothing in first hotbar slot
+inventory_get(x,y,z, 5) => ['stone', 1, {}]
+inventory_get(player(), -1) => ['diamond_pickaxe', 1, {Damage:4}] // slightly damaged diamond pick in the offhand
+
+ +### `inventory_set(inventory, slot, count, item?, nbt?)` + +Modifies or sets a stack in inventory. specify count 0 to empty the slot. If item is not specified, keeps existing +item, just modifies the count. If item is provided - replaces current item. If nbt is provided - adds a tag to the +stack at slot. Returns previous stack in that slot. + +
+inventory_set(player(), 0, 0) => ['stone', 64, {}] // player had a stack of stone in first hotbar slot
+inventory_set(player(), 0, 6) => ['diamond', 64, {}] // changed stack of diamonds in player slot to 6
+inventory_set(player(), 0, 1, 'diamond_axe','{Damage:5}') => null //added slightly damaged pick to first player slot
+
+ +### `inventory_find(inventory, item, start_slot?, ), inventory_find(inventory, null, start_slot?)` + +Finds the first slot with a corresponding item in the inventory, or if queried with null: the first empty slot. +Returns slot number if found, or null otherwise. Optional start_slot argument allows to skip all preceeding slots +allowing for efficient (so not slot-by-slot) inventory search for items. + +
+inventory_find(player(), 'stone') => 0 // player has stone in first hotbar slot
+inventory_find(player(), null) => null // player's inventory has no empty spot
+while( (slot = inventory_find(p, 'diamond', slot)) != null, 41, drop_item(p, slot) )
+    // spits all diamonds from player inventory wherever they are
+inventory_drop(x,y,z, 0) => 64 // removed and spawned in the world a full stack of items
+
+ +### `inventory_remove(inventory, item, amount?)` + +Removes amount (defaults to 1) of item from inventory. If the inventory doesn't have the defined amount, nothing +happens, otherwise the given amount of items is removed wherever they are in the inventory. Returns boolean +whether the removal operation was successful. Easiest way to remove a specific item from player inventory +without specifying the slot. + +
+inventory_remove(player(), 'diamond') => 1 // removed diamond from player inventory
+inventory_remove(player(), 'diamond', 100) => 0 // player doesn't have 100 diamonds, nothing happened
+
+ +### `drop_item(inventory, slot, amount?, )` + +Drops the items from indicated inventory slot, like player that Q's an item or villager, that exchanges food. +You can Q items from block inventories as well. default amount is 0 - which is all from the slot. +NOTE: hoppers are quick enough to pick all the queued items from their inventory anyways. +Returns size of the actual dropped items. + +
+inventory_drop(player(), 0, 1) => 1 // Q's one item on the ground
+inventory_drop(x,y,z, 0) => 64 // removed and spawned in the world a full stack of items
+
+# Scarpet events system + +Provides the ability to execute specific function whenever an event occurs. The functions to be registered need to +conform with the arguments to the event specification. When loading module functions, each function that starts +with `__on_...` and has the required arguments, will be bound automatically. In case of player specific modules, +all player action events will be directed to the appropriate player space, and all tick events will be executed in +the global context, so its not a good idea to mix these two, so use either of these, or use commands to call tick +events directly, or handle player specific data inside a module. In near future using global events +(on_tick, on_chunk_generated) will be not allowed in player scoped apps. + +### Event list + +Here is a list of events that can be handled by scarpet. This list includes prefixes required by modules to autoload +them, but you can add any function to any event if it accepts required number of parameters: + +
+__on_tick()         // can access blocks and entities in the overworld
+__on_tick_nether()  // can access blocks and entities in the nether
+__on_tick_ender()   // can access blocks and entities in the end
+__on_chunk_generated(x,z) // called after a chunk is promoted to the full chunk,
+                          // prodiving lowest x and z coords in the chunk
+                          // event will not work with optifine installed in the game
+// player specific callbacks
+__on_player_uses_item(player, item_tuple, hand)  // right click action
+__on_player_releases_item(player, item_tuple, hand)  // client action (e.g. bow)
+__on_player_finishes_using_item(player, item_tuple, hand))  // server action (e.g. food), called item is from before it is used.
+__on_player_clicks_block(player, block, face)  // left click attack on a block
+__on_player_breaks_block(player, block) // called after block is broken (the caller receives previous blockstate)
+__on_player_right_clicks_block(player, item_tuple, hand, block, face, hitvec)  // player right clicks block with anything
+__on_player_interacts_with_block(player, hand, block, face, hitvec)  //right click on a block resulted in activation of said block
+__on_player_places_block(player, item_tuple, hand, block) // player have just placed the block.
+__on_player_interacts_with_entity(player, entity, hand)
+__on_player_attacks_entity(player, entity)
+__on_player_rides(player, forward, strafe, jumping, sneaking)
+__on_player_jumps(player)
+__on_player_deploys_elytra(player)
+__on_player_wakes_up(player)
+__on_player_starts_sneaking(player)
+__on_player_stops_sneaking(player)
+__on_player_starts_sprinting(player)
+__on_player_stops_sprinting(player)
+__on_player_drops_item(player)
+__on_player_drops_stack(player)
+__on_statistic(player, category, event, value) // player statistic changes
+
+ +### `/script event` command + +used to display current events and bounded functions. use `add_to` ro register new event, or `remove_from` to +unbind a specific function from an event. Function to be bounded to an event needs to have the same number of +parameters as the action is attempting to bind to (see list above). All calls in modules loaded via `/script load` +that have functions listed above will be automatically bounded and unbounded when script is unloaded. +# Auxiliary aspects + +Collection of other methods that control smaller, yet still important aspects of the game + +## Sounds + +### `sound(name, pos, volume?, pitch?)` + +Plays a specific sound `name`, at block or position `pos`, with optional `volume` and modified `pitch`. `pos` can be +either a block, triple of coords, or a list of thee numbers. Uses the same options as a corresponding `playsound` command. + +## Particles + +### `particle(name, pos, count?. spread?, speed?, playername?)` + +Renders a cloud of particles `name` centered around `pos` position, by default `count` 10 of them, default `speed` +of 0, and to all players nearby, but these options can be changed via optional arguments. Follow vanilla `/particle` +command on details on those options. Valid particle names are +for example `'angry_villager', 'item diamond', 'block stone', 'dust 0.8 0.1 0.1 4'`. + +### `particle_line(name, pos, pos2, density?)` + +Renders a line of particles from point `pos` to `pos2` with supplied density (defaults to 1), which indicates how far +apart you would want particles to appear, so `0.1` means one every 10cm. + +### `particle_rect(name, pos, pos2, density?)` + +Renders a cuboid of particles between point `pos` to `pos2` with supplied density. + +## Markers + +### `create_marker(text, pos, rotation?, block?)` + +Spawns a (permanent) marker entity with text or block at position. Returns that entity for further manipulations. +Unloading the app that spawned them will cause all the markers from the loaded portion of the world to be removed. +Also - if the game loads that marker in the future and the app is not loaded, it will be removed as well. + +### `remove_all_markers()` + +Removes all scarpet markers from the loaded portion of the world created by this app, in case you didn't want to do + the proper cleanup. + +## System function + +### `nbt(expr)` + +Treats the argument as a nbt serializable string and returns its nbt value. In case nbt is not in a correct nbt +compound tag format, it will return `null` value. + +Consult section about container operations in `Expression` to learn about possible operations on nbt values. + +### `escape_nbt(expr)` + +Excapes all the special characters in the string or nbt tag and returns a string that can be stored in nbt directly +as a string value. + +### `print(expr)` + +Displays the result of the expression to the chat. Overrides default `scarpet` behaviour of sending everyting to stderr. + +### `logger(expr)` + +Prints the message to system logs, and not to chat. + +### `run(expr)` + +Runs a vanilla command from the string result of the `expr` and returns its success count + +
+run('fill 1 1 1 10 10 10 air') -> 123 // 123 block were filled, this operation was successful 123 times out of a possible 1000 blocks volume
+run('give @s stone 4') -> 1 // this operation was successful once
+
+ +### `save()` + +Performs autosave, saves all chunks, player data, etc. Useful for programs where autosave is disabled due to +performance reasons and saves the world only on demand. + +### `load_app_data(), load_app_data(file)` + +Loads the app data associated with the app from the world /scripts folder. Without argument returns the memory +managed and buffered / throttled NBT tag. With a file name - reads explicitly a file with that name from the +scripts folder. + +You can use app data to save non-vanilla information separately from the world and other scripts. + +### `store_app_data(tag), store_app_data(tag, file)` + +Stores the app data associated with the app from the world /scripts folder. With the `file` parameter saves +immediately and with every call, without `file` parameter, it may take up to 10 seconds for the output file +to sync preventing flickering in case this tag changes frequently. It will be synced when server closes. + +### `tick_time()` + +Returns game tick counter. Can be used to run certain operations every n-th ticks, or to count in-game time + +### `game_tick(mstime?)` + +Causes game to run for one tick. By default runs it and returns control to the program, but can optionally +accept expected tick length, in milliseconds. You can't use it to permanently change the game speed, but setting +longer commands with custom tick speeds can be interrupted via `/script stop` command + +
+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)` + +Evaluates the expression `expr` with different dimension execution context. `smth` can be an entity, +world-localized block, so not `block('stone')`, or a string representing a dimension like: + `'nether'`, `'the_nether'`, `'end'` or `'overworld'`, etc. + +### `schedule(delay, function, args...)` + +Schedules a user defined function to run with a specified `delay` ticks of delay. Scheduled functions run at the end +of the tick, and they will run in order they were scheduled. + +### `statistic(player, category, entry)` + +Queries in-game statistics for certain values. Categories include: + +* `mined`: blocks mined +* `crafted`: items crafted +* `used`: items used +* `broken`: items broken +* `picked_up`: items picked up +* `dropped`: items dropped +* `killed`: mobs killed +* `killed_by`: blocks mined +* `custom`: various random stats + +For the options of `entry`, consult your statistics page, or give it a guess. + +The call will return `null` if the statistics options are incorrect, or player didn't get these in their history. +If the player encountered the statistic, or game created for him empty one, it will return a number. +Scarpet will not affect the entries of the statistics, even if it is just creating empty ones. With `null` response +it could either mean your input is wrong, or statistic has effectively a value of `0`. + +### `plop(pos, what)` + +Plops a structure or a feature at a given `pos`, so block, triple position coordinates or a list of coordinates. +To `what` gets plopped and exactly where it often depends on the feature or structure itself. For example, all +structures are chunk aligned, and often span multiple chunks. Repeated calls to plop a structure in the same chunk +would result either in the same structure generated on top of each other, or with different state, but same position. +Most structures generate at specific altitudes, which are hardcoded, or with certain blocks around them. API will +cancel all extra position / biome / random requirements for structure / feature placement, but some hardcoded +limitations may still cause some of structures/features not to place. Some features require special blocks to be +present, like coral -> water or ice spikes -> snow block, and for some features, like fossils, placement is all sorts +of messed up. This can be partially avoided for structures by setting their structure information via `set_structure`, +which sets it without looking into world blocks, and then use `plop` to fill it with blocks. This may, or may not work. + +All generated structures will retain their properties, like mob spawning, however in many cases the world / dimension +itself has certain rules to spawn mobs, like plopping a nether fortress in the overworld will not spawn nether mobs, +because nether mobs can spawn only in the nether, but plopped in the nether - will behave like a valid nether fortress. + +`plop` will not use world random number generator to generate structures and features, but its own. This has a benefit +that they will generate properly randomly, not the same time every time. + +Structure list: + +* `monument`: Ocean Monument. Generates at fixed Y coordinate, surrounds itself with water. +* `fortress`: Nether Fortress. Altitude varies, but its bounded by the code. +* `mansion`: Woodland Mansion +* `jungle_temple`: Jungle Temple +* `desert_temple`: Desert Temple. Generates at fixed Y altitude. +* `end_city`: End City with Shulkers +* `igloo`: Igloo +* `shipwreck`: Shipwreck, version1? +* `shipwreck2`: Shipwreck, version2? +* `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. +* `mineshaft_mesa`: A Mesa (Badlands) version of a mineshaft. +* `village`: Plains, oak village. +* `village_desert`: Desert, sandstone village. +* `village_savanna`: Savanna, acacia village. +* `village_taiga`: Taiga, spruce village. +* `village_snowy`: Resolute, Canada. + +Feature list: + +* `oak` +* `oak_beehive`: oak with a hive (1.15+). +* `oak_large`: oak with branches. +* `oak_large_beehive`: oak with branches and a beehive (1.15+). +* `birch` +* `birch_large`: tall variant of birch tree. +* `shrub`: low bushes that grow in jungles. +* `shrub_acacia`: low bush but configured with acacia (1.14 only) +* `shrub_snowy`: low bush with white blocks (1.14 only) +* `jungle`: a tree +* `jungle_large`: 2x2 jungle tree +* `spruce` +* `spruce_large`: 2x2 spruce tree +* `pine`: spruce with minimal leafage (1.15+) +* `pine_large`: 2x2 spruce with minimal leafage (1.15+) +* `spruce_matchstick`: see 1.15 pine (1.14 only). +* `spruce_matchstick_large`: see 1.15 pine_large (1.14 only). +* `dark_oak` +* `acacia` +* `oak_swamp`: oak with more leaves and vines. +* `well`: desert well +* `grass`: a few spots of tall grass +* `grass_jungle`: little bushier grass feature (1.14 only) +* `lush_grass`: grass with patchy ferns (1.15+) +* `tall_grass`: 2-high grass patch (1.15+) +* `fern`: a few random 2-high ferns +* `cactus`: random cacti +* `dead_bush`: a few random dead bushi +* `fossils`: underground fossils, placement little wonky +* `mushroom_brown`: large brown mushroom. +* `mushroom_red`: large red mushroom. +* `ice_spike`: ice spike. Require snow block below to place. +* `glowstone`: glowstone cluster. Required netherrack above it. +* `melon`: a patch of melons +* `melon_pile`: a pile of melons (1.15+) +* `pumpkin`: a patch of pumpkins +* `pumpkin_pile`: a pile of pumpkins (1.15+) +* `sugarcane` +* `lilypad` +* `dungeon`: Dungeon. These are hard to place, and fail often. +* `iceberg`: Iceberg. Generate at sea level. +* `iceberg_blue`: Blue ice iceberg. +* `lake` +* `lava_lake` +* `end_island` +* `chorus`: Chorus plant. Require endstone to place. +* `sea_grass`: a patch of sea grass. Require water. +* `sea_grass_river`: a variant. +* `kelp` +* `coral_tree, coral_mushroom, coral_claw`: various coral types, random color. +* `coral`: random coral structure. Require water to spawn. +* `sea_pickle` +* `boulder`: A rocky, mossy formation from a giant taiga biome. Doesn't update client properly, needs relogging. +# `/script run` command + +Primary way to input commands. The command executes in the context, position, and dimension of the executing player, +commandblock, etc... The command receives 4 variables, `x`, `y`, `z` and `p` indicating position and +the executing entity of the command. You will receive tab completion suggestions as you type your code suggesting +functions and global variables. It is advisable to use `/execute in ... at ... as ... run script run ...` or similar, +to simulate running commands in a different scope. + +# `/script load / unload (global?)`, `/script in ` commands + +`load / unload` commands allow for very conventient way of writing your code, providing it to the game and +distribute with your worlds without the need of use of commandblocks. Just place your scarpet code in the +/scripts folder of your world files and make sure it ends with `.sc` extension. The good thing about editing that +code is that you can no only use normal editing without the need of marking of newlines, +but you can also use comments in your code. + +a comment is anything that starts with a double slash, and continues to the end of the line: + +
+foo = 1;
+//This is a comment
+bar = 2;
+// This never worked, so I commented it out
+// baz = foo()
+
+ +### `/script load/unload (?global)` + +Loading operation will load that script code from disk and execute it right away. You would probably use it to load +some stored procedures to be used for later. To reload the module, just type `/script load` again. Reloading removes +all the current global state (globals and functions) that were added later by the module. + +Loading a module, if it contains a `__command()` method, will attempt to registed a command with that app name, +and register all public (no underscore) functions available in the module as subcommands. It will also bind specific +events to the event system (check Events section for details). + +Loaded apps have the ability to store and load external files, especially their persistent tag state. For that +check `load_app_data` and `store_app_data` functions. + +If an app defines `__config` method, and that method returns a map, it will be used to apply custom settings +for this app. Currently the following options are supported: + +* `scope`: default scope for global variables for the app, Default is 'player' which means that globals and defined +functions will be unique for each player so that apps for each player will run in isolation. This is useful in +tool-like applications. Another option is 'global' which shares global state for all runs on the server - applicable +to 'block' like solutions, where custom behaviours are applied to blocks. +* `stay_loaded`: defaults to false. If true, and `/carpet scriptsAutoload` is turned on, the following apps will +stay loaded after startup. Otherwise, after reading a code, and fetching the config, server will drop them down. +This is to allow to store multiple apps on the server/world and selectively decide which one should be running at +startup. WARNING: all apps will run once at startup anyways, so be aware that their actions that are called +statically, will be performed once anyways. + +Unloading an app removes all of its state from the game, disables commands, and removes bounded events, and +saves its global state. If more cleanup is needed, one can define an `__on_close()` function which will be +executed when the module is unloaded, or server is closing, or crashing. However, there is no need to do that +explicitly for the things mentioned in the previous statement. + +Scripts can be loaded in shared(global) and player mode. Default is player, so all globals and stored functions are +individual for each player, meaning scripts don't need to worry about making sure they store some intermittent +data for each player independently. In global mode - all global values and stored functions are shared among all +players. To access specific player data with commandblocks, use `/execute as (player) run script in (app) run ...`. +To access global/server state, you need to disown the command from any player, so use a commandblock, or any +arbitrary entity: `/execute as @e[type=bat,limit=1] run script in (module) globals` for instance. + +### `/script in ...` + +Allows to run normal /script commands in a specific app, like `run, invoke,..., globals` etc... + +# `/script invoke / invokepoint / invokearea`, `/script globals` commands + +`invoke` family of commands provide convenient way to invoke stored procedures (i.e. functions that has been +defined previously by any running script. To view current stored procedure set, +run `/script globals`(or `/script globals all` to display all functions even hidden ones), to define a new stored +procedure, just run a `/script run function(a,b) -> ( ... )` command with your procedure once, and to forget a +procedure, use `undef` function: `/script run undef('function')` + +### `/script invoke ...` + +Equivalent of running `/script run fun(args, ...)`, but you get the benefit of getting the tab completion of the +command name, and lower permission level required to run these (since player is not capable of running any custom +code in this case, only this that has been executed before by an operator). Arguments will be checked for validity, +and you can only pass simple values as arguments (strings, numbers, or `null` value). Use quotes to include +whitespaces in argument strings. + +Command will check provided arguments with required arguments (count) and fail if not enough or too much +arguments are provided. Operators defining functions are advised to use descriptive arguments names, as these +will be visible for invokers and form the base of understanding what each argument does. + +`invoke` family of commands will tab complete any stored function that does not start with `'_'`, it will still +allow to run procedures starting with `'_'` but not suggest them, and ban execution of any hidden stored procedures, +so ones that start with `'__'`. In case operator needs to use subroutines for convenience and don't want to expose +them to the `invoke` callers, they can use this mechanic. + +
+/script run example_function(const, phrase, price) -> print(const+' '+phrase+' '+price)
+/script invoke example_function pi costs 5
+
+ +### `/script invokepoint ...` + +It is equivalent to `invoke` except it assumes that the first three arguments are coordinates, and provides +coordinates tab completion, with `looking at...` mechanics for convenience. All other arguments are expected +at the end + +### `/script invokearea ...` + +It is equivalent to `invoke` except it assumes that the first three arguments are one set of ccordinates, +followed by the second set of coordinates, providing tab completion, with `looking at...` mechanics for convenience, +followed by any other required arguments + +# `/script scan`, `/script fill` and `/script outline` commands + +These commands can be used to evaluate an expression over an area of blocks. They all need to have specified the +origin of the analyzed area (which is used as referenced (0,0,0), and two corners of an area to analyzed. If you +would want that the script block coordinates refer to the actual world coordinates, use origin of `0 0 0`, or if +it doesn't matter, duplicating coordinates of one of the corners is the easiest way. + +These commands, unlike raw `/script run` are limited by vanilla fill / clone command limit of 32k blocks, which can +be altered with carpet mod's own `/carpet fillLimit` command. + +### `/script scan origin corner corner expr` + +Evaluates expression for each point in the area and returns number of successes (result was positive). Since the +command by itself doesn't affect the area, the effects would be in side effects. + +### `/script fill origin corner corner "expr" (? replace )` + +Think of it as a regular fill command, that sets blocks based on whether a result of the command was successful. +Note that the expression is in quotes. Thankfully string constants in `scarpet` use single quotes. Can be used to +fill complex geometric shapes. + +### `/script outline origin corner corner "expr" (? replace )` + +Similar to `fill` command it evaluates an expression for each block in the area, but in this case setting blocks +where condition was true and any of the neighbouring blocks were evaluated negatively. This allows to create surface +areas, like sphere for example, without resorting to various rounding modes and tricks. + +Here is an example of seven ways to draw a sphere of radius of 32 blocks around 0 100 0: + +
+/script outline 0 100 0 -40 60 -40 40 140 40 "x*x+y*y+z*z <  32*32" white_stained_glass replace air
+/script outline 0 100 0 -40 60 -40 40 140 40 "x*x+y*y+z*z <= 32*32" white_stained_glass replace air
+/script outline 0 100 0 -40 60 -40 40 140 40 "x*x+y*y+z*z <  32.5*32.5" white_stained_glass replace air
+/script fill    0 100 0 -40 60 -40 40 140 40 "floor(sqrt(x*x+y*y+z*z)) == 32" white_stained_glass replace air
+/script fill    0 100 0 -40 60 -40 40 140 40 "round(sqrt(x*x+y*y+z*z)) == 32" white_stained_glass replace air
+/script fill    0 100 0 -40 60 -40 40 140 40 "ceil(sqrt(x*x+y*y+z*z)) == 32" white_stained_glass replace air
+/draw sphere 0 100 0 32 white_stained_glass replace air // fluffy ball round(sqrt(x*x+y*y+z*z)-rand(abs(y)))==32
+
+ +The last method is the one that world edit is using (part of carpet mod). It turns out that the outline method +with `32.5` radius, fill method with `round` function and draw command are equivalent + +# `script stop/script resume` command + +`/script stop` allows to stop execution of any script currently running that calls the `game_tick()` function which +allows the game loop to regain control of the game and process other commands. This will also make sure that all +current and future programs will stop their execution. Execution of all programs will be prevented +until `/script resume` command is called. + +Lets look at the following example. This is a program computes Fibonacci number in a recursive manner: + +
+fib(n) -> if(n<3, 1, fib(n-1)+fib(n-2) ); fib(8)
+
+ +That's really bad way of doing it, because the higher number we need to compute the compute requirements will +rise exponentially with `n`. It takes a little over 50 milliseconds to do fib(24), so above one tick, but about +a minute to do fib(40). Calling fib(40) will not only freeze the game, but also you woudn't be able to interrupt +its execution. We can modify the script as follows + +
+fib(n) -> ( game_tick(50); if(n<3, 1, fib(n-1)+fib(n-2) ) ); fib(40)
+
+ +But this would never finish as such call would finish after `~ 2^40` ticks. To make our computations responsive, +yet able to respond to user interactions, other commands, as well as interrupt execution, we could do the following: + +
+fib(n) -> ( if(n==23, game_tick(50) ); if(n<3, 1, fib(n-1)+fib(n-2) ) ); fib(40)
+
+ +This would slow down the computation of fib(40) from a minute to two, but allows the game to keep continue running +and be responsive to commands, using about half of each tick to advance the computation. Obviously depending on the +problem, and available hardware, certain things can take more or less time to execute, so portioning of work with +calling `gametick` should be balanced in each case separately diff --git a/mergedoc.bat b/mergedoc.bat new file mode 100644 index 00000000..ad269be7 --- /dev/null +++ b/mergedoc.bat @@ -0,0 +1,2 @@ +cat docs/scarpet/language/Overview.md docs/scarpet/language/VariablesAndConstants.md docs/scarpet/language/Operators.md docs/scarpet/language/Math.md docs/scarpet/language/SystemFunctions.md docs/scarpet/language/LoopsAndHigherOrderFunctions.md docs/scarpet/language/FunctionsAndControlFlow.md docs/scarpet/language/Containers.md docs/scarpet/api/Overview.md docs/scarpet/api/BlocksAndWorldAccess.md docs/scarpet/api/BlockIterations.md docs/scarpet/api/Entities.md docs/scarpet/api/Inventories.md docs/scarpet/api/Events.md docs/scarpet/api/Auxiliary.md docs/scarpet/api/ScriptCommand.md > docs/scarpet/Full.md + From 3f9556f9aace50a05779e15094127fc5437e0f27 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 18 Mar 2020 00:47:30 -0300 Subject: [PATCH 8/9] added legacy untracked npp lang specs --- docs/scarpet/Documentation.md | 2 +- .../editors/npp/scarpet_v1.0_notepad++.xml | 64 +++++++++++++++++++ .../editors/npp/scarpet_v1.4_notepad++.xml | 64 +++++++++++++++++++ .../editors/npp/scarpet_v1.5_notepad++.xml | 64 +++++++++++++++++++ .../editors/npp/scarpet_v1.6_notepad++.xml | 64 +++++++++++++++++++ .../java/carpet/script/value/ListValue.java | 6 +- 6 files changed, 260 insertions(+), 4 deletions(-) create mode 100644 docs/scarpet/resources/editors/npp/scarpet_v1.0_notepad++.xml create mode 100644 docs/scarpet/resources/editors/npp/scarpet_v1.4_notepad++.xml create mode 100644 docs/scarpet/resources/editors/npp/scarpet_v1.5_notepad++.xml create mode 100644 docs/scarpet/resources/editors/npp/scarpet_v1.6_notepad++.xml diff --git a/docs/scarpet/Documentation.md b/docs/scarpet/Documentation.md index fcc8dc42..8c57678c 100644 --- a/docs/scarpet/Documentation.md +++ b/docs/scarpet/Documentation.md @@ -1,4 +1,4 @@ -# API Reference +# Scarpet Language Documentation ## Language Specification diff --git a/docs/scarpet/resources/editors/npp/scarpet_v1.0_notepad++.xml b/docs/scarpet/resources/editors/npp/scarpet_v1.0_notepad++.xml new file mode 100644 index 00000000..6945ced9 --- /dev/null +++ b/docs/scarpet/resources/editors/npp/scarpet_v1.0_notepad++.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + ; + - * / % ^ && || > >= < <= == != = += -> <> ! , ~ + + ( + + ) + + + + + + + not fact rand sin cos tan asin acos atan atan2 sinh cosh tanh sec csc sech csch cot acot coth asinh acosh atanh rad deg log log10 log1p sqrt max min abs round floor ceil mandelbrot relu print return exit throw try l join split slice sort sort_key range element put var undef vars if loop map filter first all for while reduce outer bool number str length rand sleep time + block pos solid air liquid flammable transparent opacity blocks_daylight emitted_light light block_light sky_light see_sky hardness blast_resistance top loaded loaded_ep suffocates power ticks_randomly update block_tick random_tick set blocks_movement block_sound material map_colour property player entity_id entity_list entity_area entity_selector query modify scan volume neighbours rect diamond sound particle particle_line particle_rect run save tick_time game_tick plop harvest destroy schedule + euler pi null true false + x y z p + _ _i _a _x _y _z + global_ + __command __on_player_jumps __on_player_deploys_elytra __on_player_wakes_up __on_player_rides __on_player_uses_item __on_player_clicks_block __on_player_right_clicks_block __on_player_breaks_block __on_player_interacts_with_entity __on_player_attacks_entity __on_player_starts_sneaking __on_player_stops_sneaking __on_player_starts_sprinting __on_player_stops_sprinting + $ + 00' 01\ 02' 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/scarpet/resources/editors/npp/scarpet_v1.4_notepad++.xml b/docs/scarpet/resources/editors/npp/scarpet_v1.4_notepad++.xml new file mode 100644 index 00000000..e704c021 --- /dev/null +++ b/docs/scarpet/resources/editors/npp/scarpet_v1.4_notepad++.xml @@ -0,0 +1,64 @@ + + + + + + + + 00// 01 02 03 04 + + + + + + + + ; + - * / % ^ && || > >= < <= == != = += -> <> ! , ~ + + ( + + ) + + + + + + + not fact rand sin cos tan asin acos atan atan2 sinh cosh tanh sec csc sech csch cot acot coth asinh acosh atanh rad deg log log10 log1p sqrt max min abs round floor ceil mandelbrot relu print return exit throw try l join split slice sort sort_key range get put var undef vars if loop map filter first all for while reduce outer type bool number str length rand sleep time + block pos solid air liquid flammable transparent opacity blocks_daylight emitted_light light block_light sky_light see_sky hardness blast_resistance top loaded loaded_ep suffocates power ticks_randomly update block_tick random_tick set blocks_movement block_sound material map_colour property block_properties block_data place_item set_biome player spawn entity_id entity_list entity_area entity_selector query modify stack_limit inventory_size inventory_get inventory_set inventory_find inventory_remove drop_item scan volume neighbours rect diamond sound particle particle_line particle_rect run save tick_time game_tick plop harvest destroy schedule nbt create_marker remove_all_markers + euler pi null true false + x y z p + _ _i _a _x _y _z + global_ + __command __on_player_jumps __on_player_deploys_elytra __on_player_wakes_up __on_player_rides __on_player_uses_item __on_player_clicks_block __on_player_right_clicks_block __on_player_breaks_block __on_player_interacts_with_entity __on_player_attacks_entity __on_player_starts_sneaking __on_player_stops_sneaking __on_player_starts_sprinting __on_player_stops_sprinting __on_tick __on_tick_ender __on_tick_nether + $ + 00' 01\ 02' 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/scarpet/resources/editors/npp/scarpet_v1.5_notepad++.xml b/docs/scarpet/resources/editors/npp/scarpet_v1.5_notepad++.xml new file mode 100644 index 00000000..b013b24d --- /dev/null +++ b/docs/scarpet/resources/editors/npp/scarpet_v1.5_notepad++.xml @@ -0,0 +1,64 @@ + + + + + + + + 00// 01 02 03 04 + 0x + + + + + + + ; + - * / % ^ && || > >= < <= == != = += -> <> ! ~ , : + + ( + + ) + + + + + + + not fact rand sin cos tan asin acos atan atan2 sinh cosh tanh sec csc sech csch cot acot coth asinh acosh atanh rad deg log log10 log1p sqrt max min abs round floor ceil mandelbrot relu print return exit throw try l join split slice sort sort_key range m keys values pairs get put has delete var undef vars if loop map filter first all for while reduce outer type bool number str length rand sleep time profile_expr lower upper title + block pos pos_offset solid air liquid flammable transparent opacity blocks_daylight emitted_light light block_light sky_light see_sky hardness blast_resistance top loaded loaded_ep suffocates power ticks_randomly update block_tick random_tick set blocks_movement block_sound material map_colour property block_properties block_data place_item set_biome biome player spawn entity_id entity_list entity_area entity_selector query modify entity_event stack_limit item_category inventory_size inventory_has_items inventory_get inventory_set inventory_find inventory_remove drop_item scan volume neighbours rect diamond logger sound particle particle_line particle_rect run save tick_time game_tick current_dimension in_dimension plop harvest destroy schedule nbt create_marker remove_all_markers load_app_data store_app_data + euler pi null true false + x y z p + _ _i _a _x _y _z + global_ + __command __config __on_player_jumps __on_player_deploys_elytra __on_player_wakes_up __on_player_rides __on_player_uses_item __on_player_clicks_block __on_player_right_clicks_block __on_player_breaks_block __on_player_interacts_with_entity __on_player_attacks_entity __on_player_starts_sneaking __on_player_stops_sneaking __on_player_starts_sprinting __on_player_stops_sprinting __on_player_releases_item __on_player_finishes_using_item __on_player_drops_item __on_player_drops_stack __on_tick __on_tick_ender __on_tick_nether + $ + 00' 01\ 02' 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/scarpet/resources/editors/npp/scarpet_v1.6_notepad++.xml b/docs/scarpet/resources/editors/npp/scarpet_v1.6_notepad++.xml new file mode 100644 index 00000000..d8058d2d --- /dev/null +++ b/docs/scarpet/resources/editors/npp/scarpet_v1.6_notepad++.xml @@ -0,0 +1,64 @@ + + + + + + + + 00// 01 02 03 04 + 0x + + + + + + + ; + - * / % ^ && || > >= < <= == != = += -> <> ! ~ , : + + ( + + ) + + + + + + + not fact rand sin cos tan asin acos atan atan2 sinh cosh tanh sec csc sech csch cot acot coth asinh acosh atanh rad deg log log10 log1p sqrt max min abs round floor ceil mandelbrot relu print return exit throw try l join split slice sort sort_key range m keys values pairs copy get put has delete var undef vars if loop map filter first all for while reduce continue break call outer type bool number str length rand sleep time profile_expr lower upper title replace replace_first + block pos pos_offset solid air liquid flammable transparent opacity blocks_daylight emitted_light light block_light sky_light see_sky hardness blast_resistance top loaded suffocates power ticks_randomly update block_tick random_tick set blocks_movement block_sound material map_colour property block_properties block_data place_item set_biome biome loaded_status generation_status chunk_tickets player spawn entity_id entity_list entity_area entity_selector query modify entity_event stack_limit item_category inventory_size inventory_has_items inventory_get inventory_set inventory_find inventory_remove drop_item scan volume neighbours rect diamond logger sound particle particle_line particle_rect run save tick_time game_tick current_dimension in_dimension plop harvest destroy schedule nbt create_marker remove_all_markers load_app_data store_app_data escape_nbt + euler pi null true false + x y z p + _ _i _a _x _y _z + global_ + __command __config __on_player_jumps __on_player_deploys_elytra __on_player_wakes_up __on_player_rides __on_player_uses_item __on_player_clicks_block __on_player_right_clicks_block __on_player_breaks_block __on_player_interacts_with_entity __on_player_attacks_entity __on_player_starts_sneaking __on_player_stops_sneaking __on_player_starts_sprinting __on_player_stops_sprinting __on_player_releases_item __on_player_finishes_using_item __on_player_drops_item __on_player_drops_stack __on_tick __on_tick_ender __on_tick_nether + $ + 00' 01\ 02' 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/carpet/script/value/ListValue.java b/src/main/java/carpet/script/value/ListValue.java index a4af06fd..2d1ac5dc 100644 --- a/src/main/java/carpet/script/value/ListValue.java +++ b/src/main/java/carpet/script/value/ListValue.java @@ -113,7 +113,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } else { - throw new InternalExpressionException("Cannot subtract two lists of uneven sizes"); + throw new InternalExpressionException("Cannot add two lists of uneven sizes"); } } else @@ -178,7 +178,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } else { - throw new InternalExpressionException("Cannot subtract two lists of uneven sizes"); + throw new InternalExpressionException("Cannot multiply two lists of uneven sizes"); } } else @@ -205,7 +205,7 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf } else { - throw new InternalExpressionException("Cannot subtract two lists of uneven sizes"); + throw new InternalExpressionException("Cannot divide two lists of uneven sizes"); } } else From 78ee80248b51a08ac570daa21814e5875cd81cd7 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 18 Mar 2020 02:00:17 -0300 Subject: [PATCH 9/9] docs fixes --- docs/scarpet/language/Overview.md | 13 ++++++++----- docs/scarpet/language/SystemFunctions.md | 11 ++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/scarpet/language/Overview.md b/docs/scarpet/language/Overview.md index a63629da..0689740f 100644 --- a/docs/scarpet/language/Overview.md +++ b/docs/scarpet/language/Overview.md @@ -62,7 +62,7 @@ or an OVERLY complex example: or simply
-/script run print('There is'+for(rect(x,9,z,8,8,8), _ == 'diamond_ore')+' diamond ore around you')
+/script run print('There is '+for(rect(x,9,z,8,8,8), _ == 'diamond_ore')+' diamond ore around you')
 
It definitely pays to check what higher level `scarpet` functions have to offer. @@ -112,16 +112,17 @@ Or rather:
 if
-(
-    x<y+6,
+(   x<y+6,
     (
         set(x,8+y,z,'air');
         plop(x,top('surface',x,z),z,'birch')
     ),
+    // else if
     sin(query(player(),'yaw'))>0.5,
     (
         plop(0,0,0,'boulder')
     ),
+    // else
     particle('fire',x,y,z)
 )
 
@@ -134,8 +135,10 @@ have problems with them ## Functions and scoping Users can define functions in the form `fun(args....) -> expression` and they are compiled and saved for further -execution in this but also subsequent calls of /script command. Functions can also be assigned to variables, -passed as arguments, called with `call` function, but in most cases you would want to call them directly by +execution in this, but also subsequent calls of /script command, added to events, etc. Functions can also be + assigned to variables, +passed as arguments, called with `call('fun', args...)` function, but in most cases you would want to +call them directly by name, in the form of `fun(args...)`. This means that once defined functions are saved with the world for further use. For variables, there are two types of them, global - which are shared anywhere in the code, and those are all which name starts with 'global_', and local variables which is everything else and those diff --git a/docs/scarpet/language/SystemFunctions.md b/docs/scarpet/language/SystemFunctions.md index 502a3c63..e25b48ba 100644 --- a/docs/scarpet/language/SystemFunctions.md +++ b/docs/scarpet/language/SystemFunctions.md @@ -51,10 +51,10 @@ number('2')+number('2') => 4 Returns a formatted string representing expression. Accepts formatting style accepted by `String.format`. Supported types (with `"%?"` syntax): -* d, o, x: integers -* a, e, f, g: floats -* b: booleans -* s: strings +* `d`, `o`, `x`: integers, octal, hex +* `a`, `e`, `f`, `g`: floats +* `b`: booleans +* `s`: strings
 str(null) => null
@@ -81,7 +81,8 @@ the off-tick time in between ticks that didn't take 50ms. There are however bene
 like fine time control not relying on the tick clock, or running things independent on each other. You can still run 
 your actions on tick-by-tick basis, either taking control of the execution using `game_tick()` API function 
 (nasty solution), or scheduling tick using `schedule()` function (much nicer solution), but threading often gives 
-the neatest solution to solve problems in parallel (see scarpet camera).
+the neatest solution to solve problems in parallel 
+(see [scarpet camera](/src/main/resources/assets/carpet/scripts/camera.sc)).
 
 Due to limitations with the game, there are some limits to the threading as well. You cannot for 
 instance `join_task()` at all from the main script and server thread, because any use of Minecraft specific