diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md
index 99523a4f..a8ab3b82 100644
--- a/docs/scarpet/Full.md
+++ b/docs/scarpet/Full.md
@@ -906,8 +906,11 @@ 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)
+Returns the number of milliseconds since 'some point', like Java's `System.nanoTime()`, which varies from system to
+system and from Java to Java. This measure should NOT be used to determine the current (date)time, but to measure
+durations of things.
+it returns a float with time in milliseconds (ms) for convenience and microsecond (μs) resolution for sanity.
+
start_time = time();
@@ -1513,7 +1516,7 @@ range(5,10) => [5, 6, 7, 8, 9]
range(20, 10, -2) => [20, 18, 16, 14, 12]
-### `element(list, index)` (deprecated)
+### `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
@@ -3103,24 +3106,69 @@ and `voice`. `pos` can be either a block, triple of coords, or a list of thee nu
## Particles
-### `particle(name, pos, count?. spread?, speed?, playername?)`
+### `particle(name, pos, count?. spread?, speed?, player?)`
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?)`
+### `particle_line(name, pos, pos2, density?, player?)`
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.
+apart you would want particles to appear, so `0.1` means one every 10cm. If a player (or player name) is supplied, only
+that player will receive particles.
-### `particle_rect(name, pos, pos2, density?)`
-Renders a cuboid of particles between points `pos` and `pos2` with supplied density.
+### `particle_box(name, pos, pos2, density?, player?)`
+### `particle_rect` (deprecated)
+
+Renders a cuboid of particles between points `pos` and `pos2` with supplied density. If a player (or player name) is
+supplied, only that player will receive particles.
## Markers
+### `draw_shape(shape, duration, key?, value?, ... )`, `draw_shape(shape, duration, l(key?, value?, ... ))`, `draw_shape(shape, duration, attribute_map)`
+
+Draws a shape in the world that will expire in `duration` ticks. Other attributes of the shape should be provided as
+consecutive key - value argument pairs, either as next arguments, or packed in a list, or supplied as a proper key-value
+`map`. Arguments may include shared shape attributes, which are all optional, as well as shape-specific attributes, that
+could be either optional or required. Shapes will draw properly on all carpet clients. Other connected players that don't
+have carpet installed will still be able to see the required shapes in the form of dust particles. Replacement shapes
+are not required to follow all attributes precisely, but will allow vanilla clients to receive some experience of your
+apps. One of the attributes that will definitely not be honored is the duration - particles will be send once
+per shape and last whatever they typically last in the game.
+
+Shapes will fail to draw and raise a runtime error if not all its required parameters
+are specified and all available shapes have some parameters that are required, so make sure to have them in place:
+
+On the client, shapes can recognize that they are being redrawn again with the same parameters, disregarding the
+duration parameter. This updates the expiry on the drawn shape to the new value, instead of adding new shape in its
+place. This can be used for toggling the shapes on and off that has been send previously with very large durations,
+or simply refresh the shapes periodically in more dynamic applications.
+
+Optional shared shape attributes:
+ * `color` - integer value indicating the main color of the shape in the form of red, green, blue and alpha components
+ in the form of `0xRRGGBBAA`, with the default of `-1`, so white opaque, or `0xFFFFFFFF`.
+ * `player` - name or player entity to send the shape to. If specified, the shapes will appear only for the specified
+ player, otherwise it will be send to all players in the dimension.
+
+Available shapes:
+ * `'line'` - draws a straight line between two points
+ * Required attributes:
+ * `from` - triple coordinates, entity, or block value indicating one end of the line
+ * `to` - other end of the line, same format as `from`
+ * Optional attributes:
+ * `width` - line thickness, defaults to 2.0pt
+
+ * `'box'` - draws a box with corners in specified points
+ * Required attributes:
+ * `from` - triple coordinates, entity, or block value indicating one corner of the box
+ * `to` - other corner, same format as `from`
+ * Optional attributes:
+ * `width` - mesh line thickness, defaults to 2.0pt
+ * `fill` - color for the box faces, defaults to no fill, use shared color attribute format
+
### `create_marker(text, pos, rotation?, block?)`
Spawns a (permanent) marker entity with text or block at position. Returns that entity for further manipulations.
diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md
index a8b097dc..993620f7 100644
--- a/docs/scarpet/api/Auxiliary.md
+++ b/docs/scarpet/api/Auxiliary.md
@@ -66,11 +66,16 @@ Available shapes:
* Required attributes:
* `from` - triple coordinates, entity, or block value indicating one end of the line
* `to` - other end of the line, same format as `from`
+ * Optional attributes:
+ * `width` - line thickness, defaults to 2.0pt
* `'box'` - draws a box with corners in specified points
* Required attributes:
* `from` - triple coordinates, entity, or block value indicating one corner of the box
* `to` - other corner, same format as `from`
+ * Optional attributes:
+ * `width` - mesh line thickness, defaults to 2.0pt
+ * `fill` - color for the box faces, defaults to no fill, use shared color attribute format
### `create_marker(text, pos, rotation?, block?)`
diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt
index 81803965..279adc94 100644
--- a/docs/scarpet/resources/editors/idea/2.txt
+++ b/docs/scarpet/resources/editors/idea/2.txt
@@ -17,6 +17,7 @@ current_dimension
day_time
destroy
diamond
+draw_shape
drop_item
emitted_light
entity_area
diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml
index c17b3811..64158b61 100644
--- a/docs/scarpet/resources/editors/npp/scarpet.xml
+++ b/docs/scarpet/resources/editors/npp/scarpet.xml
@@ -70,7 +70,9 @@
run save tick_time world_time day_time last_tick_times 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 statistic
+ plop harvest destroy schedule nbt draw_shape create_marker remove_all_markers
+
+ load_app_data store_app_data escape_nbt statistic
euler pi null true false
x y z p
diff --git a/src/main/java/carpet/network/ClientNetworkHandler.java b/src/main/java/carpet/network/ClientNetworkHandler.java
index 96524117..07ec99df 100644
--- a/src/main/java/carpet/network/ClientNetworkHandler.java
+++ b/src/main/java/carpet/network/ClientNetworkHandler.java
@@ -35,7 +35,7 @@ public class ClientNetworkHandler
}
});
put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false));
- put("renderShape", (p, t) -> {
+ put("scShape", (p, t) -> {
if (CarpetClient.shapes != null)
CarpetClient.shapes.addShape((CompoundTag)t);
});
diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java
index 0aaadb12..a1d1f071 100644
--- a/src/main/java/carpet/script/utils/ShapeDispatcher.java
+++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java
@@ -19,6 +19,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.arguments.ParticleArgumentType;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.FloatTag;
import net.minecraft.nbt.IntTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
@@ -57,7 +58,7 @@ public class ShapeDispatcher
if (ServerNetworkHandler.validCarpetPlayers.contains(player))
{
if (tag == null) tag = ExpiringShape.toTag(params);
- ServerNetworkHandler.sendCustomCommand(player,"renderShape", tag);
+ ServerNetworkHandler.sendCustomCommand(player,"scShape", tag);
}
else
{
@@ -122,7 +123,7 @@ public class ShapeDispatcher
Function decoder = Param.decoders.get(key);
if (decoder==null)
{
- CarpetSettings.LOG.error("Unknown parameter for shape: "+key);
+ CarpetSettings.LOG.info("Unknown parameter for shape: "+key);
return null;
}
Value decodedValue = decoder.apply(tag.get(key));
@@ -131,13 +132,13 @@ public class ShapeDispatcher
Value shapeValue = options.get("shape");
if (shapeValue == null)
{
- CarpetSettings.LOG.error("Shape id missing in "+ String.join(", ", tag.getKeys()));
+ CarpetSettings.LOG.info("Shape id missing in "+ String.join(", ", tag.getKeys()));
return null;
}
Function