added optional options for draw_shape and fixed docs

This commit is contained in:
gnembon committed 2020-06-02 11:58:14 -03:00
1 parent 4271aa3a8e
commit 46409c8daa
7 files changed
+136 -30

No files matched your search

+56 -8
View File
@@ -906,8 +906,11 @@ sleep(50)
### `time()` ### `time()`
Returns the number of milliseconds since 'some point', like Java's `System.nanoTime()`. Returns the number of milliseconds since 'some point', like Java's `System.nanoTime()`, which varies from system to
It returns a float, which has 1 microsecond precision (0.001 ms) 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.
<pre> <pre>
start_time = time(); start_time = time();
@@ -1513,7 +1516,7 @@ range(5,10) => [5, 6, 7, 8, 9]
range(20, 10, -2) => [20, 18, 16, 14, 12] range(20, 10, -2) => [20, 18, 16, 14, 12]
</pre> </pre>
### `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 `.` 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 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 ## 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` 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` 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 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'`. 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 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 ## 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?)` ### `create_marker(text, pos, rotation?, block?)`
Spawns a (permanent) marker entity with text or block at position. Returns that entity for further manipulations. Spawns a (permanent) marker entity with text or block at position. Returns that entity for further manipulations.
+5
View File
@@ -66,11 +66,16 @@ Available shapes:
* Required attributes: * Required attributes:
* `from` - triple coordinates, entity, or block value indicating one end of the line * `from` - triple coordinates, entity, or block value indicating one end of the line
* `to` - other end of the line, same format as `from` * `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 * `'box'` - draws a box with corners in specified points
* Required attributes: * Required attributes:
* `from` - triple coordinates, entity, or block value indicating one corner of the box * `from` - triple coordinates, entity, or block value indicating one corner of the box
* `to` - other corner, same format as `from` * `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?)` ### `create_marker(text, pos, rotation?, block?)`
@@ -17,6 +17,7 @@ current_dimension
day_time day_time
destroy destroy
diamond diamond
draw_shape
drop_item drop_item
emitted_light emitted_light
entity_area entity_area
@@ -70,7 +70,9 @@
run save tick_time world_time day_time last_tick_times game_tick seed current_dimension in_dimension 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
</Keywords> </Keywords>
<Keywords name="Keywords3">euler pi null true false</Keywords> <Keywords name="Keywords3">euler pi null true false</Keywords>
<Keywords name="Keywords4">x y z p</Keywords> <Keywords name="Keywords4">x y z p</Keywords>
@@ -35,7 +35,7 @@ public class ClientNetworkHandler
} }
}); });
put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false)); put("TickRate", (p, t) -> TickSpeed.tickrate(((AbstractNumberTag)t).getFloat(), false));
put("renderShape", (p, t) -> { put("scShape", (p, t) -> {
if (CarpetClient.shapes != null) if (CarpetClient.shapes != null)
CarpetClient.shapes.addShape((CompoundTag)t); CarpetClient.shapes.addShape((CompoundTag)t);
}); });
@@ -19,6 +19,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.arguments.ParticleArgumentType; import net.minecraft.command.arguments.ParticleArgumentType;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.FloatTag;
import net.minecraft.nbt.IntTag; import net.minecraft.nbt.IntTag;
import net.minecraft.nbt.StringTag; import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
@@ -57,7 +58,7 @@ public class ShapeDispatcher
if (ServerNetworkHandler.validCarpetPlayers.contains(player)) if (ServerNetworkHandler.validCarpetPlayers.contains(player))
{ {
if (tag == null) tag = ExpiringShape.toTag(params); if (tag == null) tag = ExpiringShape.toTag(params);
ServerNetworkHandler.sendCustomCommand(player,"renderShape", tag); ServerNetworkHandler.sendCustomCommand(player,"scShape", tag);
} }
else else
{ {
@@ -122,7 +123,7 @@ public class ShapeDispatcher
Function<Tag, Value> decoder = Param.decoders.get(key); Function<Tag, Value> decoder = Param.decoders.get(key);
if (decoder==null) if (decoder==null)
{ {
CarpetSettings.LOG.error("Unknown parameter for shape: "+key); CarpetSettings.LOG.info("Unknown parameter for shape: "+key);
return null; return null;
} }
Value decodedValue = decoder.apply(tag.get(key)); Value decodedValue = decoder.apply(tag.get(key));
@@ -131,13 +132,13 @@ public class ShapeDispatcher
Value shapeValue = options.get("shape"); Value shapeValue = options.get("shape");
if (shapeValue == null) 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; return null;
} }
Function<Map<String, Value>,ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeValue.getString()); Function<Map<String, Value>,ExpiringShape> factory = ExpiringShape.shapeProviders.get(shapeValue.getString());
if (factory == null) if (factory == null)
{ {
CarpetSettings.LOG.error("Unknown shape: "+shapeValue.getString()); CarpetSettings.LOG.info("Unknown shape: "+shapeValue.getString());
return null; return null;
} }
try try
@@ -146,7 +147,7 @@ public class ShapeDispatcher
} }
catch (InternalExpressionException exc) catch (InternalExpressionException exc)
{ {
CarpetSettings.LOG.error(exc.getMessage()); CarpetSettings.LOG.info(exc.getMessage());
} }
return null; return null;
} }
@@ -225,7 +226,10 @@ public class ShapeDispatcher
} }
// list of params that need to be there // list of params that need to be there
private final Set<String> required = ImmutableSet.of("duration", "shape", "dim"); private final Set<String> required = ImmutableSet.of("duration", "shape", "dim");
private final Map<String, Value> optional = ImmutableMap.of("color", new NumericValue(-1), "player", Value.NULL); private final Map<String, Value> optional = ImmutableMap.of(
"color", new NumericValue(-1),
"player", Value.NULL
);
protected Set<String> requiredParams() {return required;} protected Set<String> requiredParams() {return required;}
// list of params that can be there, with defaults // list of params that can be there, with defaults
protected Set<String> optionalParams() {return optional.keySet();} protected Set<String> optionalParams() {return optional.keySet();}
@@ -234,7 +238,10 @@ public class ShapeDispatcher
public static class Box extends ExpiringShape public static class Box extends ExpiringShape
{ {
private final Set<String> required = ImmutableSet.of("from", "to"); private final Set<String> required = ImmutableSet.of("from", "to");
private final Map<String, Value> optional = ImmutableMap.of(); private final Map<String, Value> optional = ImmutableMap.of(
"width", new NumericValue(2.0),
"fill", new NumericValue(0xffffff00)
);
@Override @Override
protected Set<String> requiredParams() { return Sets.union(super.requiredParams(), required); } protected Set<String> requiredParams() { return Sets.union(super.requiredParams(), required); }
@Override @Override
@@ -243,6 +250,10 @@ public class ShapeDispatcher
float x1, y1, z1; float x1, y1, z1;
float x2, y2, z2; float x2, y2, z2;
float lineWidth;
protected float fr, fg, fb, fa;
protected int fillColor;
@Override @Override
protected void init(Map<String, Value> options) protected void init(Map<String, Value> options)
@@ -256,6 +267,12 @@ public class ShapeDispatcher
x2 = NumericValue.asNumber(to.get(0)).getFloat(); x2 = NumericValue.asNumber(to.get(0)).getFloat();
y2 = NumericValue.asNumber(to.get(1)).getFloat(); y2 = NumericValue.asNumber(to.get(1)).getFloat();
z2 = NumericValue.asNumber(to.get(2)).getFloat(); z2 = NumericValue.asNumber(to.get(2)).getFloat();
lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat();
fillColor = NumericValue.asNumber(options.getOrDefault("fill", optional.get("fill"))).getInt();
this.fr = (float)(fillColor >> 24 & 0xFF) / 255.0F;
this.fg = (float)(fillColor >> 16 & 0xFF) / 255.0F;
this.fb = (float)(fillColor >> 8 & 0xFF) / 255.0F;
this.fa = (float)(fillColor & 0xFF) / 255.0F;
} }
@Override @Override
@@ -281,6 +298,8 @@ public class ShapeDispatcher
hash = 31*hash + Float.hashCode(x2); hash = 31*hash + Float.hashCode(x2);
hash = 31*hash + Float.hashCode(y2); hash = 31*hash + Float.hashCode(y2);
hash = 31*hash + Float.hashCode(z2); hash = 31*hash + Float.hashCode(z2);
hash = 31*hash + Float.hashCode(lineWidth);
if (fa != 0.0) hash = 31*hash + fillColor;
return hash; return hash;
} }
@@ -308,7 +327,7 @@ public class ShapeDispatcher
public static class Line extends ExpiringShape public static class Line extends ExpiringShape
{ {
private final Set<String> required = ImmutableSet.of("from", "to"); private final Set<String> required = ImmutableSet.of("from", "to");
private final Map<String, Value> optional = ImmutableMap.of(); private final Map<String, Value> optional = ImmutableMap.of("width", new NumericValue(2.0));
@Override @Override
protected Set<String> requiredParams() { return Sets.union(super.requiredParams(), required); } protected Set<String> requiredParams() { return Sets.union(super.requiredParams(), required); }
@Override @Override
@@ -321,6 +340,7 @@ public class ShapeDispatcher
float x1, y1, z1; float x1, y1, z1;
float x2, y2, z2; float x2, y2, z2;
float lineWidth;
@Override @Override
protected void init(Map<String, Value> options) protected void init(Map<String, Value> options)
@@ -334,6 +354,7 @@ public class ShapeDispatcher
x2 = NumericValue.asNumber(to.get(0)).getFloat(); x2 = NumericValue.asNumber(to.get(0)).getFloat();
y2 = NumericValue.asNumber(to.get(1)).getFloat(); y2 = NumericValue.asNumber(to.get(1)).getFloat();
z2 = NumericValue.asNumber(to.get(2)).getFloat(); z2 = NumericValue.asNumber(to.get(2)).getFloat();
lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat();
} }
@Override @Override
@@ -361,6 +382,7 @@ public class ShapeDispatcher
hash = 31*hash + Float.hashCode(x2); hash = 31*hash + Float.hashCode(x2);
hash = 31*hash + Float.hashCode(y2); hash = 31*hash + Float.hashCode(y2);
hash = 31*hash + Float.hashCode(z2); hash = 31*hash + Float.hashCode(z2);
hash = 31*hash + Float.hashCode(lineWidth);
return hash; return hash;
} }
} }
@@ -374,16 +396,19 @@ public class ShapeDispatcher
put("color", ShapeDispatcher::decodeInt); put("color", ShapeDispatcher::decodeInt);
put("from", Vec3Param::decode); put("from", Vec3Param::decode);
put("to", Vec3Param::decode); put("to", Vec3Param::decode);
put("width", ShapeDispatcher::decodeFloat);
put("fill", ShapeDispatcher::decodeInt);
}}; }};
Map<String, Param> coders = new HashMap<String, Param>(){{ Map<String, Param> coders = new HashMap<String, Param>(){{
put("shape", new ShapeParam());
put("player", new PlayerParam()); put("player", new PlayerParam());
put("shape", new ShapeParam());
put("dim", new DimensionParam()); put("dim", new DimensionParam());
put("duration", new DurationParam()); put("duration", new DurationParam());
put("color", new ColorParam()); put("color", new ColorParam());
put("from", new FromParam()); put("from", new FromParam());
put("to", new ToParam()); put("to", new ToParam());
put("width", new WidthParam());
put("fill", new FillColorParam());
}}; }};
Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize
Value validate(CarpetContext cc, Value value); // makes sure the value is proper Value validate(CarpetContext cc, Value value); // makes sure the value is proper
@@ -452,8 +477,6 @@ public class ShapeDispatcher
} }
public static abstract class NumericParam implements Param public static abstract class NumericParam implements Param
{ {
@Override
public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); }
@Override @Override
public Value validate(CarpetContext cc, Value value) public Value validate(CarpetContext cc, Value value)
{ {
@@ -471,15 +494,34 @@ public class ShapeDispatcher
return ret; return ret;
} }
} }
public static abstract class PositiveFloatParam extends PositiveParam
{
@Override
public Tag toTag(Value value) { return FloatTag.of(NumericValue.asNumber(value).getFloat()); }
}
public static abstract class PositiveIntParam extends PositiveParam
{
@Override
public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); }
}
public static Value decodeInt(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } public static Value decodeInt(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); }
public static class DurationParam extends PositiveParam public static Value decodeFloat(Tag tag) { return new NumericValue(((FloatTag)tag).getFloat()); }
public static class DurationParam extends PositiveIntParam
{ {
@Override @Override
public boolean appliesTo(ExpiringShape shape) { return true; } public boolean appliesTo(ExpiringShape shape) { return true; }
@Override @Override
public String identify() { return "duration"; } public String identify() { return "duration"; }
} }
public static class WidthParam extends PositiveFloatParam
{
@Override
public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box || shape instanceof Line; }
@Override
public String identify() { return "width"; }
}
public static abstract class Vec3Param implements Param public static abstract class Vec3Param implements Param
{ {
@@ -546,12 +588,22 @@ public class ShapeDispatcher
} }
public static class ColorParam extends NumericParam public static class ColorParam extends NumericParam
{ {
@Override
public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); }
@Override @Override
public boolean appliesTo(ExpiringShape shape) { return true; } public boolean appliesTo(ExpiringShape shape) { return true; }
@Override @Override
public String identify() { return "color"; } public String identify() { return "color"; }
} }
public static class FillColorParam extends ColorParam
{
@Override
public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box; }
@Override
public String identify() { return "fill"; }
}
public static class FromParam extends Vec3Param public static class FromParam extends Vec3Param
{ {
@Override @Override
@@ -91,12 +91,9 @@ public class ShapesRenderer
if (shape == null) return; if (shape == null) return;
BiFunction<MinecraftClient, ShapeDispatcher.ExpiringShape, RenderedShape<? extends ShapeDispatcher.ExpiringShape >> shapeFactory; BiFunction<MinecraftClient, ShapeDispatcher.ExpiringShape, RenderedShape<? extends ShapeDispatcher.ExpiringShape >> shapeFactory;
shapeFactory = renderedShapes.get(tag.getString("shape")); shapeFactory = renderedShapes.get(tag.getString("shape"));
if (shapeFactory == null) if (shapeFactory == null)
{ {
CarpetSettings.LOG.error("Unrecognized shape: "+tag.getString("shape")); CarpetSettings.LOG.info("Unrecognized shape: "+tag.getString("shape"));
} }
else else
{ {
@@ -161,7 +158,7 @@ public class ShapesRenderer
@Override @Override
public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz)
{ {
RenderSystem.lineWidth(2.0F); RenderSystem.lineWidth(shape.lineWidth);
bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3
drawBoxWireGLLines(bufferBuilder, drawBoxWireGLLines(bufferBuilder,
shape.x1 - cx-renderEpsilon, shape.y1 - cy-renderEpsilon, shape.z1 - cz-renderEpsilon, shape.x1 - cx-renderEpsilon, shape.y1 - cy-renderEpsilon, shape.z1 - cz-renderEpsilon,
@@ -173,12 +170,13 @@ public class ShapesRenderer
@Override @Override
public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz)
{ {
if (shape.fa == 0.0) return;
RenderSystem.lineWidth(1.0F); RenderSystem.lineWidth(1.0F);
bufferBuilder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); // 3 bufferBuilder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); // 3
drawBox(bufferBuilder, drawBox(bufferBuilder,
shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon,
shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon, shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon,
shape.r, shape.g, shape.b, shape.a/6 shape.fr, shape.fg, shape.fb, shape.fa
); );
tessellator.draw(); tessellator.draw();
} }
@@ -193,7 +191,7 @@ public class ShapesRenderer
@Override @Override
public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz)
{ {
RenderSystem.lineWidth(2.0F); RenderSystem.lineWidth(shape.lineWidth);
bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3
drawLine(bufferBuilder, drawLine(bufferBuilder,
shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon,