refactor
This commit is contained in:
1 parent
0f10e030dd
commit
50b414727c
4 files changed
+209
-339
No files matched your search
@@ -60,25 +60,23 @@ Optional shared shape attributes:
|
|||||||
in the form of `0xRRGGBBAA`, with the default of `-1`, so white opaque, or `0xFFFFFFFF`.
|
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` - 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.
|
player, otherwise it will be send to all players in the dimension.
|
||||||
|
* `width` - line thickness, defaults to 2.0pt
|
||||||
|
* `fill` - color for the faces, defaults to no fill. Use `color` attribute format
|
||||||
|
* `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
|
||||||
|
of using entity or block as position markers. You must specify positions as a triple.
|
||||||
|
|
||||||
Available shapes:
|
Available shapes:
|
||||||
* `'line'` - draws a straight line between two points
|
* `'line'` - draws a straight line between two points
|
||||||
* 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
|
|
||||||
* `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
|
|
||||||
of using entity or block as position markers. You must specify positions as a triple.
|
|
||||||
|
|
||||||
* `'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
|
|
||||||
* `'sphere'` - draws a sphere
|
* `'sphere'` - draws a sphere
|
||||||
* Required attributes:
|
* Required attributes:
|
||||||
* `center` - center of the sphere
|
* `center` - center of the sphere
|
||||||
@@ -86,7 +84,6 @@ Available shapes:
|
|||||||
* Optional attributes:
|
* Optional attributes:
|
||||||
* `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the
|
* `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the
|
||||||
level of detail will be selected automatically based on radius.
|
level of detail will be selected automatically based on radius.
|
||||||
* `width` - line thickness
|
|
||||||
|
|
||||||
### `create_marker(text, pos, rotation?, block?)`
|
### `create_marker(text, pos, rotation?, block?)`
|
||||||
|
|
||||||
|
|||||||
@@ -2635,15 +2635,11 @@ public class CarpetExpression
|
|||||||
}
|
}
|
||||||
Vec3d a = pos1.vec;
|
Vec3d a = pos1.vec;
|
||||||
Vec3d b = pos2.vec;
|
Vec3d b = pos2.vec;
|
||||||
double ax = min(a.x, b.x);
|
Vec3d from = new Vec3d(min(a.x, b.x), min(a.y, b.y), min(a.z, b.z));
|
||||||
double ay = min(a.y, b.y);
|
Vec3d to = new Vec3d(max(a.x, b.x), max(a.y, b.y), max(a.z, b.z));
|
||||||
double az = min(a.z, b.z);
|
int particleCount = ShapeDispatcher.Box.particleMesh(
|
||||||
double bx = max(a.x, b.x);
|
|
||||||
double by = max(a.y, b.y);
|
|
||||||
double bz = max(a.z, b.z);
|
|
||||||
int particleCount = ShapeDispatcher.Box.mesh(
|
|
||||||
player==null?world.getPlayers():Collections.singletonList(player),
|
player==null?world.getPlayers():Collections.singletonList(player),
|
||||||
particle, density, ax, ay, az, bx, by, bz
|
particle, density, from, to
|
||||||
);
|
);
|
||||||
return (c_, t_) -> new NumericValue(particleCount);
|
return (c_, t_) -> new NumericValue(particleCount);
|
||||||
});
|
});
|
||||||
@@ -2680,13 +2676,17 @@ public class CarpetExpression
|
|||||||
}
|
}
|
||||||
params.putIfAbsent("dim", new StringValue(cc.s.getWorld().getDimension().getType().toString()));
|
params.putIfAbsent("dim", new StringValue(cc.s.getWorld().getDimension().getType().toString()));
|
||||||
params.putIfAbsent("duration", duration);
|
params.putIfAbsent("duration", duration);
|
||||||
|
|
||||||
ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.create(cc, shapeType, params);
|
|
||||||
ServerPlayerEntity player = null;
|
ServerPlayerEntity player = null;
|
||||||
if (params.containsKey("player"))
|
if (params.containsKey("player"))
|
||||||
{
|
{
|
||||||
player = (ServerPlayerEntity)((EntityValue)params.get("player")).getEntity();
|
player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), params.get("player"));
|
||||||
|
if (player == null)
|
||||||
|
throw new InternalExpressionException("'player' parameter needs to represent an existing player");
|
||||||
|
params.remove("player");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.create(cc, shapeType, params);
|
||||||
|
|
||||||
ShapeDispatcher.sendShape(
|
ShapeDispatcher.sendShape(
|
||||||
(player==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player),
|
(player==null)?cc.s.getWorld().getPlayers():Collections.singletonList(player),
|
||||||
shape,
|
shape,
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ import java.util.function.Consumer;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import static java.lang.Math.sqrt;
|
|
||||||
|
|
||||||
public class ShapeDispatcher
|
public class ShapeDispatcher
|
||||||
{
|
{
|
||||||
private static final Map<String, ParticleEffect> particleCache = new HashMap<>();
|
private static final Map<String, ParticleEffect> particleCache = new HashMap<>();
|
||||||
@@ -107,7 +105,7 @@ public class ShapeDispatcher
|
|||||||
{
|
{
|
||||||
userParams.put("shape", new StringValue(shapeType));
|
userParams.put("shape", new StringValue(shapeType));
|
||||||
userParams.keySet().forEach(key -> {
|
userParams.keySet().forEach(key -> {
|
||||||
Param param = Param.coders.get(key);
|
Param param = Param.of.get(key);
|
||||||
if (param==null) throw new InternalExpressionException("Unknown feature for shape: "+key);
|
if (param==null) throw new InternalExpressionException("Unknown feature for shape: "+key);
|
||||||
userParams.put(key, param.validate(userParams, cc, userParams.get(key)));
|
userParams.put(key, param.validate(userParams, cc, userParams.get(key)));
|
||||||
});
|
});
|
||||||
@@ -122,13 +120,13 @@ public class ShapeDispatcher
|
|||||||
Map<String, Value> options = new HashMap<>();
|
Map<String, Value> options = new HashMap<>();
|
||||||
for (String key : tag.getKeys())
|
for (String key : tag.getKeys())
|
||||||
{
|
{
|
||||||
Function<Tag, Value> decoder = Param.decoders.get(key);
|
Param decoder = Param.of.get(key);
|
||||||
if (decoder==null)
|
if (decoder==null)
|
||||||
{
|
{
|
||||||
CarpetSettings.LOG.info("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.decode(tag.get(key));
|
||||||
options.put(key, decodedValue);
|
options.put(key, decodedValue);
|
||||||
}
|
}
|
||||||
Value shapeValue = options.get("shape");
|
Value shapeValue = options.get("shape");
|
||||||
@@ -170,8 +168,11 @@ public class ShapeDispatcher
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float lineWidth;
|
||||||
protected float r, g, b, a;
|
protected float r, g, b, a;
|
||||||
protected int color;
|
protected int color;
|
||||||
|
protected float fr, fg, fb, fa;
|
||||||
|
protected int fillColor;
|
||||||
protected int duration = 0;
|
protected int duration = 0;
|
||||||
private int key;
|
private int key;
|
||||||
protected int followEntity;
|
protected int followEntity;
|
||||||
@@ -184,7 +185,7 @@ public class ShapeDispatcher
|
|||||||
{
|
{
|
||||||
CompoundTag tag = new CompoundTag();
|
CompoundTag tag = new CompoundTag();
|
||||||
params.forEach((k, v) -> {
|
params.forEach((k, v) -> {
|
||||||
Tag valTag = Param.coders.get(k).toTag(v);
|
Tag valTag = Param.of.get(k).toTag(v);
|
||||||
if (valTag != null) tag.put(k, valTag);
|
if (valTag != null) tag.put(k, valTag);
|
||||||
});
|
});
|
||||||
return tag;
|
return tag;
|
||||||
@@ -200,20 +201,33 @@ public class ShapeDispatcher
|
|||||||
if (!options.keySet().containsAll(required))
|
if (!options.keySet().containsAll(required))
|
||||||
throw new InternalExpressionException("Missing required parameters for shape: "+Sets.difference(required, options.keySet()));
|
throw new InternalExpressionException("Missing required parameters for shape: "+Sets.difference(required, options.keySet()));
|
||||||
options.keySet().forEach(k ->{
|
options.keySet().forEach(k ->{
|
||||||
if (!Param.coders.get(k).appliesTo(this))
|
if (!this.canTake(k))
|
||||||
throw new InternalExpressionException("Parameter "+k+" doesn't apply for shape "+options.get("shape").getString());
|
throw new InternalExpressionException("Parameter "+k+" doesn't apply for shape "+options.get("shape").getString());
|
||||||
});
|
});
|
||||||
init(options);
|
init(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected void init(Map<String, Value> options)
|
protected void init(Map<String, Value> options)
|
||||||
{
|
{
|
||||||
|
|
||||||
duration = NumericValue.asNumber(options.get("duration")).getInt();
|
duration = NumericValue.asNumber(options.get("duration")).getInt();
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
color = NumericValue.asNumber(options.getOrDefault("color", optional.get("color"))).getInt();
|
color = NumericValue.asNumber(options.getOrDefault("color", optional.get("color"))).getInt();
|
||||||
this.r = (float)(color >> 24 & 0xFF) / 255.0F;
|
this.r = (float)(color >> 24 & 0xFF) / 255.0F;
|
||||||
this.g = (float)(color >> 16 & 0xFF) / 255.0F;
|
this.g = (float)(color >> 16 & 0xFF) / 255.0F;
|
||||||
this.b = (float)(color >> 8 & 0xFF) / 255.0F;
|
this.b = (float)(color >> 8 & 0xFF) / 255.0F;
|
||||||
this.a = (float)(color & 0xFF) / 255.0F;
|
this.a = (float)(color & 0xFF) / 255.0F;
|
||||||
|
|
||||||
key = 0;
|
key = 0;
|
||||||
followEntity = -1;
|
followEntity = -1;
|
||||||
entityDimension = null;
|
entityDimension = null;
|
||||||
@@ -224,10 +238,21 @@ public class ShapeDispatcher
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public int getExpiry() { return duration; }
|
public int getExpiry() { return duration; }
|
||||||
public Vec3d toAbsolute(Entity e, float x, float y, float z)
|
public Vec3d toAbsolute(Entity e, Vec3d vec)
|
||||||
{
|
{
|
||||||
return e.getPos().add(x,y,z);
|
return e.getPos().add(vec);
|
||||||
}
|
}
|
||||||
|
public Vec3d vecFromValue(Value value)
|
||||||
|
{
|
||||||
|
if (!(value instanceof ListValue)) throw new InternalExpressionException("decoded value of "+value.getPrettyString()+" is not a triple");
|
||||||
|
List<Value> elements = ((ListValue) value).getItems();
|
||||||
|
return new Vec3d(
|
||||||
|
NumericValue.asNumber( elements.get(0)).getDouble(),
|
||||||
|
NumericValue.asNumber( elements.get(1)).getDouble(),
|
||||||
|
NumericValue.asNumber( elements.get(2)).getDouble()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract Consumer<ServerPlayerEntity> alternative();
|
public abstract Consumer<ServerPlayerEntity> alternative();
|
||||||
public int key()
|
public int key()
|
||||||
{
|
{
|
||||||
@@ -240,82 +265,67 @@ public class ShapeDispatcher
|
|||||||
int hash = 17;
|
int hash = 17;
|
||||||
hash = 31*hash + color;
|
hash = 31*hash + color;
|
||||||
hash = 31*hash + followEntity;
|
hash = 31*hash + followEntity;
|
||||||
|
hash = 31*hash + Float.hashCode(lineWidth);
|
||||||
|
if (fa != 0.0) hash = 31*hash + fillColor;
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
// 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(
|
private final Map<String, Value> optional = ImmutableMap.of(
|
||||||
"color", new NumericValue(-1),
|
"color", new NumericValue(-1),
|
||||||
"player", Value.NULL,
|
"follow", new NumericValue(-1),
|
||||||
"follow", new NumericValue(-1)
|
"width", new NumericValue(2.0),
|
||||||
|
"fill", new NumericValue(0xffffff00)
|
||||||
);
|
);
|
||||||
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();}
|
||||||
|
|
||||||
|
private boolean canTake(String param)
|
||||||
|
{
|
||||||
|
return requiredParams().contains(param) || optionalParams().contains(param);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
protected Set<String> optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); }
|
protected Set<String> optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); }
|
||||||
public Box() { }
|
public Box() { }
|
||||||
|
|
||||||
float x1, y1, z1;
|
Vec3d from;
|
||||||
float x2, y2, z2;
|
Vec3d to;
|
||||||
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)
|
||||||
{
|
{
|
||||||
super.init(options);
|
super.init(options);
|
||||||
List<Value> from = ((ListValue)options.get("from")).getItems();
|
from = vecFromValue(options.get("from"));
|
||||||
x1 = NumericValue.asNumber(from.get(0)).getFloat();
|
to = vecFromValue(options.get("to"));
|
||||||
y1 = NumericValue.asNumber(from.get(1)).getFloat();
|
|
||||||
z1 = NumericValue.asNumber(from.get(2)).getFloat();
|
|
||||||
List<Value> to = ((ListValue)options.get("to")).getItems();
|
|
||||||
x2 = NumericValue.asNumber(to.get(0)).getFloat();
|
|
||||||
y2 = NumericValue.asNumber(to.get(1)).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
|
||||||
public Consumer<ServerPlayerEntity> alternative()
|
public Consumer<ServerPlayerEntity> alternative()
|
||||||
{
|
{
|
||||||
|
|
||||||
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 dx = x1-x2;
|
double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1);
|
||||||
double dy = y1-y2;
|
|
||||||
double dz = z1-z2;
|
|
||||||
double density = Math.max(2.0, Math.sqrt(dx*dx+dy*dy+dz*dz) /50) / (a+0.1);
|
|
||||||
return p ->
|
return p ->
|
||||||
{
|
{
|
||||||
if (followEntity == -1)
|
if (followEntity == -1)
|
||||||
{
|
{
|
||||||
mesh(Collections.singletonList(p), particle, density, x1, y1, z1, x2, y2, z2);
|
particleMesh(Collections.singletonList(p), particle, density, from, to);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity);
|
Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity);
|
||||||
if (e == null) return;
|
if (e == null) return;
|
||||||
Vec3d rel1 = toAbsolute(e, x1, y1, z1);
|
Vec3d rel1 = toAbsolute(e, from);
|
||||||
Vec3d rel2 = toAbsolute(e, x2, y2, z2);
|
Vec3d rel2 = toAbsolute(e, to);
|
||||||
mesh(Collections.singletonList(p), particle, density, rel1.x, rel1.y, rel1.z, rel2.x, rel2.y, rel2.z);
|
particleMesh(Collections.singletonList(p), particle, density, rel1, rel2);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,20 +334,20 @@ public class ShapeDispatcher
|
|||||||
{
|
{
|
||||||
int hash = super.calcKey();
|
int hash = super.calcKey();
|
||||||
hash = 31*hash + 1;
|
hash = 31*hash + 1;
|
||||||
hash = 31*hash + Float.hashCode(x1);
|
hash = 31*hash + from.hashCode();
|
||||||
hash = 31*hash + Float.hashCode(y1);
|
hash = 31*hash + to.hashCode();
|
||||||
hash = 31*hash + Float.hashCode(z1);
|
|
||||||
hash = 31*hash + Float.hashCode(x2);
|
|
||||||
hash = 31*hash + Float.hashCode(y2);
|
|
||||||
hash = 31*hash + Float.hashCode(z2);
|
|
||||||
hash = 31*hash + Float.hashCode(lineWidth);
|
|
||||||
if (fa != 0.0) hash = 31*hash + fillColor;
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int mesh(List<ServerPlayerEntity> playerList, ParticleEffect particle, double density,
|
public static int particleMesh(List<ServerPlayerEntity> playerList, ParticleEffect particle, double density,
|
||||||
double x1, double y1, double z1, double x2, double y2, double z2 )
|
Vec3d from, Vec3d to)
|
||||||
{
|
{
|
||||||
|
double x1 = from.x;
|
||||||
|
double y1 = from.y;
|
||||||
|
double z1 = from.z;
|
||||||
|
double x2 = to.z;
|
||||||
|
double y2 = to.y;
|
||||||
|
double z2 = to.z;
|
||||||
return
|
return
|
||||||
drawParticleLine(playerList, particle, new Vec3d(x1, y1, z1), new Vec3d(x1, y2, z1), density)+
|
drawParticleLine(playerList, particle, new Vec3d(x1, y1, z1), new Vec3d(x1, y2, z1), density)+
|
||||||
drawParticleLine(playerList, particle, new Vec3d(x1, y2, z1), new Vec3d(x2, y2, z1), density)+
|
drawParticleLine(playerList, particle, new Vec3d(x1, y2, z1), new Vec3d(x2, y2, z1), density)+
|
||||||
@@ -359,7 +369,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("width", new NumericValue(2.0));
|
private final Map<String, Value> optional = ImmutableMap.of();
|
||||||
@Override
|
@Override
|
||||||
protected Set<String> requiredParams() { return Sets.union(super.requiredParams(), required); }
|
protected Set<String> requiredParams() { return Sets.union(super.requiredParams(), required); }
|
||||||
@Override
|
@Override
|
||||||
@@ -370,23 +380,15 @@ public class ShapeDispatcher
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
float x1, y1, z1;
|
Vec3d from;
|
||||||
float x2, y2, z2;
|
Vec3d to;
|
||||||
float lineWidth;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void init(Map<String, Value> options)
|
protected void init(Map<String, Value> options)
|
||||||
{
|
{
|
||||||
super.init(options);
|
super.init(options);
|
||||||
List<Value> from = ((ListValue)options.get("from")).getItems();
|
from = vecFromValue(options.get("from"));
|
||||||
x1 = NumericValue.asNumber(from.get(0)).getFloat();
|
to = vecFromValue(options.get("to"));
|
||||||
y1 = NumericValue.asNumber(from.get(1)).getFloat();
|
|
||||||
z1 = NumericValue.asNumber(from.get(2)).getFloat();
|
|
||||||
List<Value> to = ((ListValue)options.get("to")).getItems();
|
|
||||||
x2 = NumericValue.asNumber(to.get(0)).getFloat();
|
|
||||||
y2 = NumericValue.asNumber(to.get(1)).getFloat();
|
|
||||||
z2 = NumericValue.asNumber(to.get(2)).getFloat();
|
|
||||||
lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -394,24 +396,19 @@ 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);
|
||||||
Vec3d pos1 = new Vec3d(x1, y1, z1);
|
double density = Math.max(2.0, from.distanceTo(to) /50) / (a+0.1);
|
||||||
Vec3d pos2 = new Vec3d(x2, y2, z2);
|
|
||||||
double dx = x1-x2;
|
|
||||||
double dy = y1-y2;
|
|
||||||
double dz = z1-z2;
|
|
||||||
double density = Math.max(2.0, Math.sqrt(dx*dx+dy*dy+dz*dz) /50) / (a+0.1);
|
|
||||||
return p ->
|
return p ->
|
||||||
{
|
{
|
||||||
if (followEntity == -1)
|
if (followEntity == -1)
|
||||||
{
|
{
|
||||||
drawParticleLine(Collections.singletonList(p), particle, pos1, pos2, density);
|
drawParticleLine(Collections.singletonList(p), particle, from, to, density);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity);
|
Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity);
|
||||||
if (e == null) return;
|
if (e == null) return;
|
||||||
Vec3d rel1 = toAbsolute(e, x1, y1, z1);
|
Vec3d rel1 = toAbsolute(e, from);
|
||||||
Vec3d rel2 = toAbsolute(e, x2, y2, z2);
|
Vec3d rel2 = toAbsolute(e, to);
|
||||||
drawParticleLine(Collections.singletonList(p), particle, rel1, rel2, density);
|
drawParticleLine(Collections.singletonList(p), particle, rel1, rel2, density);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -421,13 +418,8 @@ public class ShapeDispatcher
|
|||||||
{
|
{
|
||||||
int hash = super.calcKey();
|
int hash = super.calcKey();
|
||||||
hash = 31*hash + 2;
|
hash = 31*hash + 2;
|
||||||
hash = 31*hash + Float.hashCode(x1);
|
hash = 31*hash + from.hashCode();
|
||||||
hash = 31*hash + Float.hashCode(y1);
|
hash = 31*hash + to.hashCode();
|
||||||
hash = 31*hash + Float.hashCode(z1);
|
|
||||||
hash = 31*hash + Float.hashCode(x2);
|
|
||||||
hash = 31*hash + Float.hashCode(y2);
|
|
||||||
hash = 31*hash + Float.hashCode(z2);
|
|
||||||
hash = 31*hash + Float.hashCode(lineWidth);
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,11 +427,7 @@ public class ShapeDispatcher
|
|||||||
public static class Sphere extends ExpiringShape
|
public static class Sphere extends ExpiringShape
|
||||||
{
|
{
|
||||||
private final Set<String> required = ImmutableSet.of("center", "radius");
|
private final Set<String> required = ImmutableSet.of("center", "radius");
|
||||||
private final Map<String, Value> optional = ImmutableMap.of(
|
private final Map<String, Value> optional = ImmutableMap.of("level", Value.ZERO);
|
||||||
"width", new NumericValue(2.0),
|
|
||||||
"level", Value.ZERO,
|
|
||||||
"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
|
||||||
@@ -450,23 +438,16 @@ public class ShapeDispatcher
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
float cx, cy, cz;
|
Vec3d center;
|
||||||
float radius;
|
float radius;
|
||||||
int level;
|
int level;
|
||||||
int subdivisions;
|
int subdivisions;
|
||||||
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)
|
||||||
{
|
{
|
||||||
super.init(options);
|
super.init(options);
|
||||||
List<Value> from = ((ListValue)options.get("center")).getItems();
|
center = vecFromValue(options.get("center"));
|
||||||
cx = NumericValue.asNumber(from.get(0)).getFloat();
|
|
||||||
cy = NumericValue.asNumber(from.get(1)).getFloat();
|
|
||||||
cz = NumericValue.asNumber(from.get(2)).getFloat();
|
|
||||||
radius = NumericValue.asNumber(options.get("radius")).getFloat();
|
radius = NumericValue.asNumber(options.get("radius")).getFloat();
|
||||||
level = NumericValue.asNumber(options.getOrDefault("level", optional.get("level"))).getInt();
|
level = NumericValue.asNumber(options.getOrDefault("level", optional.get("level"))).getInt();
|
||||||
subdivisions = level;
|
subdivisions = level;
|
||||||
@@ -474,12 +455,6 @@ public class ShapeDispatcher
|
|||||||
{
|
{
|
||||||
subdivisions = Math.max(10, (int)(10*Math.sqrt(radius)));
|
subdivisions = Math.max(10, (int)(10*Math.sqrt(radius)));
|
||||||
}
|
}
|
||||||
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
|
||||||
@@ -487,34 +462,31 @@ 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);
|
||||||
float pihalf = (float)(Math.PI / 180.0f);
|
|
||||||
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();
|
||||||
|
|
||||||
float ccx, ccy, ccz;
|
double ccx, ccy, ccz;
|
||||||
if (followEntity == -1)
|
if (followEntity == -1)
|
||||||
{
|
{
|
||||||
ccx = cx; ccy = cy; ccz = cz;
|
ccx = center.x; ccy = center.y; ccz = center.z;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity);
|
Entity e = p.getServer().getWorld(entityDimension).getEntityById(followEntity);
|
||||||
if (e == null) return;
|
if (e == null) return;
|
||||||
Vec3d rel1 = toAbsolute(e, cx, cy, cz);
|
Vec3d rel1 = toAbsolute(e, center);
|
||||||
ccx = (float)rel1.x; ccy = (float)rel1.y; ccz = (float)rel1.z;
|
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++)
|
||||||
{
|
{
|
||||||
//float theta = 360.0f*rand.nextFloat()*pihalf;
|
float theta = (float)Math.asin(rand.nextDouble()*2.0-1.0);
|
||||||
//float phi = 180f*rand.nextFloat()*pihalf;
|
float phi = (float)(2*Math.PI*rand.nextDouble());
|
||||||
float theta = (float)Math.asin(rand.nextFloat()*2.0-1.0);
|
|
||||||
float phi = (float)(2*Math.PI*rand.nextFloat());
|
|
||||||
|
|
||||||
float x = radius * MathHelper.cos(theta) * MathHelper.cos(phi);
|
double x = radius * MathHelper.cos(theta) * MathHelper.cos(phi);
|
||||||
float y = radius * MathHelper.cos(theta) * MathHelper.sin(phi);
|
double y = radius * MathHelper.cos(theta) * MathHelper.sin(phi);
|
||||||
float z = radius * MathHelper.sin(theta);
|
double z = radius * MathHelper.sin(theta);
|
||||||
world.spawnParticles(p, particle, true,
|
world.spawnParticles(p, particle, true,
|
||||||
x+ccx, y+ccy, z+ccz, 1,
|
x+ccx, y+ccy, z+ccz, 1,
|
||||||
0.0, 0.0, 0.0, 0.0);
|
0.0, 0.0, 0.0, 0.0);
|
||||||
@@ -526,86 +498,55 @@ public class ShapeDispatcher
|
|||||||
{
|
{
|
||||||
int hash = super.calcKey();
|
int hash = super.calcKey();
|
||||||
hash = 31*hash + 3;
|
hash = 31*hash + 3;
|
||||||
hash = 31*hash + Float.hashCode(cx);
|
hash = 31*hash + center.hashCode();
|
||||||
hash = 31*hash + Float.hashCode(cy);
|
hash = 31*hash + Double.hashCode(radius);
|
||||||
hash = 31*hash + Float.hashCode(cz);
|
|
||||||
hash = 31*hash + Float.hashCode(radius);
|
|
||||||
hash = 31*hash + level;
|
hash = 31*hash + level;
|
||||||
hash = 31*hash + Float.hashCode(lineWidth);
|
|
||||||
if (fa != 0.0) hash = 31*hash + fillColor;
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface Param
|
public static abstract class Param
|
||||||
{
|
{
|
||||||
Map<String, Function<Tag, Value>> decoders = new HashMap<String, Function<Tag, Value>>(){{
|
public static Map<String, Param> of = new HashMap<String, Param>(){{
|
||||||
put("shape", StringParam::decode);
|
|
||||||
put("dim", StringParam::decode);
|
|
||||||
put("duration", ShapeDispatcher::decodeInt);
|
|
||||||
put("color", ShapeDispatcher::decodeInt);
|
|
||||||
put("follow", EntityParam::decode);
|
|
||||||
|
|
||||||
put("from", Vec3Param::decode);
|
|
||||||
put("to", Vec3Param::decode);
|
|
||||||
put("width", ShapeDispatcher::decodeFloat);
|
|
||||||
put("fill", ShapeDispatcher::decodeInt);
|
|
||||||
put("center", Vec3Param::decode);
|
|
||||||
put("radius", ShapeDispatcher::decodeFloat);
|
|
||||||
put("level", ShapeDispatcher::decodeInt);
|
|
||||||
}};
|
|
||||||
Map<String, Param> coders = new HashMap<String, Param>(){{
|
|
||||||
put("player", new PlayerParam());
|
|
||||||
put("shape", new ShapeParam());
|
put("shape", new ShapeParam());
|
||||||
put("dim", new DimensionParam());
|
put("dim", new DimensionParam());
|
||||||
put("duration", new DurationParam());
|
put("duration", new PositiveIntParam("duration"));
|
||||||
put("color", new ColorParam());
|
put("color", new ColorParam("color"));
|
||||||
put("follow", new FollowParam());
|
put("follow", new EntityParam("follow"));
|
||||||
|
put("width", new PositiveFloatParam("width"));
|
||||||
|
put("fill", new ColorParam("fill"));
|
||||||
|
|
||||||
put("from", new FromParam());
|
put("from", new Vec3Param("from", false));
|
||||||
put("to", new ToParam());
|
put("to", new Vec3Param("to", true));
|
||||||
put("width", new WidthParam());
|
put("center", new Vec3Param("center", false));
|
||||||
put("fill", new FillColorParam());
|
put("radius", new PositiveFloatParam("radius"));
|
||||||
put("center", new CenterParam());
|
put("level", new PositiveIntParam("level"));
|
||||||
put("radius", new RadiusParam());
|
|
||||||
put("level", new LevelParam());
|
|
||||||
}};
|
}};
|
||||||
Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize
|
protected String id;
|
||||||
Value validate(Map<String, Value> options, CarpetContext cc, Value value); // makes sure the value is proper
|
protected Param(String id)
|
||||||
boolean appliesTo(ExpiringShape shape); // check if applies to the shape
|
|
||||||
String identify();
|
|
||||||
}
|
|
||||||
public static class PlayerParam implements Param
|
|
||||||
{
|
{
|
||||||
@Override // doesn't need to be converted
|
this.id = id;
|
||||||
public Tag toTag(Value value) { return null; }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
|
|
||||||
{
|
|
||||||
ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), value);
|
|
||||||
if (player == null)
|
|
||||||
throw new InternalExpressionException("'player' parameter needs to represent an existing player");
|
|
||||||
return new EntityValue(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public abstract Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize
|
||||||
public boolean appliesTo(ExpiringShape shape) { return true; }
|
public abstract Value validate(Map<String, Value> options, CarpetContext cc, Value value); // makes sure the value is proper
|
||||||
@Override
|
public abstract Value decode(Tag tag);
|
||||||
public String identify() { return "player"; }
|
|
||||||
|
|
||||||
public static Value decode(Tag tag) { throw new RuntimeException("player tag should not be passed to the client"); }
|
|
||||||
}
|
}
|
||||||
public abstract static class StringParam implements Param
|
|
||||||
|
public abstract static class StringParam extends Param
|
||||||
{
|
{
|
||||||
|
protected StringParam(String id) { super(id); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Tag toTag(Value value) { return StringTag.of(value.getString()); }
|
public Tag toTag(Value value) { return StringTag.of(value.getString()); }
|
||||||
public static Value decode(Tag tag) { return new StringValue(tag.asString()); }
|
public Value decode(Tag tag) { return new StringValue(tag.asString()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DimensionParam extends StringParam
|
public static class DimensionParam extends StringParam
|
||||||
{
|
{
|
||||||
|
protected DimensionParam() { super("dim"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
|
public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
|
||||||
{
|
{
|
||||||
@@ -614,13 +555,11 @@ public class ShapeDispatcher
|
|||||||
if (!dimOp.isPresent()) throw new InternalExpressionException("Unknown dimension "+dimStr);
|
if (!dimOp.isPresent()) throw new InternalExpressionException("Unknown dimension "+dimStr);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public boolean appliesTo(ExpiringShape shape) { return true; }
|
|
||||||
@Override
|
|
||||||
public String identify() { return "dim"; }
|
|
||||||
}
|
}
|
||||||
public static class ShapeParam extends StringParam
|
public static class ShapeParam extends StringParam
|
||||||
{
|
{
|
||||||
|
protected ShapeParam() { super("shape"); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
|
public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
|
||||||
{
|
{
|
||||||
@@ -629,74 +568,65 @@ public class ShapeDispatcher
|
|||||||
throw new InternalExpressionException("Unknown shape: "+shape);
|
throw new InternalExpressionException("Unknown shape: "+shape);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@Override
|
|
||||||
public boolean appliesTo(ExpiringShape shape) { return true; }
|
|
||||||
@Override
|
|
||||||
public String identify() { return "shape"; }
|
|
||||||
}
|
}
|
||||||
public static abstract class NumericParam implements Param
|
public static abstract class NumericParam extends Param
|
||||||
{
|
{
|
||||||
|
protected NumericParam(String id) { super(id); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
|
public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
|
||||||
{
|
{
|
||||||
if (!(value instanceof NumericValue))
|
if (!(value instanceof NumericValue))
|
||||||
throw new InternalExpressionException("'" + identify() + "' needs to be a number");
|
throw new InternalExpressionException("'" + id + "' needs to be a number");
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static abstract class PositiveParam extends NumericParam
|
public static abstract class PositiveParam extends NumericParam
|
||||||
{
|
{
|
||||||
|
protected PositiveParam(String id) { super(id); }
|
||||||
@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);
|
||||||
if (((NumericValue)ret).getDouble()<=0) throw new InternalExpressionException("'"+identify()+"' should be positive");
|
if (((NumericValue)ret).getDouble()<=0) throw new InternalExpressionException("'"+id+"' should be positive");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static abstract class PositiveFloatParam extends PositiveParam
|
public static class PositiveFloatParam extends PositiveParam
|
||||||
{
|
{
|
||||||
|
protected PositiveFloatParam(String id) { super(id); }
|
||||||
|
@Override
|
||||||
|
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).getFloat()); }
|
||||||
|
|
||||||
}
|
}
|
||||||
public static abstract class PositiveIntParam extends PositiveParam
|
public static class PositiveIntParam extends PositiveParam
|
||||||
{
|
{
|
||||||
|
protected PositiveIntParam(String id) { super(id); }
|
||||||
|
@Override
|
||||||
|
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).getInt()); }
|
||||||
|
|
||||||
}
|
}
|
||||||
public static Value decodeInt(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); }
|
|
||||||
public static Value decodeFloat(Tag tag) { return new NumericValue(((FloatTag)tag).getFloat()); }
|
public static class Vec3Param extends Param
|
||||||
public static class DurationParam extends PositiveIntParam
|
|
||||||
{
|
{
|
||||||
@Override
|
private boolean roundsUpForBlocks;
|
||||||
public boolean appliesTo(ExpiringShape shape) { return true; }
|
protected Vec3Param(String id, boolean doesRoundUpForBlocks)
|
||||||
@Override
|
{
|
||||||
public String identify() { return "duration"; }
|
super(id);
|
||||||
|
roundsUpForBlocks = doesRoundUpForBlocks;
|
||||||
}
|
}
|
||||||
public static class WidthParam extends PositiveFloatParam
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box || shape instanceof Line || shape instanceof Sphere; }
|
|
||||||
@Override
|
|
||||||
public String identify() { return "width"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static abstract class Vec3Param implements Param
|
|
||||||
{
|
|
||||||
|
|
||||||
public abstract boolean roundsUpForBlocks();
|
|
||||||
public abstract String identify();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
|
public Value validate(Map<String, Value> options, CarpetContext cc, Value value)
|
||||||
{
|
{
|
||||||
if (value instanceof BlockValue)
|
if (value instanceof BlockValue)
|
||||||
{
|
{
|
||||||
if (options.containsKey("follow"))
|
if (options.containsKey("follow"))
|
||||||
throw new InternalExpressionException(identify()+" parameter cannot use blocks as positions for relative positioning due to 'follow' attribute being present");
|
throw new InternalExpressionException(id+" parameter cannot use blocks as positions for relative positioning due to 'follow' attribute being present");
|
||||||
BlockPos pos = ((BlockValue) value).getPos();
|
BlockPos pos = ((BlockValue) value).getPos();
|
||||||
int offset = roundsUpForBlocks()?1:0;
|
int offset = roundsUpForBlocks?1:0;
|
||||||
return ListValue.of(
|
return ListValue.of(
|
||||||
new NumericValue(pos.getX()+offset),
|
new NumericValue(pos.getX()+offset),
|
||||||
new NumericValue(pos.getY()+offset),
|
new NumericValue(pos.getY()+offset),
|
||||||
@@ -706,18 +636,18 @@ public class ShapeDispatcher
|
|||||||
if (value instanceof ListValue)
|
if (value instanceof ListValue)
|
||||||
{
|
{
|
||||||
List<Value> values = ((ListValue) value).getItems();
|
List<Value> values = ((ListValue) value).getItems();
|
||||||
if (values.size()!=3) throw new InternalExpressionException("'"+identify()+"' requires 3 numerical values");
|
if (values.size()!=3) throw new InternalExpressionException("'"+id+"' requires 3 numerical values");
|
||||||
for (Value component : values)
|
for (Value component : values)
|
||||||
{
|
{
|
||||||
if (!(component instanceof NumericValue))
|
if (!(component instanceof NumericValue))
|
||||||
throw new InternalExpressionException("'"+identify()+"' requires 3 numerical values");
|
throw new InternalExpressionException("'"+id+"' requires 3 numerical values");
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
if (value instanceof EntityValue)
|
if (value instanceof EntityValue)
|
||||||
{
|
{
|
||||||
if (options.containsKey("follow"))
|
if (options.containsKey("follow"))
|
||||||
throw new InternalExpressionException(identify()+" parameter cannot use entity as positions for relative positioning due to 'follow' attribute being present");
|
throw new InternalExpressionException(id+" parameter cannot use entity as positions for relative positioning due to 'follow' attribute being present");
|
||||||
Entity e = ((EntityValue) value).getEntity();
|
Entity e = ((EntityValue) value).getEntity();
|
||||||
return ListValue.of(
|
return ListValue.of(
|
||||||
new NumericValue(e.getX()),
|
new NumericValue(e.getX()),
|
||||||
@@ -726,16 +656,16 @@ public class ShapeDispatcher
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
CarpetSettings.LOG.error("Value: "+value.getString());
|
CarpetSettings.LOG.error("Value: "+value.getString());
|
||||||
throw new InternalExpressionException("'"+identify()+"' requires a triple, block or entity to indicate position");
|
throw new InternalExpressionException("'"+id+"' requires a triple, block or entity to indicate position");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Value decode(Tag tag)
|
public Value decode(Tag tag)
|
||||||
{
|
{
|
||||||
CompoundTag ctag = (CompoundTag)tag;
|
CompoundTag ctag = (CompoundTag)tag;
|
||||||
return ListValue.of(
|
return ListValue.of(
|
||||||
new NumericValue(ctag.getFloat("x")),
|
new NumericValue(ctag.getDouble("x")),
|
||||||
new NumericValue(ctag.getFloat("y")),
|
new NumericValue(ctag.getDouble("y")),
|
||||||
new NumericValue(ctag.getFloat("z"))
|
new NumericValue(ctag.getDouble("z"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@@ -743,75 +673,28 @@ public class ShapeDispatcher
|
|||||||
{
|
{
|
||||||
List<Value> lv = ((ListValue)value).getItems();
|
List<Value> lv = ((ListValue)value).getItems();
|
||||||
CompoundTag tag = new CompoundTag();
|
CompoundTag tag = new CompoundTag();
|
||||||
tag.putFloat("x", NumericValue.asNumber(lv.get(0)).getFloat());
|
tag.putDouble("x", NumericValue.asNumber(lv.get(0)).getDouble());
|
||||||
tag.putFloat("y", NumericValue.asNumber(lv.get(1)).getFloat());
|
tag.putDouble("y", NumericValue.asNumber(lv.get(1)).getDouble());
|
||||||
tag.putFloat("z", NumericValue.asNumber(lv.get(2)).getFloat());
|
tag.putDouble("z", NumericValue.asNumber(lv.get(2)).getDouble());
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static class ColorParam extends NumericParam
|
public static class ColorParam extends NumericParam
|
||||||
{
|
{
|
||||||
|
protected ColorParam(String id)
|
||||||
|
{
|
||||||
|
super(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
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).getInt()); }
|
||||||
@Override
|
|
||||||
public boolean appliesTo(ExpiringShape shape) { return true; }
|
|
||||||
@Override
|
|
||||||
public String identify() { return "color"; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class FillColorParam extends ColorParam
|
public static class EntityParam extends Param
|
||||||
{
|
{
|
||||||
@Override
|
|
||||||
public boolean appliesTo(ExpiringShape shape) { return shape instanceof Box || shape instanceof Sphere; }
|
|
||||||
@Override
|
|
||||||
public String identify() { return "fill"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class FromParam extends Vec3Param
|
protected EntityParam(String id) { super(id); }
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean appliesTo(ExpiringShape shape) { return shape instanceof Line || shape instanceof Box; }
|
|
||||||
@Override
|
|
||||||
public boolean roundsUpForBlocks() { return false; }
|
|
||||||
@Override
|
|
||||||
public String identify() { return "from"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ToParam extends Vec3Param
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean appliesTo(ExpiringShape shape) { return (shape instanceof Line) || (shape instanceof Box); }
|
|
||||||
@Override
|
|
||||||
public boolean roundsUpForBlocks() { return true; }
|
|
||||||
@Override
|
|
||||||
public String identify() { return "to"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class CenterParam extends Vec3Param
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean appliesTo(ExpiringShape shape) { return (shape instanceof Sphere); }
|
|
||||||
@Override
|
|
||||||
public boolean roundsUpForBlocks() { return false; }
|
|
||||||
@Override
|
|
||||||
public String identify() { return "center"; }
|
|
||||||
}
|
|
||||||
public static class RadiusParam extends PositiveFloatParam
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean appliesTo(ExpiringShape shape) { return shape instanceof Sphere; }
|
|
||||||
@Override
|
|
||||||
public String identify() { return "radius"; }
|
|
||||||
}
|
|
||||||
public static class LevelParam extends PositiveIntParam
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public boolean appliesTo(ExpiringShape shape) { return shape instanceof Sphere; }
|
|
||||||
@Override
|
|
||||||
public String identify() { return "level"; }
|
|
||||||
}
|
|
||||||
public abstract static class EntityParam implements Param
|
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Tag toTag(Value value)
|
public Tag toTag(Value value)
|
||||||
@@ -825,22 +708,12 @@ public class ShapeDispatcher
|
|||||||
if (value instanceof EntityValue) return new NumericValue(((EntityValue) value).getEntity().getEntityId());
|
if (value instanceof EntityValue) return new NumericValue(((EntityValue) value).getEntity().getEntityId());
|
||||||
ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), value);
|
ServerPlayerEntity player = EntityValue.getPlayerByValue(cc.s.getMinecraftServer(), value);
|
||||||
if (player == null)
|
if (player == null)
|
||||||
throw new InternalExpressionException(identify()+" parameter needs to represent an entity or player");
|
throw new InternalExpressionException(id+" parameter needs to represent an entity or player");
|
||||||
return new NumericValue(player.getEntityId());
|
return new NumericValue(player.getEntityId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); }
|
||||||
public boolean appliesTo(ExpiringShape shape) { return true; }
|
|
||||||
|
|
||||||
public static Value decode(Tag tag) { return new NumericValue(((IntTag)tag).getInt()); }
|
|
||||||
}
|
}
|
||||||
public static class FollowParam extends EntityParam
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public String identify() { return "follow"; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static boolean isStraight(Vec3d from, Vec3d to, double density)
|
private static boolean isStraight(Vec3d from, Vec3d to, double density)
|
||||||
{
|
{
|
||||||
@@ -893,7 +766,7 @@ public class ShapeDispatcher
|
|||||||
if (isStraight(from, to, density)) return drawOptimizedParticleLine(players, particle, from, to, density);
|
if (isStraight(from, to, density)) return drawOptimizedParticleLine(players, particle, from, to, density);
|
||||||
double lineLengthSq = from.squaredDistanceTo(to);
|
double lineLengthSq = from.squaredDistanceTo(to);
|
||||||
if (lineLengthSq == 0) return 0;
|
if (lineLengthSq == 0) return 0;
|
||||||
Vec3d incvec = to.subtract(from).multiply(2*density/sqrt(lineLengthSq));
|
Vec3d incvec = to.subtract(from).multiply(2*density/MathHelper.sqrt(lineLengthSq));
|
||||||
int pcount = 0;
|
int pcount = 0;
|
||||||
for (Vec3d delta = new Vec3d(0.0,0.0,0.0);
|
for (Vec3d delta = new Vec3d(0.0,0.0,0.0);
|
||||||
delta.lengthSquared()<lineLengthSq;
|
delta.lengthSquared()<lineLengthSq;
|
||||||
|
|||||||
@@ -80,14 +80,16 @@ public class ShapesRenderer
|
|||||||
shapes.get(dimensionType).values().forEach(
|
shapes.get(dimensionType).values().forEach(
|
||||||
s ->
|
s ->
|
||||||
{
|
{
|
||||||
if ( s.shouldRender(dimensionType)) s.render2pass(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ);
|
if ( s.shouldRender(dimensionType))
|
||||||
|
s.renderFaces(tessellator, bufferBuilder, cameraX, cameraY, cameraZ);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
//lines
|
//lines
|
||||||
shapes.get(dimensionType).values().forEach(
|
shapes.get(dimensionType).values().forEach(
|
||||||
|
|
||||||
s -> {
|
s -> {
|
||||||
if ( s.shouldRender(dimensionType)) s.render(tessellator, bufferBuilder, (float) cameraX, (float) cameraY, (float) cameraZ);
|
if ( s.shouldRender(dimensionType))
|
||||||
|
s.renderLines(tessellator, bufferBuilder, cameraX, cameraY, cameraZ);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -143,14 +145,14 @@ public class ShapesRenderer
|
|||||||
protected T shape;
|
protected T shape;
|
||||||
protected MinecraftClient client;
|
protected MinecraftClient client;
|
||||||
long expiryTick;
|
long expiryTick;
|
||||||
float renderEpsilon = 0;
|
double renderEpsilon = 0;
|
||||||
public abstract void render(Tessellator tessellator, BufferBuilder builder, float cx, float cy, float cz );
|
public abstract void renderLines(Tessellator tessellator, BufferBuilder builder, double cx, double cy, double cz );
|
||||||
public void render2pass(Tessellator tessellator, BufferBuilder builder, float cx, float cy, float cz ) {};
|
public void renderFaces(Tessellator tessellator, BufferBuilder builder, double cx, double cy, double cz ) {}
|
||||||
protected RenderedShape(MinecraftClient client, T shape)
|
protected RenderedShape(MinecraftClient client, T shape)
|
||||||
{
|
{
|
||||||
this.shape = shape;
|
this.shape = shape;
|
||||||
expiryTick = client.world.getTime()+shape.getExpiry();
|
expiryTick = client.world.getTime()+shape.getExpiry();
|
||||||
renderEpsilon = (2+((float)shape.key())/Integer.MAX_VALUE)/1000;
|
renderEpsilon = (2+((double)shape.key())/Integer.MAX_VALUE)/1000;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,11 +172,11 @@ public class ShapesRenderer
|
|||||||
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(float x, float y, float z)
|
protected Vec3d relativiseRender(Vec3d vec)
|
||||||
{
|
{
|
||||||
if (shape.followEntity <= 0) return new Vec3d(x,y,z);
|
if (shape.followEntity <= 0) return vec;
|
||||||
Entity e = client.world.getEntityById(shape.followEntity);
|
Entity e = client.world.getEntityById(shape.followEntity);
|
||||||
return shape.toAbsolute(e, x, y, z);
|
return shape.toAbsolute(e, vec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,31 +189,30 @@ public class ShapesRenderer
|
|||||||
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz)
|
public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz)
|
||||||
{
|
{
|
||||||
if (shape.a == 0.0) return;
|
if (shape.a == 0.0) return;
|
||||||
Vec3d v1 = relativiseRender(shape.x1, shape.y1, shape.z1);
|
Vec3d v1 = relativiseRender(shape.from);
|
||||||
Vec3d v2 = relativiseRender(shape.x2, shape.y2, shape.z2);
|
Vec3d v2 = relativiseRender(shape.to);
|
||||||
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),
|
||||||
(float)v2.x-cx+renderEpsilon, (float)v2.y-cy+renderEpsilon, (float)v2.z-cz+renderEpsilon,
|
(float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon),
|
||||||
shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b
|
shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz)
|
public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz)
|
||||||
{
|
{
|
||||||
if (shape.fa == 0.0) return;
|
if (shape.fa == 0.0) return;
|
||||||
Vec3d v1 = relativiseRender(shape.x1, shape.y1, shape.z1);
|
Vec3d v1 = relativiseRender(shape.from);
|
||||||
Vec3d v2 = relativiseRender(shape.x2, shape.y2, shape.z2);
|
Vec3d v2 = relativiseRender(shape.to);
|
||||||
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),
|
||||||
(float)v2.x-cx+renderEpsilon, (float)v2.y-cy+renderEpsilon, (float)v2.z-cz+renderEpsilon,
|
(float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon),
|
||||||
shape.fr, shape.fg, shape.fb, shape.fa
|
shape.fr, shape.fg, shape.fb, shape.fa
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -223,14 +224,14 @@ public class ShapesRenderer
|
|||||||
super(client, (ShapeDispatcher.Line)shape);
|
super(client, (ShapeDispatcher.Line)shape);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz)
|
public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz)
|
||||||
{
|
{
|
||||||
Vec3d v1 = relativiseRender(shape.x1, shape.y1, shape.z1);
|
Vec3d v1 = relativiseRender(shape.from);
|
||||||
Vec3d v2 = relativiseRender(shape.x2, shape.y2, shape.z2);
|
Vec3d v2 = relativiseRender(shape.to);
|
||||||
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),
|
||||||
(float)v2.x-cx+renderEpsilon, (float)v2.y-cy+renderEpsilon, (float)v2.z-cz+renderEpsilon,
|
(float)(v2.x-cx+renderEpsilon), (float)(v2.y-cy+renderEpsilon), (float)(v2.z-cz+renderEpsilon),
|
||||||
shape.r, shape.g, shape.b, shape.a
|
shape.r, shape.g, shape.b, shape.a
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -243,25 +244,24 @@ public class ShapesRenderer
|
|||||||
super(client, (ShapeDispatcher.Sphere)shape);
|
super(client, (ShapeDispatcher.Sphere)shape);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz)
|
public void renderLines(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz)
|
||||||
{
|
{
|
||||||
if (shape.a == 0.0) return;
|
if (shape.a == 0.0) return;
|
||||||
Vec3d vc = relativiseRender(shape.cx, shape.cy, shape.cz);
|
Vec3d vc = relativiseRender(shape.center);
|
||||||
|
|
||||||
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),
|
||||||
shape.radius, shape.subdivisions,
|
shape.radius, shape.subdivisions,
|
||||||
shape.r, shape.g, shape.b, shape.a);
|
shape.r, shape.g, shape.b, shape.a);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void render2pass(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz)
|
public void renderFaces(Tessellator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz)
|
||||||
{
|
{
|
||||||
if (shape.fa == 0.0) return;
|
if (shape.fa == 0.0) return;
|
||||||
Vec3d vc = relativiseRender(shape.cx, shape.cy, shape.cz);
|
Vec3d vc = relativiseRender(shape.center);
|
||||||
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),
|
||||||
shape.radius, shape.subdivisions,
|
shape.radius, shape.subdivisions,
|
||||||
shape.fr, shape.fg, shape.fb, shape.fa);
|
shape.fr, shape.fg, shape.fb, shape.fa);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user