adding a shape that can display a item or a block (#1365)

added 'polygon', 'item' and 'block' to scarpet rendered shapes
This commit is contained in:
ch-yx authored and GitHub committed 2022-09-12 00:38:52 +02:00
1 parent c528695d1a
commit 179f5a6006
5 files changed
+868 -6

No files matched your search

+26
View File
@@ -91,6 +91,7 @@ Optional shared shape attributes:
value is `'xyz'`, meaning the shape will be drawn relatively to the entity in all three directions. Using `xz` for 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. Preceeding an axis instance makes so that the shape follows the entity, but stays at the same, absolute Y coordinate. Preceeding an axis
with `d`, like `dxdydz` would make so that entity position is treated discretely (rounded down). with `d`, like `dxdydz` would make so that entity position is treated discretely (rounded down).
* `toggleable` - if True, can toggle visibility by using F3+B. just like entities' hitbox.
Available shapes: Available shapes:
* `'line'` - draws a straight line between two points. * `'line'` - draws a straight line between two points.
@@ -142,6 +143,31 @@ Available shapes:
* `height` - height of the cyllinder, defaults to `0`, so flat disk. Can be negative. * `height` - height of the cyllinder, defaults to `0`, so flat disk. Can be negative.
* `level` - level of details, see `'sphere'`. * `level` - level of details, see `'sphere'`.
* `'polygon'`:
* Required attributes:
* `points` - list of points defining vertices of the polygon
* Optional attributes:
* `relative` - list of bools. vertices of the polygon that affected by 'follow'. Could be a single bools to affact allpoints too. Default means that every point is affacted.
* `mode` - how those points are connected. may be "polygon"(default),"strip" or "triangles". "polygon" means that it will be viewed as vertices of a polygon center on the first one. "strip" means that it will be viewed as a triangles strip. "triangles" means that it will be viewed as some triangles that are not related to each other (therefor length of `points` in this mode have to be a multiple of 3).
* `inner` - if `true` it will make the inner edges be drawn as well.
* `doublesided` - if `true` it will make the shapes visible from the back as well. Default is `true`.
* `'block'` \ `'item'`:
* Required attributes:
* `pos` - position of the object.
* `item` - the object to show. could have NBT. is a item tuple or a string-id (exclusive to `'item'`)
* `block` - the object to show. could have NBT. is a block value or a string-id (exclusive to `'block'`)
* Optional attributes:
* `facing` - object's direction, where its facing. Possible options are: `player` (it
always rotates to face the player), `north`(default), `south`, `east`, `west`, `up`, `down`
* `tilt`, `lean`, `turn` - additional rotations along all three axis. for `block`, it use its block center as the origin.
* `scale` - scale of it in 3 axis-direction. should be a number or a list of 3 numbers (x,y,z).
* `skylight`, `blocklight` - light level. omit it to use local light level. should between 0~15.
* `variant` - one of "none","third_person_left_hand","third_person_right_hand","first_person_left_hand",
"first_person_right_hand","head","gui","ground","fixed". In addition to the literal meaning, it can also be used to use special models of tridents and telescopes. (exclusive to `'item'`)
### `create_marker(text, pos, rotation?, block?, interactive?)` ### `create_marker(text, pos, rotation?, block?, interactive?)`
Spawns a (permanent) marker entity with text or block at position. Returns that entity for further manipulations. Spawns a (permanent) marker entity with text or block at position. Returns that entity for further manipulations.
@@ -0,0 +1,11 @@
package carpet.mixins;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import net.minecraft.client.model.ShulkerModel;
@Mixin(net.minecraft.client.renderer.blockentity.ShulkerBoxRenderer.class)
public interface ShulkerBoxAccessMixin {
@Accessor("model")
ShulkerModel getModel();
}
@@ -6,18 +6,26 @@ import carpet.script.exception.InternalExpressionException;
import carpet.script.exception.ThrowStatement; import carpet.script.exception.ThrowStatement;
import carpet.script.exception.Throwables; import carpet.script.exception.Throwables;
import carpet.script.language.Sys; import carpet.script.language.Sys;
import carpet.script.value.AbstractListValue;
import carpet.script.value.BlockValue; import carpet.script.value.BlockValue;
import carpet.script.value.BooleanValue; import carpet.script.value.BooleanValue;
import carpet.script.value.EntityValue; import carpet.script.value.EntityValue;
import carpet.script.value.FormattedTextValue; import carpet.script.value.FormattedTextValue;
import carpet.script.value.ListValue; import carpet.script.value.ListValue;
import carpet.script.value.MapValue; import carpet.script.value.MapValue;
import carpet.script.value.NBTSerializableValue;
import carpet.script.value.NumericValue; import carpet.script.value.NumericValue;
import carpet.script.value.StringValue; import carpet.script.value.StringValue;
import carpet.script.value.Value; import carpet.script.value.Value;
import carpet.script.value.ValueConversions;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat.Mode;
import com.mojang.brigadier.StringReader; import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.client.renderer.block.model.ItemTransforms.TransformType;
import net.minecraft.commands.arguments.ParticleArgument; import net.minecraft.commands.arguments.ParticleArgument;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@@ -29,8 +37,11 @@ import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.FloatTag; import net.minecraft.nbt.FloatTag;
import net.minecraft.nbt.IntTag; import net.minecraft.nbt.IntTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.StringTag; import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
import net.minecraft.nbt.NumericTag;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
@@ -40,12 +51,16 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource; import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@@ -249,6 +264,9 @@ public class ShapeDispatcher
put("sphere", creator(Sphere::new)); put("sphere", creator(Sphere::new));
put("cylinder", creator(Cylinder::new)); put("cylinder", creator(Cylinder::new));
put("label", creator(DisplayedText::new)); put("label", creator(DisplayedText::new));
put("polygon",creator(Polyface::new));
put("block",creator(()->new DisplayedSprite(false)));
put("item",creator(()->new DisplayedSprite(true)));
}}; }};
private static Function<Map<String, Value>,ExpiringShape> creator(Supplier<ExpiringShape> shapeFactory) private static Function<Map<String, Value>,ExpiringShape> creator(Supplier<ExpiringShape> shapeFactory)
{ {
@@ -271,6 +289,7 @@ public class ShapeDispatcher
protected boolean snapX, snapY, snapZ; protected boolean snapX, snapY, snapZ;
protected boolean discreteX, discreteY, discreteZ; protected boolean discreteX, discreteY, discreteZ;
protected ResourceKey<Level> shapeDimension; protected ResourceKey<Level> shapeDimension;
protected boolean needf3b;
protected ExpiringShape() { } protected ExpiringShape() { }
@@ -322,6 +341,11 @@ public class ShapeDispatcher
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;
needf3b = false;
if (options.containsKey("toggleable")) {
needf3b = options.get("toggleable").getBoolean();
}
key = 0; key = 0;
followEntity = -1; followEntity = -1;
shapeDimension = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(options.get("dim").getString())); shapeDimension = ResourceKey.create(Registry.DIMENSION_REGISTRY, new ResourceLocation(options.get("dim").getString()));
@@ -386,6 +410,7 @@ public class ShapeDispatcher
hash ^= shapeDimension.hashCode(); hash *= 1099511628211L; hash ^= shapeDimension.hashCode(); hash *= 1099511628211L;
hash ^= color; hash *= 1099511628211L; hash ^= color; hash *= 1099511628211L;
hash ^= followEntity; hash *= 1099511628211L; hash ^= followEntity; hash *= 1099511628211L;
hash ^= Boolean.hashCode(needf3b); hash *= 1099511628211L;
if (followEntity >= 0) if (followEntity >= 0)
{ {
hash ^= snapTo.hashCode(); hash *= 1099511628211L; hash ^= snapTo.hashCode(); hash *= 1099511628211L;
@@ -408,6 +433,7 @@ 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),
"toggleable", Value.FALSE,
"fill", new NumericValue(0xffffff00), "fill", new NumericValue(0xffffff00),
"snap", new StringValue("xyz") "snap", new StringValue("xyz")
); );
@@ -546,6 +572,140 @@ public class ShapeDispatcher
} }
} }
public static class DisplayedSprite extends ExpiringShape {
private final Set<String> required = Set.of("pos");
private final Map<String, Value> optional = Map.ofEntries(
entry("facing", new StringValue("north")),
entry("tilt", new NumericValue(0)),
entry("lean", new NumericValue(0)),
entry("turn", new NumericValue(0)),
entry("scale", ListValue.fromTriple(1,1,1)),
entry("blocklight", new NumericValue(-1)),
entry("skylight", new NumericValue(-1)));
private boolean isitem;
@Override
protected Set<String> requiredParams() {
return Sets.union(Sets.union(super.requiredParams(), required), Set.of(isitem ? "item" : "block"));
}
@Override
protected Set<String> optionalParams() {
return Sets.union(Sets.union(super.optionalParams(), optional.keySet()),isitem ? Set.of("variant") : Set.of());
}
public DisplayedSprite(boolean i) {
isitem = i;
}
Vec3 pos;
Direction facing;
float tilt;
float lean;
float turn;
float scale_z = 1.0f;
int light_fromblock;
int light_fromsky;
float scale_y = 1.0f;
float scale_x = 1.0f;
CompoundTag blockEntity;
BlockState blockState;
ItemStack item = null;
TransformType item_transform_type;
@Override
protected void init(Map<String, Value> options) {
super.init(options);
pos = vecFromValue(options.get("pos"));
if(!this.isitem){
blockState = ((BlockValue) options.get("block")).getBlockState();
blockEntity = ((BlockValue) options.get("block")).getData();
}else{
this.item = ItemStack.of(((NBTSerializableValue) options.get("item")).getCompoundTag());
}
light_fromblock = NumericValue
.asNumber(options.getOrDefault("blocklight", optional.get("blocklight"))).getInt();
if (light_fromblock > 15)
light_fromblock = 15;
light_fromsky = NumericValue.asNumber(options.getOrDefault("skylight", optional.get("skylight")))
.getInt();
if (light_fromsky > 15)
light_fromsky = 15;
item_transform_type = TransformType.NONE;
if(options.containsKey("variant")){
item_transform_type = TransformType.valueOf(options.get("variant").getString());
}
String dir = options.getOrDefault("facing", optional.get("facing")).getString();
facing = null;
switch (dir)
{
case "north": facing = Direction.NORTH; break;
case "south": facing = Direction.SOUTH; break;
case "east": facing = Direction.EAST; break;
case "west": facing = Direction.WEST; break;
case "up": facing = Direction.UP; break;
case "down": facing = Direction.DOWN; break;
}
tilt = NumericValue.asNumber(options.getOrDefault("tilt", optional.get("tilt"))).getFloat();
lean = NumericValue.asNumber(options.getOrDefault("lean", optional.get("lean"))).getFloat();
turn = NumericValue.asNumber(options.getOrDefault("turn", optional.get("turn"))).getFloat();
List<Value> scale = ((ListValue) options.getOrDefault("scale", optional.get("scale"))).unpack();
scale_y = NumericValue.asNumber(scale.get(1)).getFloat();
scale_x = NumericValue.asNumber(scale.get(0)).getFloat();
scale_z = NumericValue.asNumber(scale.get(2)).getFloat();
}
@Override
public Consumer<ServerPlayer> alternative() {
ParticleOptions locparticledata;
if(this.isitem){
if(Block.byItem(this.item.getItem()).defaultBlockState().isAir())
return p->{};
locparticledata = getParticleData("block_marker "+Registry.BLOCK.getKey(Block.byItem(this.item.getItem())));
}else{
locparticledata = getParticleData("block_marker "+Registry.BLOCK.getKey(this.blockState.getBlock()));
}
return p -> {
Vec3 v=relativiseRender(p.level, this.pos, 0);
p.getLevel().sendParticles(p,locparticledata , true,
v.x, v.y, v.z, 1,
0.0, 0.0, 0.0, 0.0);
};
}
@Override
public long calcKey() {
long hash = super.calcKey();
hash ^= 7; hash *= 1099511628211L;
hash ^= vec3dhash(pos); hash *= 1099511628211L;
if (facing!= null) hash ^= facing.hashCode(); hash *= 1099511628211L;
hash ^= Float.hashCode(tilt); hash *= 1099511628211L;
hash ^= Float.hashCode(lean); hash *= 1099511628211L;
hash ^= Float.hashCode(turn); hash *= 1099511628211L;
hash ^= Float.hashCode(scale_y); hash *= 1099511628211L;
hash ^= Float.hashCode(scale_z); hash *= 1099511628211L;
hash ^= Float.hashCode(scale_x); hash *= 1099511628211L;
hash ^= Float.hashCode(light_fromsky); hash *= 1099511628211L;
hash ^= Float.hashCode(light_fromblock); hash *= 1099511628211L;
if (blockEntity!= null) hash ^= blockEntity.toString().hashCode(); hash *= 1099511628211L;
if (blockState!= null) hash ^= blockState.hashCode(); hash *= 1099511628211L;
hash ^= ValueConversions.of(item).getString().hashCode(); hash *= 1099511628211L;
//hash ^= Boolean.hashCode(needf3b); hash *= 1099511628211L;
hash ^= item_transform_type.hashCode(); hash *= 1099511628211L;
return hash;
}
}
public static class Box extends ExpiringShape public static class Box extends ExpiringShape
{ {
@@ -625,6 +785,192 @@ public class ShapeDispatcher
} }
} }
public static class Polyface extends ExpiringShape
{
@Override
public long calcKey(){
long hash = super.calcKey();
hash ^= 6; hash *= 1099511628211L;
hash ^= mode.hashCode(); hash *= 1099511628211L;
hash ^= relative.hashCode(); hash *= 1099511628211L;
for (Vec3 i :vertex_list){
hash ^= vec3dhash(i);
hash *= 1099511628211L;
}
hash ^= Boolean.hashCode(doublesided); hash *= 1099511628211L;
hash ^= Integer.hashCode(vertex_list.size()); hash *= 1099511628211L;
hash ^= Boolean.hashCode(inneredges); hash *= 1099511628211L;
//hash ^= Boolean.hashCode(needf3b); hash *= 1099511628211L;
return hash;
}
ArrayList<Vec3> alter_point=null;
final Random random=new Random();
boolean doublesided;
ArrayList<Vec3> alter_point(ServerPlayer p){
if (alter_point!=null){
return alter_point;
}
alter_point=new ArrayList<>();
switch (mode) {
case TRIANGLES:
for (int i=0;i<vertex_list.size();i++){
Vec3 vecA=vertex_list.get(i);
if(relative.get(i)){
vecA=relativiseRender(p.level, vecA, 0);
}
i++;
Vec3 vecB=vertex_list.get(i);
if(relative.get(i)){
vecB=relativiseRender(p.level, vecB, 0);
}
i++;
Vec3 vecC=vertex_list.get(i);
if(relative.get(i)){
vecC=relativiseRender(p.level, vecC, 0);
}
alter_draw_triangles(vecA, vecB, vecC);
}
break;
case TRIANGLE_FAN:
Vec3 vec0=vertex_list.get(0);
if(relative.get(0)){
vec0=relativiseRender(p.level, vec0, 0);
}
Vec3 vec1=vertex_list.get(1);
if(relative.get(1)){
vec1=relativiseRender(p.level, vec1, 0);
}
for(int i=2;i<vertex_list.size();i++){
Vec3 vec=vertex_list.get(i);
if(relative.get(i)){
vec=relativiseRender(p.level, vec, 0);
}
alter_draw_triangles(vec0,vec1,vec);
vec1=vec;
}
break;
case TRIANGLE_STRIP:
Vec3 vecA=vertex_list.get(0);
if(relative.get(0)){
vecA=relativiseRender(p.level, vecA, 0);
}
Vec3 vecB=vertex_list.get(1);
if(relative.get(1)){
vecB=relativiseRender(p.level, vecB, 0);
}
//ArrayList<Vec3> last = new ArrayList<Vec3>();
//last.add(vecA);last.add(vecB);
for(int i=2;i<vertex_list.size();i++){
Vec3 vec=vertex_list.get(i);
if(relative.get(i)){
vec=relativiseRender(p.level, vec, 0);
}
//alter_draw_triangles(last.get(0),last.get(1),vec);
//last.remove(0);last.add(vec);
alter_draw_triangles(vecA,vecB,vec);
vecA=vecB;vecB=vec;
}
break;
default:
break;
}
return alter_point;
}
void alter_draw_triangles(Vec3 a,Vec3 b,Vec3 c){
Vec3 B = b.subtract(a);Vec3 C = c.subtract(a);
for(int i=0;i/8<B.cross(C).length();i++){
double x = random.nextDouble();double y = random.nextDouble();
alter_point.add(a.add(B.scale(x/2)).add(C.scale(y/2)));
if(x+y<1){
alter_point.add(a.add(B.scale((x+1)/2)).add(C.scale(y/2)));
}else{
x=1-x;y=1-y;
alter_point.add(a.add(B.scale(x/2)).add(C.scale((y+1)/2)));
}
}
}
@Override
public Consumer<ServerPlayer> alternative() {
final ParticleOptions locparticledata = getParticleData(String.format(Locale.ROOT ,"dust %.1f %.1f %.1f %.1f", fr, fg, fb, fa));
return p->{
if(p.level.dimension() != this.shapeDimension){return;}
if(!(fa>0.0f)){return;}
for(Vec3 v : alter_point(p)){
p.getLevel().sendParticles(p,locparticledata , true,
v.x, v.y, v.z, 1,
0.0, 0.0, 0.0, 0.0);
}
};
}
private final Set<String> required = Set.of("points");
private final Map<String, Value> optional = Map.ofEntries(
entry("relative",Value.NULL),
entry("mode", new StringValue("polygon")),
entry("inner", Value.TRUE),
entry("doublesided", Value.TRUE)
);
@Override
protected Set<String> requiredParams() { return Sets.union(super.requiredParams(), required); }
@Override
protected Set<String> optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); }
ArrayList<Vec3> vertex_list=new ArrayList<>();
Mode mode;
ArrayList<Boolean> relative=new ArrayList<>();
boolean inneredges;
@Override
protected void init(Map<String, Value> options)
{
super.init(options);
doublesided=options.getOrDefault("doublesided",optional.get("doublesided")).getBoolean();
if (options.get("points") instanceof AbstractListValue abl){
abl.forEach(x->vertex_list.add(vecFromValue(x)));
}
String _mode = options.getOrDefault("mode",optional.get("mode")).getString();
inneredges = options.getOrDefault("inner",optional.get("inner")).getBoolean();
if(vertex_list.size()<3){
throw new IllegalArgumentException("Unexpected vertex list size: " + vertex_list.size());
}else if(vertex_list.size()<4){
inneredges=false;
}
if("polygon".equals(_mode)){
mode=VertexFormat.Mode.TRIANGLE_FAN;
}else if("strip".equals(_mode)){
mode=VertexFormat.Mode.TRIANGLE_STRIP;
}else if("triangles".equals(_mode)){
mode=VertexFormat.Mode.TRIANGLES;
if(vertex_list.size()%3!=0){
throw new IllegalArgumentException("Unexpected vertex list size: " + vertex_list.size());
}
}
if (options.getOrDefault("relative",optional.get("relative")) instanceof AbstractListValue abl){
Iterator<Value> it = abl.iterator();
for(long i=0L;i<vertex_list.size();i++){
relative.add(it.hasNext()?it.next().getBoolean():false);//if part of it got defined.
}
}
else if(options.getOrDefault("relative",optional.get("relative")) instanceof BooleanValue boolv){
for(long i=0L;i<vertex_list.size();i++){
relative.add(boolv.getBoolean());//if it is a boolean.
}
}
else{
for(long i=0L;i<vertex_list.size();i++){
relative.add(true);//if there is nothing defined at all.
}
}
}
}
public static class Line extends ExpiringShape public static class Line extends ExpiringShape
{ {
private final Set<String> required = Set.of("from", "to"); private final Set<String> required = Set.of("from", "to");
@@ -858,11 +1204,30 @@ public class ShapeDispatcher
public static abstract class Param public static abstract class Param
{ {
public static Map<String, Param> of = new HashMap<String, Param>(){{ public static Map<String, Param> of = new HashMap<String, Param>(){{
put("mode",new StringChoiceParam("mode","polygon","strip","triangles"));
put("relative",new OptionalBoolListParam("relative"));
put("inner", new BoolParam("inner"));
put("shape", new ShapeParam()); put("shape", new ShapeParam());
put("dim", new DimensionParam()); put("dim", new DimensionParam());
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("variant",new StringChoiceParam("variant",
"NONE",
"THIRD_PERSON_LEFT_HAND",
"THIRD_PERSON_RIGHT_HAND",
"FIRST_PERSON_LEFT_HAND",
"FIRST_PERSON_RIGHT_HAND",
"HEAD",
"GUI",
"GROUND",
"FIXED")
{
public Value validate(Map o, MinecraftServer s, Value v)
{
return super.validate(o, s ,new StringValue(v.getString().toUpperCase(Locale.ROOT)));
}
});
put("snap", new StringChoiceParam("snap", put("snap", new StringChoiceParam("snap",
"xyz", "xz", "yz", "xy", "x", "y", "z", "xyz", "xz", "yz", "xy", "x", "y", "z",
"dxdydz", "dxdz", "dydz", "dxdy", "dx", "dy", "dz", "dxdydz", "dxdz", "dydz", "dxdy", "dx", "dy", "dz",
@@ -879,6 +1244,15 @@ public class ShapeDispatcher
put("radius", new PositiveFloatParam("radius")); put("radius", new PositiveFloatParam("radius"));
put("level", new PositiveIntParam("level")); put("level", new PositiveIntParam("level"));
put("height", new FloatParam("height")); put("height", new FloatParam("height"));
put("width", new FloatParam("width"));
put("scale", new Vec3Param("scale", false){
public Value validate(java.util.Map<String,Value> options, MinecraftServer server, Value value) {
if (value instanceof NumericValue vn){
value = ListValue.of(vn,vn,vn);
}
return super.validate(options, server, value);
};
});
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"));
put("text", new FormattedTextParam("text")); put("text", new FormattedTextParam("text"));
@@ -886,11 +1260,18 @@ public class ShapeDispatcher
put("size", new PositiveIntParam("size")); put("size", new PositiveIntParam("size"));
put("align", new StringChoiceParam("align", "center", "left", "right")); put("align", new StringChoiceParam("align", "center", "left", "right"));
put("block", new BlockParam("block"));
put("item", new ItemParam("item"));
put("blocklight", new NonNegativeIntParam("blocklight"));
put("skylight", new NonNegativeIntParam("skylight"));
put("indent", new FloatParam("indent")); put("indent", new FloatParam("indent"));
put("raise", new FloatParam("raise")); put("raise", new FloatParam("raise"));
put("tilt", new FloatParam("tilt")); put("tilt", new FloatParam("tilt"));
put("lean", new FloatParam("lean"));
put("turn", new FloatParam("turn"));
put("facing", new StringChoiceParam("axis", "player", "north", "south", "east", "west", "up", "down")); put("facing", new StringChoiceParam("axis", "player", "north", "south", "east", "west", "up", "down"));
put("doublesided", new BoolParam("doublesided")); put("doublesided", new BoolParam("doublesided"));
put("toggleable", new BoolParam("toggleable"));
}}; }};
protected String id; protected String id;
@@ -903,7 +1284,34 @@ public class ShapeDispatcher
public abstract Value validate(Map<String, Value> options, MinecraftServer server, Value value); // makes sure the value is proper public abstract Value validate(Map<String, Value> options, MinecraftServer server, Value value); // makes sure the value is proper
public abstract Value decode(Tag tag); public abstract Value decode(Tag tag);
} }
public static class OptionalBoolListParam extends Param
{
public OptionalBoolListParam(String id) { super(id); }
@Override
public Tag toTag(Value value) { return value.toTag(true);}
@Override
public Value decode(Tag tag) {
if(tag instanceof ListTag){
return ListValue.wrap(((ListTag)tag).stream().map(x->BooleanValue.of(((NumericTag)x).getAsNumber().doubleValue()!=0)));
}
if(tag instanceof ByteTag booltag){
return BooleanValue.of(booltag.getAsByte()!=0);
}
return Value.NULL;
}
@Override
public Value validate(Map<String, Value> options, MinecraftServer server, Value value) {
if(value instanceof AbstractListValue lv){
return ListValue.wrap(lv.unpack().stream().map(Value::getBoolean).map(BooleanValue::of));
}
if(value instanceof BooleanValue || value.isNull()){
return value;
}
return BooleanValue.of(value.getBoolean());
}
}
public abstract static class StringParam extends Param public abstract static class StringParam extends Param
{ {
protected StringParam(String id) { super(id); } protected StringParam(String id) { super(id); }
@@ -913,6 +1321,65 @@ public class ShapeDispatcher
@Override @Override
public Value decode(Tag tag) { return new StringValue(tag.getAsString()); } public Value decode(Tag tag) { return new StringValue(tag.getAsString()); }
} }
public static class BlockParam extends Param
{
protected BlockParam(String id) {
super(id);
}
@Override
public Value validate(Map<String, Value> options, MinecraftServer server, Value value)
{
if(value instanceof BlockValue blv){
return value;
}
return BlockValue.fromString(value.getString());
}
@Override
public Tag toTag(Value value) {
if(value instanceof BlockValue blv){
CompoundTag com = NbtUtils.writeBlockState(blv.getBlockState());
CompoundTag dataTag = blv.getData();
if (dataTag != null)
{
com.put("TileEntityData", dataTag);
}
return com;
}
return null;
}
@Override
public Value decode(Tag tag) {
BlockState bs = NbtUtils.readBlockState((CompoundTag) tag);
CompoundTag compoundTag2 = null;
if (((CompoundTag) tag).contains("TileEntityData", 10)) {
compoundTag2 = ((CompoundTag) tag).getCompound("TileEntityData");
}
return new BlockValue(bs, null, null, compoundTag2);
}
}
public static class ItemParam extends Param
{
protected ItemParam(String id) {
super(id);
}
@Override
public Value validate(Map<String, Value> options, MinecraftServer server, Value value)
{
ItemStack item=ValueConversions.getItemStackFromValue(value, true);
return new NBTSerializableValue(item.save(new CompoundTag()));
}
@Override
public Tag toTag(Value value) {
return ((NBTSerializableValue)value).getTag();
}
@Override
public Value decode(Tag tag) {
return new NBTSerializableValue(tag);
}
}
public static class TextParam extends StringParam public static class TextParam extends StringParam
{ {
protected TextParam(String id) protected TextParam(String id)
@@ -1211,9 +1678,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.valueOf(NumericValue.asNumber(lv.get(0), "x").getDouble())); tag.add(DoubleTag.valueOf(NumericValue.asNumber(coords.get(0), "x").getDouble()));
tag.add(DoubleTag.valueOf(NumericValue.asNumber(lv.get(1), "y").getDouble())); tag.add(DoubleTag.valueOf(NumericValue.asNumber(coords.get(1), "y").getDouble()));
tag.add(DoubleTag.valueOf(NumericValue.asNumber(lv.get(2), "z").getDouble())); tag.add(DoubleTag.valueOf(NumericValue.asNumber(coords.get(2), "z").getDouble()));
ltag.add(tag); ltag.add(tag);
} }
return ltag; return ltag;
@@ -2,30 +2,81 @@ package carpet.script.utils;
import carpet.CarpetSettings; import carpet.CarpetSettings;
import carpet.utils.CarpetProfiler; import carpet.utils.CarpetProfiler;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.blaze3d.vertex.VertexFormat; import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat.Mode;
import com.mojang.datafixers.util.Either;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.stream.Stream;
import net.minecraft.client.Camera; import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.resources.model.Material;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundSource;
import net.minecraft.tags.TagKey;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.ShulkerBoxBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.ShulkerBoxBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.entity.LevelEntityGetter;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.ticks.LevelTickAccess;
public class ShapesRenderer public class ShapesRenderer
{ {
@@ -41,6 +92,9 @@ public class ShapesRenderer
put("sphere", RenderedSphere::new); put("sphere", RenderedSphere::new);
put("cylinder", RenderedCylinder::new); put("cylinder", RenderedCylinder::new);
put("label", RenderedText::new); put("label", RenderedText::new);
put("polygon",RenderedPolyface::new);
put("block",(c,s)->new RenderedSprite(c,s).set_isitem(false));
put("item",(c,s)->new RenderedSprite(c,s).set_isitem(true));
}}; }};
public ShapesRenderer(Minecraft minecraftClient) public ShapesRenderer(Minecraft minecraftClient)
@@ -82,6 +136,7 @@ public class ShapesRenderer
double cameraX = camera.getPosition().x; double cameraX = camera.getPosition().x;
double cameraY = camera.getPosition().y; double cameraY = camera.getPosition().y;
double cameraZ = camera.getPosition().z; double cameraZ = camera.getPosition().z;
boolean hasf3b = client.getEntityRenderDispatcher().shouldRenderHitBoxes();
if (shapes.size() != 0) { synchronized (shapes) { if (shapes.size() != 0) { synchronized (shapes) {
shapes.get(dimensionType).long2ObjectEntrySet().removeIf( shapes.get(dimensionType).long2ObjectEntrySet().removeIf(
@@ -95,12 +150,12 @@ public class ShapesRenderer
// lines // lines
RenderSystem.lineWidth(0.5F); RenderSystem.lineWidth(0.5F);
shapes.get(dimensionType).values().forEach( s -> { shapes.get(dimensionType).values().forEach( s -> {
if (s.shouldRender(dimensionType)) s.renderLines(matrices, tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); if ( (!s.shape.needf3b ||hasf3b ) && s.shouldRender(dimensionType)) s.renderLines(matrices, tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick);
}); });
// faces // faces
RenderSystem.lineWidth(0.1F); RenderSystem.lineWidth(0.1F);
shapes.get(dimensionType).values().forEach(s -> { shapes.get(dimensionType).values().forEach(s -> {
if (s.shouldRender(dimensionType)) s.renderFaces(tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); if ( (!s.shape.needf3b ||hasf3b ) && s.shouldRender(dimensionType)) s.renderFaces(tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick);
}); });
RenderSystem.lineWidth(1.0F); RenderSystem.lineWidth(1.0F);
matrixStack.popPose(); matrixStack.popPose();
@@ -113,7 +168,7 @@ public class ShapesRenderer
entry -> entry.getValue().isExpired(currentTime) entry -> entry.getValue().isExpired(currentTime)
); );
labels.get(dimensionType).values().forEach(s -> { labels.get(dimensionType).values().forEach(s -> {
if (s.shouldRender(dimensionType)) s.renderLines(matrices, tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick); if ( (!s.shape.needf3b || hasf3b) && s.shouldRender(dimensionType)) s.renderLines(matrices, tessellator, bufferBuilder, cameraX, cameraY, cameraZ, partialTick);
}); });
}} }}
RenderSystem.enableCull(); RenderSystem.enableCull();
@@ -233,6 +288,175 @@ public class ShapesRenderer
} }
} }
public static class RenderedSprite extends RenderedShape<ShapeDispatcher.DisplayedSprite> {
private boolean isitem;
public RenderedSprite set_isitem(boolean isitem) {
this.isitem = isitem;
return this;
}
private BlockPos blockPos;
private BlockState blockState;
private BlockEntity BlockEntity = null;
protected RenderedSprite(Minecraft client, ShapeDispatcher.ExpiringShape shape) {
super(client, (ShapeDispatcher.DisplayedSprite) shape);
}
@Override
public void renderLines(PoseStack matrices, Tesselator tessellator, BufferBuilder builder, double cx, double cy,
double cz, float partialTick) {
if (shape.a == 0.0)
return;
Vec3 v1 = shape.relativiseRender(client.level, shape.pos, partialTick);
Camera camera1 = client.gameRenderer.getMainCamera();
matrices.pushPose();
if (!isitem)// blocks should use its center as the origin
matrices.translate(0.5, 0.5, 0.5);
matrices.translate(v1.x - cx, v1.y - cy, v1.z - cz);
if (shape.facing == null) {
matrices.mulPose(camera1.rotation());
matrices.mulPose(Vector3f.YP.rotationDegrees(180));
} else {
switch (shape.facing) {
case NORTH:
break;
case SOUTH:
matrices.mulPose(Vector3f.YP.rotationDegrees(180));
break;
case EAST:
matrices.mulPose(Vector3f.YP.rotationDegrees(270));
break;
case WEST:
matrices.mulPose(Vector3f.YP.rotationDegrees(90));
break;
case UP:
matrices.mulPose(Vector3f.XP.rotationDegrees(90));
break;
case DOWN:
matrices.mulPose(Vector3f.XP.rotationDegrees(-90));
break;
}
}
if (shape.tilt != 0.0f)
matrices.mulPose(Vector3f.ZP.rotationDegrees(shape.tilt));
if (shape.lean != 0.0f)
matrices.mulPose(Vector3f.XP.rotationDegrees(shape.lean));
if (shape.turn != 0.0f)
matrices.mulPose(Vector3f.YP.rotationDegrees(shape.turn));
matrices.scale(shape.scale_x, shape.scale_y, shape.scale_z);
if (!isitem)// blocks should use its center as the origin
matrices.translate(-0.5, -0.5, -0.5);
RenderSystem.depthMask(true);
RenderSystem.enableCull();
RenderSystem.enableDepthTest();
blockPos = new BlockPos(v1);
int light;
light = LightTexture.pack(
shape.light_fromblock < 0 ? client.level.getBrightness(LightLayer.BLOCK, blockPos)
: shape.light_fromblock,
shape.light_fromsky < 0 ? client.level.getBrightness(LightLayer.SKY, blockPos)
: shape.light_fromsky);
blockState = shape.blockState;
MultiBufferSource.BufferSource immediate = client.renderBuffers().bufferSource();
if (!isitem) {
// draw the block itself
if (blockState.getRenderShape() == RenderShape.MODEL) {
var bakedModel = client.getBlockRenderer().getBlockModel(blockState);
int color = client.getBlockColors().getColor(blockState,client.level,blockPos,0);
//dont know why there is a 0.
//see https://github.com/senseiwells/EssentialClient/blob/4db1f291936f502304791ee323f369c206b3021d/src/main/java/me/senseiwells/essentialclient/utils/render/RenderHelper.java#L464
float red = (color >> 16 & 0xFF) / 255.0F;
float green = (color >> 8 & 0xFF) / 255.0F;
float blue = (color & 0xFF) / 255.0F;
client.getBlockRenderer().getModelRenderer().renderModel(matrices.last(), immediate.getBuffer(ItemBlockRenderTypes.getRenderType(blockState, false)), blockState, bakedModel, red, green, blue, light, OverlayTexture.NO_OVERLAY);
}
// draw the block`s entity part
if (BlockEntity == null) {
if (blockState.getBlock() instanceof EntityBlock eb) {
BlockEntity = eb.newBlockEntity(blockPos, blockState);
if (BlockEntity != null) {
BlockEntity.setLevel(client.level);
if (shape.blockEntity != null)
BlockEntity.load(shape.blockEntity);
}
}
}
if (BlockEntity instanceof ShulkerBoxBlockEntity sbBlockEntity){
sbrender(sbBlockEntity, partialTick,
matrices, immediate, light, OverlayTexture.NO_OVERLAY);
}else
if (BlockEntity != null && client.getBlockEntityRenderDispatcher().getRenderer(BlockEntity) != null) {
client.getBlockEntityRenderDispatcher().getRenderer(BlockEntity).render(BlockEntity, partialTick,
matrices, immediate, light, OverlayTexture.NO_OVERLAY);
}
} else {
// draw item
if (shape.item != null)
client.getItemRenderer().renderStatic(shape.item, shape.item_transform_type, light,
OverlayTexture.NO_OVERLAY, matrices, immediate, (int) shape.key());
}
matrices.popPose();
immediate.endBatch();
RenderSystem.disableCull();
RenderSystem.disableDepthTest();
RenderSystem.depthMask(false);
}
@Override
public boolean stageDeux() {
return true;
}
// copy and modifiy a bit from net.minecraft.client.renderer.blockentity.ShulkerBoxRenderer.render
public void sbrender(ShulkerBoxBlockEntity shulkerBoxBlockEntity, float f, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, int j) {
Direction direction = Direction.UP;
if (shulkerBoxBlockEntity.hasLevel()) {
BlockState blockState = shulkerBoxBlockEntity.getBlockState();
if (blockState.getBlock() instanceof ShulkerBoxBlock) {
direction = blockState.getValue(ShulkerBoxBlock.FACING);
}
}
DyeColor dyeColor = shulkerBoxBlockEntity.getColor();
Material material;
if (dyeColor == null) {
material = Sheets.DEFAULT_SHULKER_TEXTURE_LOCATION;
} else {
material = (Material)Sheets.SHULKER_TEXTURE_LOCATION.get(dyeColor.getId());
}
poseStack.pushPose();
poseStack.translate(0.5, 0.5, 0.5);
float g = 0.9995F;
poseStack.scale(0.9995F, 0.9995F, 0.9995F);
poseStack.mulPose(direction.getRotation());
poseStack.scale(1.0F, -1.0F, -1.0F);
poseStack.translate(0.0, -1.0, 0.0);
ModelPart modelPart = ((carpet.mixins.ShulkerBoxAccessMixin)(Object)(client.getBlockEntityRenderDispatcher().getRenderer(BlockEntity))).getModel().getLid();
modelPart.setPos(0.0F, 24.0F - shulkerBoxBlockEntity.getProgress(f) * 0.5F * 16.0F, 0.0F);
modelPart.yRot = 270.0F * shulkerBoxBlockEntity.getProgress(f) * (float) (Math.PI / 180.0);
VertexConsumer vertexConsumer = material.buffer(multiBufferSource, RenderType::entityCutoutNoCull);
((carpet.mixins.ShulkerBoxAccessMixin)(Object)(client.getBlockEntityRenderDispatcher().getRenderer(BlockEntity))).getModel().renderToBuffer(poseStack, vertexConsumer, i, j, 1.0F, 1.0F, 1.0F, 1.0F);
poseStack.popPose();
}
}
public static class RenderedText extends RenderedShape<ShapeDispatcher.DisplayedText> public static class RenderedText extends RenderedShape<ShapeDispatcher.DisplayedText>
{ {
@@ -386,7 +610,140 @@ public class ShapesRenderer
); );
} }
} }
public static class RenderedPolyface extends RenderedShape<ShapeDispatcher.Polyface>
{
public RenderedPolyface(Minecraft client, ShapeDispatcher.ExpiringShape shape)
{
super(client, (ShapeDispatcher.Polyface)shape);
}
@Override
public void renderFaces(Tesselator tessellator, BufferBuilder bufferBuilder, double cx, double cy, double cz, float partialTick)
{
if(shape.fa==0){return;}
if (shape.doublesided)
RenderSystem.disableCull();
else
RenderSystem.enableCull();
bufferBuilder.begin(shape.mode, DefaultVertexFormat.POSITION_COLOR);
for(int i=0;i<shape.vertex_list.size();i++){
Vec3 vec=shape.vertex_list.get(i);
if(shape.relative.get(i)){
vec=shape.relativiseRender(client.level, vec, partialTick);
}
bufferBuilder.vertex(vec.x()-cx, vec.y()-cy, vec.z()-cz).color(shape.fr, shape.fg, shape.fb, shape.fa).endVertex();
}
tessellator.end();
RenderSystem.disableCull();
RenderSystem.depthMask(false);
//RenderSystem.enableDepthTest();
}
@Override
public void renderLines(PoseStack matrices, Tesselator tessellator, BufferBuilder builder, double cx, double cy,
double cz, float partialTick) {
if(shape.a==0){return;}
if (shape.mode==Mode.TRIANGLE_FAN){
builder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR);
Vec3 vec0=null;
for(int i=0;i<shape.vertex_list.size();i++){
Vec3 vec=shape.vertex_list.get(i);
if(shape.relative.get(i)){
vec=shape.relativiseRender(client.level, vec, partialTick);
}
if(i==0)vec0=vec;
builder.vertex(vec.x()-cx, vec.y()-cy, vec.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
}
builder.vertex(vec0.x()-cx, vec0.y()-cy, vec0.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
tessellator.end();
if(shape.inneredges){
builder.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR);
for(int i=1;i<shape.vertex_list.size()-1;i++){
Vec3 vec = shape.vertex_list.get(i);
if(shape.relative.get(i)){
vec=shape.relativiseRender(client.level, vec, partialTick);
}
builder.vertex(vec.x()-cx, vec.y()-cy, vec.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
builder.vertex(vec0.x()-cx, vec0.y()-cy, vec0.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
}
tessellator.end();
}
return;
}
if (shape.mode==Mode.TRIANGLE_STRIP){
//02468
//1357*
builder.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR);
Vec3 vec=shape.vertex_list.get(1);
if(shape.relative.get(1)){
vec=shape.relativiseRender(client.level, vec, partialTick);
}
builder.vertex(vec.x()-cx, vec.y()-cy, vec.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
int i;
for(i=0;i<shape.vertex_list.size();i+=2){
vec=shape.vertex_list.get(i);
if(shape.relative.get(i)){
vec=shape.relativiseRender(client.level, vec, partialTick);
}
builder.vertex(vec.x()-cx, vec.y()-cy, vec.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
}
i=shape.vertex_list.size()-1;
for(i-=1-i%2;i>0;i-=2){
vec=shape.vertex_list.get(i);
if(shape.relative.get(i)){
vec=shape.relativiseRender(client.level, vec, partialTick);
}
builder.vertex(vec.x()-cx, vec.y()-cy, vec.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
}
if(shape.inneredges){
for(i=2;i<shape.vertex_list.size()-1;i++){
vec=shape.vertex_list.get(i);
if(shape.relative.get(i)){
vec=shape.relativiseRender(client.level, vec, partialTick);
}
builder.vertex(vec.x()-cx, vec.y()-cy, vec.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
}
}
tessellator.end();
return;
}
if (shape.mode==Mode.TRIANGLES){
builder.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR);
for (int i=0;i<shape.vertex_list.size();i++){
Vec3 vecA=shape.vertex_list.get(i);
if(shape.relative.get(i)){
vecA=shape.relativiseRender(client.level, vecA, partialTick);
}
i++;
Vec3 vecB=shape.vertex_list.get(i);
if(shape.relative.get(i)){
vecB=shape.relativiseRender(client.level, vecB, partialTick);
}
i++;
Vec3 vecC=shape.vertex_list.get(i);
if(shape.relative.get(i)){
vecC=shape.relativiseRender(client.level, vecC, partialTick);
}
builder.vertex(vecA.x()-cx, vecA.y()-cy, vecA.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
builder.vertex(vecB.x()-cx, vecB.y()-cy, vecB.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
builder.vertex(vecB.x()-cx, vecB.y()-cy, vecB.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
builder.vertex(vecC.x()-cx, vecC.y()-cy, vecC.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
builder.vertex(vecC.x()-cx, vecC.y()-cy, vecC.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
builder.vertex(vecA.x()-cx, vecA.y()-cy, vecA.z()-cz).color(shape.r, shape.g, shape.b, shape.a).endVertex();
}
tessellator.end();
return;
}
}
}
public static class RenderedSphere extends RenderedShape<ShapeDispatcher.Sphere> public static class RenderedSphere extends RenderedShape<ShapeDispatcher.Sphere>
{ {
public RenderedSphere(Minecraft client, ShapeDispatcher.ExpiringShape shape) public RenderedSphere(Minecraft client, ShapeDispatcher.ExpiringShape shape)
+1
View File
@@ -189,6 +189,7 @@
"SlimeBlock_customStickyMixin" "SlimeBlock_customStickyMixin"
], ],
"client": [ "client": [
"ShulkerBoxAccessMixin",
"Timer_tickSpeedMixin", "Timer_tickSpeedMixin",
"MinecraftMixin", "MinecraftMixin",
"Minecraft_pausedShakeMixin", "Minecraft_pausedShakeMixin",