added snap to shape

added bulk shape rendering
This commit is contained in:
gnembon committed 2020-06-10 01:25:51 -03:00
1 parent 1a83a76be5
commit 58862fca11
6 files changed
+341 -91

No files matched your search

+12 -1
View File
@@ -36,7 +36,10 @@ 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)` ### `draw_shape(shape, duration, key?, value?, ... )`,
### `draw_shape(shape, duration, l(key?, value?, ... ))`,
### `draw_shape(shape, duration, attribute_map)`
### `draw_shape(shape_list)`
Draws a shape in the world that will expire in `duration` ticks. Other attributes of the shape should be provided as 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 consecutive key - value argument pairs, either as next arguments, or packed in a list, or supplied as a proper key-value
@@ -47,6 +50,10 @@ are not required to follow all attributes precisely, but will allow vanilla clie
apps. One of the attributes that will definitely not be honored is the duration - particles will be send once 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. per shape and last whatever they typically last in the game.
Shapes can be send one by one, using either of the first three invocations, or batched as a list of shape descriptors.
Batching has this benefit that they will be send possibly as one packet, limiting network overhead of
sending many small packets to draw several shapes at once.
Shapes will fail to draw and raise a runtime error if not all its required parameters 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: are specified and all available shapes have some parameters that are required, so make sure to have them in place:
@@ -65,6 +72,10 @@ Optional shared shape attributes:
* `follow` - entity, or player name. Shape will follow an entity instead of being static. * `follow` - entity, or player name. Shape will follow an entity instead of being static.
Follow attribute requires all positional arguments to be relative to the entity and disallow Follow attribute requires all positional arguments to be relative to the entity and disallow
of using entity or block as position markers. You must specify positions as a triple. of using entity or block as position markers. You must specify positions as a triple.
* `snap` - if `follow` is present, indicated on which axis the snapping to entity coordinates occurs, and which axis
will be treated statically, i.e. the coordinate passed in a coord triple is the actual value in the world. Default
value is `'xyz'`, meaning the shape will be drawn relatively to the entity in all three directions. Using `xz` for
instance makes so that the shape follows the entity, but stays at the same, absolute Y coordinate.
Available shapes: Available shapes:
* `'line'` - draws a straight line between two points * `'line'` - draws a straight line between two points
@@ -49,6 +49,7 @@ public class CarpetScriptServer
add(new BundledModule("event_test", false)); add(new BundledModule("event_test", false));
add(new BundledModule("stats_test", false)); add(new BundledModule("stats_test", false));
add(new BundledModule("math", true)); add(new BundledModule("math", true));
add(new BundledModule("chunk_display", false));
}}; }};
public CarpetScriptServer(MinecraftServer server) public CarpetScriptServer(MinecraftServer server)
@@ -31,9 +31,11 @@ import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.dimension.DimensionType;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
@@ -62,7 +64,7 @@ public class ShapeDispatcher
{ {
if (lv.size() < 3) throw new InternalExpressionException("'draw_shape' takes at least three parameters, shape name, duration, and its params"); if (lv.size() < 3) throw new InternalExpressionException("'draw_shape' takes at least three parameters, shape name, duration, and its params");
String shapeType = lv.get(0).getString(); String shapeType = lv.get(0).getString();
Value duration = NumericValue.asNumber(lv.get(1)); Value duration = NumericValue.asNumber(lv.get(1), "duration");
Map<String, Value> params; Map<String, Value> params;
if (lv.size() == 3) if (lv.size() == 3)
{ {
@@ -230,6 +232,7 @@ public class ShapeDispatcher
put("line", creator(Line::new)); put("line", creator(Line::new));
put("box", creator(Box::new)); put("box", creator(Box::new));
put("sphere", creator(Sphere::new)); put("sphere", creator(Sphere::new));
put("cylinder", creator(Cylinder::new));
}}; }};
private static Function<Map<String, Value>,ExpiringShape> creator(Supplier<ExpiringShape> shapeFactory) private static Function<Map<String, Value>,ExpiringShape> creator(Supplier<ExpiringShape> shapeFactory)
{ {
@@ -248,7 +251,9 @@ public class ShapeDispatcher
protected int duration = 0; protected int duration = 0;
private long key; private long key;
protected int followEntity; protected int followEntity;
protected DimensionType entityDimension; protected String snapTo;
protected boolean snapX, snapY, snapZ;
public DimensionType shapeDimension;
protected ExpiringShape() { } protected ExpiringShape() { }
@@ -302,18 +307,33 @@ public class ShapeDispatcher
key = 0; key = 0;
followEntity = -1; followEntity = -1;
entityDimension = null; shapeDimension = Registry.DIMENSION_TYPE.get(new Identifier(options.get("dim").getString()));
if (options.containsKey("follow")) if (options.containsKey("follow"))
{ {
followEntity = NumericValue.asNumber(options.getOrDefault("follow", optional.get("follow"))).getInt(); followEntity = NumericValue.asNumber(options.getOrDefault("follow", optional.get("follow"))).getInt();
entityDimension = Registry.DIMENSION_TYPE.get(new Identifier(options.get("dim").getString())); snapTo = options.getOrDefault("snap", optional.get("snap")).getString().toLowerCase(Locale.ROOT);
snapX = snapTo.contains("x");
snapY = snapTo.contains("y");
snapZ = snapTo.contains("z");
} }
} }
public int getExpiry() { return duration; } public int getExpiry() { return duration; }
public Vec3d toAbsolute(Entity e, Vec3d vec) public Vec3d toAbsolute(Entity e, Vec3d vec, float partialTick)
{ {
return e.getPos().add(vec); return vec.add(
snapX?MathHelper.lerp(partialTick, e.prevX, e.getX()):0.0,
snapY?MathHelper.lerp(partialTick, e.prevY, e.getY()):0.0,
snapZ?MathHelper.lerp(partialTick, e.prevZ, e.getZ()):0.0
);
} }
public Vec3d relativiseRender(World world, Vec3d vec, float partialTick)
{
if (followEntity <= 0) return vec;
Entity e = world.getEntityById(followEntity);
if (e == null) return vec;
return toAbsolute(e, vec, partialTick);
}
public Vec3d vecFromValue(Value value) public Vec3d vecFromValue(Value value)
{ {
if (!(value instanceof ListValue)) throw new InternalExpressionException("decoded value of "+value.getPrettyString()+" is not a triple"); if (!(value instanceof ListValue)) throw new InternalExpressionException("decoded value of "+value.getPrettyString()+" is not a triple");
@@ -335,6 +355,7 @@ public class ShapeDispatcher
protected long calcKey() protected long calcKey()
{ // using FNV-1a algorithm { // using FNV-1a algorithm
long hash = -3750763034362895579L; long hash = -3750763034362895579L;
hash ^= shapeDimension.hashCode(); hash *= 1099511628211L;
hash ^= color; hash *= 1099511628211L; hash ^= color; hash *= 1099511628211L;
hash ^= followEntity; hash *= 1099511628211L; hash ^= followEntity; hash *= 1099511628211L;
hash ^= Float.hashCode(lineWidth); hash *= 1099511628211L; hash ^= Float.hashCode(lineWidth); hash *= 1099511628211L;
@@ -347,7 +368,8 @@ public class ShapeDispatcher
"color", new NumericValue(-1), "color", new NumericValue(-1),
"follow", new NumericValue(-1), "follow", new NumericValue(-1),
"line", new NumericValue(2.0), "line", new NumericValue(2.0),
"fill", new NumericValue(0xffffff00) "fill", new NumericValue(0xffffff00),
"snap", new StringValue("xyz")
); );
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
@@ -389,16 +411,16 @@ public class ShapeDispatcher
double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1); double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1);
return p -> return p ->
{ {
if (followEntity == -1) if (p.dimension == shapeDimension)
{ {
particleMesh(Collections.singletonList(p), particle, density, from, to); particleMesh(
return; Collections.singletonList(p),
particle,
density,
relativiseRender(p.getServerWorld(), from, 0),
relativiseRender(p.getServerWorld(), to, 0)
);
} }
Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity);
if (e == null) return;
Vec3d rel1 = toAbsolute(e, from);
Vec3d rel2 = toAbsolute(e, to);
particleMesh(Collections.singletonList(p), particle, density, rel1, rel2);
}; };
} }
@@ -471,19 +493,16 @@ public class ShapeDispatcher
String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b);
ParticleEffect particle = getParticleData(particleName); ParticleEffect particle = getParticleData(particleName);
double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1); double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1);
return p -> return p ->
{ {
if (followEntity == -1) if (p.dimension == shapeDimension) drawParticleLine(
{ Collections.singletonList(p),
drawParticleLine(Collections.singletonList(p), particle, from, to, density); particle,
return; relativiseRender(p.getServerWorld(), from, 0),
} relativiseRender(p.getServerWorld(), to, 0),
density
Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity); );
if (e == null) return;
Vec3d rel1 = toAbsolute(e, from);
Vec3d rel2 = toAbsolute(e, to);
drawParticleLine(Collections.singletonList(p), particle, rel1, rel2, density);
}; };
} }
@@ -534,24 +553,18 @@ public class ShapeDispatcher
@Override @Override
public Consumer<ServerPlayerEntity> alternative() { return p -> public Consumer<ServerPlayerEntity> alternative() { return p ->
{ {
if (p.dimension != shapeDimension) return;
String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b);
ParticleEffect particle = getParticleData(particleName); ParticleEffect particle = getParticleData(particleName);
int partno = Math.min(1000,20*subdivisions); int partno = Math.min(1000,20*subdivisions);
Random rand = p.world.getRandom(); Random rand = p.world.getRandom();
ServerWorld world = p.getServerWorld(); ServerWorld world = p.getServerWorld();
double ccx, ccy, ccz; Vec3d ccenter = relativiseRender(world, center, 0 );
if (followEntity == -1)
{ double ccx = ccenter.x;
ccx = center.x; ccy = center.y; ccz = center.z; double ccy = ccenter.y;
} double ccz = ccenter.z;
else
{
Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity);
if (e == null) return;
Vec3d rel1 = toAbsolute(e, center);
ccx = (float)rel1.x; ccy = (float)rel1.y; ccz = (float)rel1.z;
}
for (int i=0; i<partno; i++) for (int i=0; i<partno; i++)
{ {
@@ -578,6 +591,110 @@ public class ShapeDispatcher
return hash; return hash;
} }
} }
public static class Cylinder extends ExpiringShape
{
private final Set<String> required = ImmutableSet.of("center", "radius");
private final Map<String, Value> optional = ImmutableMap.of(
"level", Value.ZERO,
"height", Value.ZERO,
"axis", new StringValue("y")
);
@Override
protected Set<String> requiredParams() { return Sets.union(super.requiredParams(), required); }
@Override
protected Set<String> optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); }
Vec3d center;
float height;
float radius;
int level;
int subdivisions;
Direction.Axis axis;
private Cylinder() { super(); }
@Override
protected void init(Map<String, Value> options)
{
super.init(options);
center = vecFromValue(options.get("center"));
radius = NumericValue.asNumber(options.get("radius")).getFloat();
level = NumericValue.asNumber(options.getOrDefault("level", optional.get("level"))).getInt();
subdivisions = level;
if (subdivisions <= 0)
{
subdivisions = Math.max(10, (int)(10*Math.sqrt(radius)));
}
height = NumericValue.asNumber(options.getOrDefault("height", optional.get("height"))).getFloat();
axis = Direction.Axis.fromName(options.getOrDefault("axis", optional.get("axis")).getString());
}
@Override
public Consumer<ServerPlayerEntity> alternative() { return p ->
{
String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b);
ParticleEffect particle = getParticleData(particleName);
int partno = (int)Math.min(1000,Math.sqrt(20*subdivisions*(1+height)));
Random rand = p.world.getRandom();
ServerWorld world = p.getServerWorld();
Vec3d ccenter = relativiseRender(world, center, 0 );
double ccx = ccenter.x;
double ccy = ccenter.y;
double ccz = ccenter.z;
if (axis == Direction.Axis.Y)
{
for (int i=0; i<partno; i++)
{
float d = rand.nextFloat()*height;
float phi = (float)(2*Math.PI*rand.nextDouble());
double x = radius * MathHelper.cos(phi);
double y = d;
double z = radius * MathHelper.sin(phi);
world.spawnParticles(p, particle, true, x+ccx, y+ccy, z+ccz, 1, 0.0, 0.0, 0.0, 0.0);
}
}
else if (axis== Direction.Axis.X)
{
for (int i=0; i<partno; i++)
{
float d = rand.nextFloat()*height;
float phi = (float)(2*Math.PI*rand.nextDouble());
double x = d;
double y = radius * MathHelper.cos(phi);
double z = radius * MathHelper.sin(phi);
world.spawnParticles(p, particle, true, x+ccx, y+ccy, z+ccz, 1, 0.0, 0.0, 0.0, 0.0);
}
}
else // Z
{
for (int i=0; i<partno; i++)
{
float d = rand.nextFloat()*height;
float phi = (float)(2*Math.PI*rand.nextDouble());
double x = radius * MathHelper.sin(phi);
double y = radius * MathHelper.cos(phi);
double z = d;
world.spawnParticles(p, particle, true, x+ccx, y+ccy, z+ccz, 1, 0.0, 0.0, 0.0, 0.0);
}
}
};}
@Override
public long calcKey()
{
long hash = super.calcKey();
hash ^= 3; hash *= 1099511628211L;
hash ^= center.hashCode(); hash *= 1099511628211L;
hash ^= Double.hashCode(radius); hash *= 1099511628211L;
hash ^= Double.hashCode(height); hash *= 1099511628211L;
hash ^= level; hash *= 1099511628211L;
return hash;
}
}
public static abstract class Param public static abstract class Param
@@ -588,6 +705,7 @@ public class ShapeDispatcher
put("duration", new NonNegativeIntParam("duration")); put("duration", new NonNegativeIntParam("duration"));
put("color", new ColorParam("color")); put("color", new ColorParam("color"));
put("follow", new EntityParam("follow")); put("follow", new EntityParam("follow"));
put("snap", new StringChoiceParam("snap", "xyz", "xz", "yz", "xy", "x", "y", "z"));
put("line", new PositiveFloatParam("line")); put("line", new PositiveFloatParam("line"));
put("fill", new ColorParam("fill")); put("fill", new ColorParam("fill"));
@@ -596,7 +714,7 @@ public class ShapeDispatcher
put("center", new Vec3Param("center", false)); put("center", new Vec3Param("center", false));
put("radius", new PositiveFloatParam("radius")); put("radius", new PositiveFloatParam("radius"));
put("level", new PositiveIntParam("level")); put("level", new PositiveIntParam("level"));
put("height", new PositiveFloatParam("height")); put("height", new NonNegativeFloatParam("height"));
put("axis", new StringChoiceParam("axis", "x", "y", "z")); put("axis", new StringChoiceParam("axis", "x", "y", "z"));
put("points", new PointsParam("points")); put("points", new PointsParam("points"));
}}; }};
@@ -692,7 +810,7 @@ public class ShapeDispatcher
@Override @Override
public Value decode(Tag tag) { return new NumericValue(((FloatTag)tag).getFloat()); } public Value decode(Tag tag) { return new NumericValue(((FloatTag)tag).getFloat()); }
@Override @Override
public Tag toTag(Value value) { return FloatTag.of(NumericValue.asNumber(value).getFloat()); } public Tag toTag(Value value) { return FloatTag.of(NumericValue.asNumber(value, id).getFloat()); }
} }
public static class PositiveIntParam extends PositiveParam public static class PositiveIntParam extends PositiveParam
@@ -701,7 +819,7 @@ public class ShapeDispatcher
@Override @Override
public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); }
@Override @Override
public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value, id).getInt()); }
} }
public static class NonNegativeIntParam extends NumericParam public static class NonNegativeIntParam extends NumericParam
@@ -710,7 +828,21 @@ public class ShapeDispatcher
@Override @Override
public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); }
@Override @Override
public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value, id).getInt()); }
@Override public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
{
Value ret = super.validate(options, cc, value);
if (((NumericValue)ret).getDouble()<0) throw new InternalExpressionException("'"+id+"' should be non-negative");
return ret;
}
}
public static class NonNegativeFloatParam extends NumericParam
{
protected NonNegativeFloatParam(String id) { super(id); }
@Override
public Value decode(Tag tag) { return new NumericValue(((FloatTag)tag).getFloat()); }
@Override
public Tag toTag(Value value) { return FloatTag.of(NumericValue.asNumber(value, id).getFloat()); }
@Override public Value validate(Map<String, Value> options, CarpetContext cc, Value value) @Override public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
{ {
Value ret = super.validate(options, cc, value); Value ret = super.validate(options, cc, value);
@@ -786,9 +918,9 @@ public class ShapeDispatcher
{ {
List<Value> lv = ((ListValue)value).getItems(); List<Value> lv = ((ListValue)value).getItems();
ListTag tag = new ListTag(); ListTag tag = new ListTag();
tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(0)).getDouble())); tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(0), "x").getDouble()));
tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(1)).getDouble())); tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(1), "y").getDouble()));
tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(2)).getDouble())); tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(2), "z").getDouble()));
return tag; return tag;
} }
} }
@@ -834,9 +966,9 @@ public class ShapeDispatcher
{ {
List<Value> coords = ((ListValue)value).getItems(); List<Value> coords = ((ListValue)value).getItems();
ListTag tag = new ListTag(); ListTag tag = new ListTag();
tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(0)).getDouble())); tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(0), "x").getDouble()));
tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(1)).getDouble())); tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(1), "y").getDouble()));
tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(2)).getDouble())); tag.add(DoubleTag.of(NumericValue.asNumber(lv.get(2), "z").getDouble()));
ltag.add(tag); ltag.add(tag);
} }
return ltag; return ltag;
@@ -853,7 +985,7 @@ public class ShapeDispatcher
public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); } public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); }
@Override @Override
public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value).getInt()); } public Tag toTag(Value value) { return IntTag.of(NumericValue.asNumber(value, id).getInt()); }
} }
public static class EntityParam extends Param public static class EntityParam extends Param
@@ -864,7 +996,7 @@ public class ShapeDispatcher
@Override @Override
public Tag toTag(Value value) public Tag toTag(Value value)
{ {
return IntTag.of(NumericValue.asNumber(value).getInt()); return IntTag.of(NumericValue.asNumber(value, id).getInt());
} }
@Override @Override
@@ -8,13 +8,11 @@ import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Camera; import net.minecraft.client.render.Camera;
import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats; import net.minecraft.client.render.VertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.util.Identifier; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.dimension.DimensionType;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
@@ -34,6 +32,7 @@ public class ShapesRenderer
put("line", RenderedLine::new); put("line", RenderedLine::new);
put("box", RenderedBox::new); put("box", RenderedBox::new);
put("sphere", RenderedSphere::new); put("sphere", RenderedSphere::new);
put("cylinder", RenderedCylinder::new);
}}; }};
public ShapesRenderer(MinecraftClient minecraftClient) public ShapesRenderer(MinecraftClient minecraftClient)
@@ -128,7 +127,7 @@ public class ShapesRenderer
else else
{ {
RenderedShape<?> rshape = shapeFactory.apply(client, shape); RenderedShape<?> rshape = shapeFactory.apply(client, shape);
DimensionType dim = Registry.DIMENSION_TYPE.get(new Identifier(tag.getString("dim"))); DimensionType dim = shape.shapeDimension;
long key = rshape.key(); long key = rshape.key();
synchronized (shapes) synchronized (shapes)
{ {
@@ -181,20 +180,9 @@ public class ShapesRenderer
{ {
if (shape.followEntity <=0 ) return true; if (shape.followEntity <=0 ) return true;
if (client.world == null) return false; if (client.world == null) return false;
if (client.world.dimension.getType() != dim) return false;
if (client.world.getEntityById(shape.followEntity) == null) return false; if (client.world.getEntityById(shape.followEntity) == null) return false;
return true; return true;
} }
protected Vec3d relativiseRender(Vec3d vec, float partialTick)
{
if (shape.followEntity <= 0) return vec;
Entity e = client.world.getEntityById(shape.followEntity);
return vec.add(
MathHelper.lerp(partialTick, e.prevX, e.getX()),
MathHelper.lerp(partialTick, e.prevY, e.getY()),
MathHelper.lerp(partialTick, e.prevZ, e.getZ())
);
}
} }
public static class RenderedBox extends RenderedShape<ShapeDispatcher.Box> public static class RenderedBox extends RenderedShape<ShapeDispatcher.Box>
@@ -209,8 +197,8 @@ public class ShapesRenderer
public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick)
{ {
if (shape.a == 0.0) return; if (shape.a == 0.0) return;
Vec3d v1 = relativiseRender(shape.from, partialTick); Vec3d v1 = shape.relativiseRender(client.world, shape.from, partialTick);
Vec3d v2 = relativiseRender(shape.to, partialTick); Vec3d v2 = shape.relativiseRender(client.world, shape.to, partialTick);
RenderSystem.lineWidth(shape.lineWidth); RenderSystem.lineWidth(shape.lineWidth);
drawBoxWireGLLines(tessellator, bufferBuilder, drawBoxWireGLLines(tessellator, bufferBuilder,
(float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon),
@@ -223,8 +211,8 @@ public class ShapesRenderer
public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick)
{ {
if (shape.fa == 0.0) return; if (shape.fa == 0.0) return;
Vec3d v1 = relativiseRender(shape.from, partialTick); Vec3d v1 = shape.relativiseRender(client.world, shape.from, partialTick);
Vec3d v2 = relativiseRender(shape.to, partialTick); Vec3d v2 = shape.relativiseRender(client.world, shape.to, partialTick);
RenderSystem.lineWidth(1.0F); RenderSystem.lineWidth(1.0F);
drawBoxFaces(tessellator, bufferBuilder, drawBoxFaces(tessellator, bufferBuilder,
(float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon),
@@ -245,8 +233,8 @@ public class ShapesRenderer
@Override @Override
public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick)
{ {
Vec3d v1 = relativiseRender(shape.from, partialTick); Vec3d v1 = shape.relativiseRender(client.world, shape.from, partialTick);
Vec3d v2 = relativiseRender(shape.to, partialTick); Vec3d v2 = shape.relativiseRender(client.world, shape.to, partialTick);
RenderSystem.lineWidth(shape.lineWidth); RenderSystem.lineWidth(shape.lineWidth);
drawLine(tessellator, bufferBuilder, drawLine(tessellator, bufferBuilder,
(float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon), (float)(v1.x-cx-renderEpsilon), (float)(v1.y-cy-renderEpsilon), (float)(v1.z-cz-renderEpsilon),
@@ -266,7 +254,7 @@ public class ShapesRenderer
public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick)
{ {
if (shape.a == 0.0) return; if (shape.a == 0.0) return;
Vec3d vc = relativiseRender(shape.center, partialTick); Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick);
RenderSystem.lineWidth(shape.lineWidth); RenderSystem.lineWidth(shape.lineWidth);
drawSphereWireframe(tessellator, bufferBuilder, drawSphereWireframe(tessellator, bufferBuilder,
(float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon),
@@ -277,7 +265,7 @@ public class ShapesRenderer
public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick) public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick)
{ {
if (shape.fa == 0.0) return; if (shape.fa == 0.0) return;
Vec3d vc = relativiseRender(shape.center, partialTick); Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick);
RenderSystem.lineWidth(1.0f); RenderSystem.lineWidth(1.0f);
drawSphereFaces(tessellator, bufferBuilder, drawSphereFaces(tessellator, bufferBuilder,
(float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon), (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon),
@@ -286,6 +274,36 @@ public class ShapesRenderer
} }
} }
public static class RenderedCylinder extends RenderedShape<ShapeDispatcher.Cylinder>
{
public RenderedCylinder(MinecraftClient client, ShapeDispatcher.ExpiringShape shape)
{
super(client, (ShapeDispatcher.Cylinder)shape);
}
@Override
public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick)
{
if (shape.a == 0.0) return;
Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick);
RenderSystem.lineWidth(shape.lineWidth);
drawCylinderWireframe(tessellator, bufferBuilder,
(float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon),
shape.radius, shape.height, shape.axis, shape.subdivisions,
shape.r, shape.g, shape.b, shape.a);
}
@Override
public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick)
{
if (shape.fa == 0.0) return;
//Vec3d vc = shape.relativiseRender(client.world, shape.center, partialTick);
//RenderSystem.lineWidth(1.0f);
//drawSphereFaces(tessellator, bufferBuilder,
// (float)(vc.x-cx-renderEpsilon), (float)(vc.y-cy-renderEpsilon), (float)(vc.z-cz-renderEpsilon),
// shape.radius, shape.subdivisions,
// shape.fr, shape.fg, shape.fb, shape.fa);
}
}
// some raw shit // some raw shit
public static void drawLine(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { public static void drawLine(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) {
@@ -409,6 +427,90 @@ public class ShapesRenderer
tessellator.draw(); tessellator.draw();
} }
public static void drawCylinderWireframe(Tessellator tessellator, BufferBuilder builder,
float cx, float cy, float cz,
float r, float h, Direction.Axis axis, int subd,
float red, float grn, float blu, float alpha)
{
float step = (float)Math.PI / (subd/2);
int num_steps180 = (int)(Math.PI / step)+1;
int num_steps360 = (int)(2*Math.PI / step);
int hsteps = (h>0) ? ((int)Math.ceil(h / (step*r))+1) : 1;
float hstep = (h>0) ? (h / (hsteps-1)) : 1;
// draw base
if (axis == Direction.Axis.Y)
{
for (int dh = 0; dh < hsteps; dh++)
{
float hh = dh*hstep;
builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR);
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float x = r * MathHelper.cos(theta);
float y = hh;
float z = r * MathHelper.sin(theta);
builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).next();
}
tessellator.draw();
}
if (h > 0)
{
for (int i = 0; i <= num_steps180; i++)
{
builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR);
float theta = step * i;
float x = r * MathHelper.cos(theta);
float z = r * MathHelper.sin(theta);
builder.vertex(cx - x, cy + 0, cz + z).color(red, grn, blu, alpha).next();
builder.vertex(cx + x, cy + 0, cz - z).color(red, grn, blu, alpha).next();
builder.vertex(cx + x, cy + h, cz - z).color(red, grn, blu, alpha).next();
builder.vertex(cx - x, cy + h, cz + z).color(red, grn, blu, alpha).next();
tessellator.draw();
}
}
}
else if (axis == Direction.Axis.X)
{
for (int dh = 0; dh < hsteps; dh++)
{
float hh = dh * hstep;
builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR);
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float z = r * MathHelper.cos(theta);
float x = hh;
float y = r * MathHelper.sin(theta);
builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).next();
}
tessellator.draw();
}
}
else if (axis == Direction.Axis.Z)
{
for (int dh = 0; dh < hsteps; dh++)
{
float hh = dh * hstep;
builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR);
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float y = r * MathHelper.cos(theta);
float z = hh;
float x = r * MathHelper.sin(theta);
builder.vertex(x + cx, y + cy, z + cz).color(red, grn, blu, alpha).next();
}
tessellator.draw();
}
}
}
public static void drawSphereWireframe(Tessellator tessellator, BufferBuilder builder, public static void drawSphereWireframe(Tessellator tessellator, BufferBuilder builder,
float cx, float cy, float cz, float cx, float cy, float cz,
float r, int subd, float r, int subd,
@@ -13,6 +13,13 @@ public class NumericValue extends Value
private Double value; private Double value;
final static double epsilon = 1024*Double.MIN_VALUE; final static double epsilon = 1024*Double.MIN_VALUE;
public static NumericValue asNumber(Value v1, String id)
{
if (!(v1 instanceof NumericValue))
throw new InternalExpressionException("Argument "+id+" has to be of a numeric type");
return ((NumericValue) v1);
}
public static NumericValue asNumber(Value v1) public static NumericValue asNumber(Value v1)
{ {
if (!(v1 instanceof NumericValue)) if (!(v1 instanceof NumericValue))
@@ -8,19 +8,19 @@ global_chunk_colors = m(
// stable full generation (for '0's, all 1,2,3 are always 'full') // stable full generation (for '0's, all 1,2,3 are always 'full')
l('full', l(0xbbbbbb00, 0x88888800)), // gray l('full', l(0xbbbbbb00, 0x88888800)), // gray
// unstable final bits // unstable final bits
l('heightmaps', l(0xFFFFFF00, 0x00000000)), // checker l('heightmaps', l(0x33333300, 0x22222200)), // checker
l('spawn', l(0xFFFFFF00, 0x00000000)), // checker l('spawn', l(0x00333300, 0x00222200)), // checker
l('light_gen', l(0xFFFFFF00, 0x00000000)), // checker l('light_gen', l(0x55550000, 0x44440000)), // checker
// stable features // stable features
l('features', l(0x88bb2200, 0x66882200)), // green muddled l('features', l(0x88bb2200, 0x66882200)), // green muddled
//stable terrain //stable terrain
l('liquid_carvers', l(0x65432100, 0x54321000)), // browns l('liquid_carvers', l(0x65432100, 0x54321000)), // browns
//unstable terrain - not generated yet //unstable terrain - not generated yet
l('carvers', l(0xFFFFFF00, 0x00000000)), // checker l('carvers', l(0x33003300, 0x22002200)), // checker
l('surface', l(0xFFFFFF00, 0x00000000)), // checker l('surface', l(0x33330000, 0x22220000)), // checker
l('noise', l(0xFFFFFF00, 0x00000000)), // checker l('noise', l(0x33000000, 0x22000000)), // checker
l('biomes', l(0xFFFFFF00, 0x00000000)), // checker l('biomes', l(0x00330000, 0x00220000)), // checker
l('structure_references', l(0xFFFFFF00, 0x00000000)), // checker l('structure_references', l(0x00003300, 0x00002200)), // checker
// stable // stable
l('structure_starts', l(0x66666600, 0x22222200)), // darkgrey l('structure_starts', l(0x66666600, 0x22222200)), // darkgrey
// not stated yet // not stated yet
@@ -37,7 +37,7 @@ global_chunk_colors = m(
l('post_teleport', l(0xAA00AA00, 0xAA00AA00)), // purple l('post_teleport', l(0xAA00AA00, 0xAA00AA00)), // purple
l('start', l(0xDDFF0000, 0xDDFF0000)), // lime, green l('start', l(0xDDFF0000, 0xDDFF0000)), // lime, green
// recent chunk requests // recent chunk requests
l('unknown', l(0xFFFFFF00, 0x00000000)) // check l('unknown', l(0xFF55FF00, 0xff99ff00)) // pink purple
); );
// map representing current displayed chunkloading setup // map representing current displayed chunkloading setup
@@ -67,8 +67,6 @@ __on_player_uses_item(player, item_tuple, hand) ->
__setup_tracker(player, item_tuple); __setup_tracker(player, item_tuple);
); );
//__on_tick() -> null;
__remove_previous_setup(new_player) -> __remove_previous_setup(new_player) ->
( (
if (!global_current_setup, return()); if (!global_current_setup, return());
@@ -127,6 +125,7 @@ __chunk_visualizer_tick(p) ->
if(!setup, return()); if(!setup, return());
if (!global_running, return()); if (!global_running, return());
show_activity = (p~'holds':0 == 'redstone_torch'); show_activity = (p~'holds':0 == 'redstone_torch');
yval = setup:'plot_center':1+16;
in_dimension( setup:'plot_dimension', in_dimension( setup:'plot_dimension',
l(sx, sy, sz) = setup:'source_center'; l(sx, sy, sz) = setup:'source_center';
l(px, py, pz) = setup:'plot_center'; l(px, py, pz) = setup:'plot_center';
@@ -154,8 +153,6 @@ __chunk_visualizer_tick(p) ->
for(tickets, for(tickets,
l(type, level) = _; l(type, level) = _;
if (show_activity || type != 'unknown', if (show_activity || type != 'unknown',
//global_status_cache:source_pos = type;
//changed = true;
status = type; status = type;
); );
); );
@@ -163,15 +160,15 @@ __chunk_visualizer_tick(p) ->
l(cached_status, expiry) = global_status_cache:source_pos; l(cached_status, expiry) = global_status_cache:source_pos;
changed = (status != cached_status); changed = (status != cached_status);
if ( changed || (expiry < now), if ( changed || (expiry < now),
global_status_cache:source_pos = l(status, now+100+floor(rand(20))); global_status_cache:source_pos = l(status, now+100+floor(rand(40)));
bpos = l(dx/2, 10, dz/2); bpos = l(dx/2, yval, dz/2);
bcol = global_chunk_colors:status:((dx+dz)%2); bcol = global_chunk_colors:status:((dx+dz)%2);
shapes += l('box', 150, 'from', bpos, 'to', bpos + l(0.5,0,0.5), shapes += l('box', 150, 'from', bpos, 'to', bpos + l(0.5,0,0.5),
'color', 0xffffff00, 'fill', bcol+128, 'follow', p); 'color', 0xffffff00, 'fill', bcol+128, 'follow', p, 'snap', 'xz');
if (changed, if (changed,
pbcol = global_chunk_colors:cached_status:((dx+dz)%2); pbcol = global_chunk_colors:cached_status:((dx+dz)%2);
shapes += l('box', 0, 'from', bpos, 'to', bpos + l(0.5,0,0.5), shapes += l('box', 0, 'from', bpos, 'to', bpos + l(0.5,0,0.5),
'color', 0xffffff00, 'fill', pbcol+128, 'follow', p); 'color', 0xffffff00, 'fill', pbcol+128, 'follow', p, 'snap', 'xz');
); );
); );
); );