Skip to content

Instantly share code, notes, and snippets.

@mworzala
Created May 18, 2024 05:30
Show Gist options
  • Save mworzala/10c3b54295f64c0d946b1b3b073e6b20 to your computer and use it in GitHub Desktop.
Save mworzala/10c3b54295f64c0d946b1b3b073e6b20 to your computer and use it in GitHub Desktop.
package net.hollowcube.mapmaker.map.entity.impl;
import net.hollowcube.mapmaker.map.entity.MapEntity;
import net.hollowcube.mapmaker.map.util.NbtUtil;
import net.kyori.adventure.nbt.*;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.EntityType;
import net.minestom.server.entity.metadata.display.AbstractDisplayMeta;
import net.minestom.server.entity.metadata.display.BlockDisplayMeta;
import net.minestom.server.entity.metadata.display.ItemDisplayMeta;
import net.minestom.server.entity.metadata.display.TextDisplayMeta;
import net.minestom.server.item.ItemStack;
import net.minestom.server.utils.nbt.BinaryTagSerializer;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.UUID;
import static net.kyori.adventure.nbt.FloatBinaryTag.floatBinaryTag;
public class DisplayEntity extends MapEntity {
private static final BinaryTagSerializer<AbstractDisplayMeta.BillboardConstraints> BILLBOARD_CONSTRAINTS = BinaryTagSerializer.fromEnumStringable(AbstractDisplayMeta.BillboardConstraints.class);
protected DisplayEntity(@NotNull EntityType entityType, @NotNull UUID uuid) {
super(entityType, uuid);
setNoGravity(true);
hasPhysics = false;
}
@Override
public @NotNull AbstractDisplayMeta getEntityMeta() {
return (AbstractDisplayMeta) super.getEntityMeta();
}
@Override
public void writeData(CompoundBinaryTag.@NotNull Builder tag) {
super.writeData(tag);
final AbstractDisplayMeta meta = getEntityMeta();
if (meta.getTransformationInterpolationStartDelta() != 0)
tag.putInt("start_interpolation", meta.getTransformationInterpolationStartDelta());
if (meta.getTransformationInterpolationDuration() != 0)
tag.putInt("interpolation_duration", meta.getTransformationInterpolationDuration());
if (meta.getPosRotInterpolationDuration() != 0)
tag.putInt("teleport_duration", meta.getPosRotInterpolationDuration());
// Write transformation as decomposed form always.
var transformationTag = CompoundBinaryTag.builder();
var translation = meta.getTranslation();
if (!translation.isZero()) {
var elems = List.<BinaryTag>of(floatBinaryTag((float) translation.x()), floatBinaryTag((float) translation.y()), floatBinaryTag((float) translation.z()));
transformationTag.put("translation", ListBinaryTag.listBinaryTag(BinaryTagTypes.FLOAT, elems));
}
var scale = meta.getScale();
if (!scale.isZero()) {
var elems = List.<BinaryTag>of(floatBinaryTag((float) scale.x()), floatBinaryTag((float) scale.y()), floatBinaryTag((float) scale.z()));
transformationTag.put("scale", ListBinaryTag.listBinaryTag(BinaryTagTypes.FLOAT, elems));
}
var leftRotation = meta.getLeftRotation();
if (leftRotation[0] != 0 || leftRotation[1] != 0 || leftRotation[2] != 0 || leftRotation[3] != 0) {
var elems = List.<BinaryTag>of(floatBinaryTag(leftRotation[0]), floatBinaryTag(leftRotation[1]), floatBinaryTag(leftRotation[2]), floatBinaryTag(leftRotation[3]));
transformationTag.put("left_rotation", ListBinaryTag.listBinaryTag(BinaryTagTypes.FLOAT, elems));
}
var rightRotation = meta.getRightRotation();
if (rightRotation[0] != 0 || rightRotation[1] != 0 || rightRotation[2] != 0 || rightRotation[3] != 0) {
var elems = List.<BinaryTag>of(floatBinaryTag(rightRotation[0]), floatBinaryTag(rightRotation[1]), floatBinaryTag(rightRotation[2]), floatBinaryTag(rightRotation[3]));
transformationTag.put("right_rotation", ListBinaryTag.listBinaryTag(BinaryTagTypes.FLOAT, elems));
}
var transformation = transformationTag.build();
if (transformation.size() > 0) tag.put("transformation", transformation);
if (meta.getBillboardRenderConstraints() != AbstractDisplayMeta.BillboardConstraints.FIXED)
tag.put("billboard", BILLBOARD_CONSTRAINTS.write(meta.getBillboardRenderConstraints()));
//todo brightness override
if (meta.getViewRange() != 0)
tag.putFloat("view_range", meta.getViewRange());
if (meta.getShadowRadius() != 0)
tag.putFloat("shadow_radius", meta.getShadowRadius());
if (meta.getShadowStrength() != 0)
tag.putFloat("shadow_strength", meta.getShadowStrength());
if (meta.getWidth() != 0)
tag.putFloat("width", meta.getWidth());
if (meta.getHeight() != 0)
tag.putFloat("height", meta.getHeight());
if (meta.getGlowColorOverride() != 0)
tag.putInt("glow_color_override", meta.getGlowColorOverride());
}
@Override
public void readData(@NotNull CompoundBinaryTag tag) {
super.readData(tag);
final AbstractDisplayMeta meta = getEntityMeta();
if (tag.get("start_interpolation") instanceof NumberBinaryTag startInterpolation)
meta.setTransformationInterpolationStartDelta(startInterpolation.intValue());
if (tag.get("interpolation_duration") instanceof NumberBinaryTag interpolationDuration)
meta.setTransformationInterpolationDuration(interpolationDuration.intValue());
if (tag.get("teleport_duration") instanceof NumberBinaryTag teleportDuration)
meta.setPosRotInterpolationDuration(teleportDuration.intValue());
var transformationTag = tag.get("transformation");
if (transformationTag instanceof CompoundBinaryTag transform) {
if (transform.get("translation") instanceof ListBinaryTag translate && translate.size() == 3 && translate.elementType() == BinaryTagTypes.FLOAT)
meta.setTranslation(new Vec(translate.getFloat(0), translate.getFloat(1), translate.getFloat(2)));
if (transform.get("scale") instanceof ListBinaryTag scale && scale.size() == 3 && scale.elementType() == BinaryTagTypes.FLOAT)
meta.setScale(new Vec(scale.getFloat(0), scale.getFloat(1), scale.getFloat(2)));
if (transform.get("left_rotation") instanceof ListBinaryTag leftRot && leftRot.size() == 4 && leftRot.elementType() == BinaryTagTypes.FLOAT)
meta.setLeftRotation(new float[]{leftRot.getFloat(0), leftRot.getFloat(1), leftRot.getFloat(2), leftRot.getFloat(3)});
if (transform.get("right_rotation") instanceof ListBinaryTag rightRot && rightRot.size() == 4 && rightRot.elementType() == BinaryTagTypes.FLOAT)
meta.setRightRotation(new float[]{rightRot.getFloat(0), rightRot.getFloat(1), rightRot.getFloat(2), rightRot.getFloat(3)});
} else if (transformationTag instanceof ListBinaryTag transformation && transformation.size() == 16 && transformation.elementType() == BinaryTagTypes.FLOAT) {
// https://github.com/apache/commons-math/blob/ffcdf39f8fa7ccd19c5c21a73fccb90c753592cd/commons-math-legacy/src/main/java/org/apache/commons/math4/legacy/linear/SingularValueDecomposition.java#L53
throw new UnsupportedOperationException("SVD is not supported yet.");
}
if (tag.get("billboard") instanceof StringBinaryTag billboardName)
meta.setBillboardRenderConstraints(BILLBOARD_CONSTRAINTS.read(billboardName));
//todo brightness override
if (tag.get("view_range") instanceof NumberBinaryTag viewRange)
meta.setViewRange(viewRange.floatValue());
if (tag.get("shadow_radius") instanceof NumberBinaryTag shadowRadius)
meta.setShadowRadius(shadowRadius.floatValue());
if (tag.get("shadow_strength") instanceof NumberBinaryTag shadowStrength)
meta.setShadowStrength(shadowStrength.floatValue());
if (tag.get("width") instanceof NumberBinaryTag width)
meta.setWidth(width.floatValue());
if (tag.get("height") instanceof NumberBinaryTag height)
meta.setHeight(height.floatValue());
if (tag.get("glow_color_override") instanceof NumberBinaryTag glowColor)
meta.setGlowColorOverride(glowColor.intValue());
}
public static class Block extends DisplayEntity {
public Block(@NotNull UUID uuid) {
super(EntityType.BLOCK_DISPLAY, uuid);
}
@Override
public @NotNull BlockDisplayMeta getEntityMeta() {
return (BlockDisplayMeta) super.getEntityMeta();
}
@Override
public void writeData(CompoundBinaryTag.@NotNull Builder tag) {
super.writeData(tag);
final BlockDisplayMeta meta = getEntityMeta();
var block = net.minestom.server.instance.block.Block.fromStateId((short) meta.getBlockStateId());
if (block != null && !block.isAir())
tag.put("block_state", NbtUtil.BLOCK_COMPOUND.write(block));
}
@Override
public void readData(@NotNull CompoundBinaryTag tag) {
super.readData(tag);
final BlockDisplayMeta meta = getEntityMeta();
if (tag.get("block_state") instanceof CompoundBinaryTag blockState) {
var block = NbtUtil.BLOCK_COMPOUND.read(blockState);
if (!block.isAir()) meta.setBlockState(block.stateId());
}
}
}
public static class Item extends DisplayEntity {
private static final BinaryTagSerializer<ItemDisplayMeta.DisplayContext> DISPLAY_CONTEXT = BinaryTagSerializer.fromEnumStringable(ItemDisplayMeta.DisplayContext.class);
public Item(@NotNull UUID uuid) {
super(EntityType.ITEM_DISPLAY, uuid);
}
@Override
public @NotNull ItemDisplayMeta getEntityMeta() {
return (ItemDisplayMeta) super.getEntityMeta();
}
@Override
public void writeData(CompoundBinaryTag.@NotNull Builder tag) {
super.writeData(tag);
final ItemDisplayMeta meta = getEntityMeta();
var itemStack = meta.getItemStack();
if (!itemStack.isAir() && itemStack.amount() > 0)
tag.put("item", ItemStack.NBT_TYPE.write(itemStack));
if (meta.getDisplayContext() != ItemDisplayMeta.DisplayContext.NONE)
tag.put("item_display", DISPLAY_CONTEXT.write(meta.getDisplayContext()));
}
@Override
public void readData(@NotNull CompoundBinaryTag tag) {
super.readData(tag);
final ItemDisplayMeta meta = getEntityMeta();
if (tag.get("item") instanceof CompoundBinaryTag item)
meta.setItemStack(ItemStack.NBT_TYPE.read(item));
if (tag.get("item_display") instanceof StringBinaryTag itemDisplay)
meta.setDisplayContext(DISPLAY_CONTEXT.read(itemDisplay));
}
}
public static class Text extends DisplayEntity {
public Text(@NotNull UUID uuid) {
super(EntityType.TEXT_DISPLAY, uuid);
}
@Override
public @NotNull TextDisplayMeta getEntityMeta() {
return (TextDisplayMeta) super.getEntityMeta();
}
@Override
public void writeData(CompoundBinaryTag.@NotNull Builder tag) {
super.writeData(tag);
final TextDisplayMeta meta = getEntityMeta();
tag.putString("text", GsonComponentSerializer.gson().serialize(meta.getText()));
if (meta.getLineWidth() != 0)
tag.putInt("line_width", meta.getLineWidth());
if (meta.getBackgroundColor() != 0)
tag.putInt("background", meta.getBackgroundColor());
if (meta.getTextOpacity() != 0)
tag.putByte("text_opacity", (byte) meta.getTextOpacity());
if (meta.isShadow())
tag.putByte("shadow", (byte) 1);
if (meta.isSeeThrough())
tag.putByte("see_through", (byte) 1);
if (meta.isUseDefaultBackground())
tag.putByte("default_background", (byte) 1);
if (meta.isAlignLeft() && !meta.isAlignRight())
tag.putString("alignment", "left");
if (meta.isAlignRight() && !meta.isAlignLeft())
tag.putString("alignment", "right");
}
@Override
public void readData(@NotNull CompoundBinaryTag tag) {
super.readData(tag);
final TextDisplayMeta meta = getEntityMeta();
if (tag.get("text") instanceof StringBinaryTag text)
meta.setText(GsonComponentSerializer.gson().deserialize(text.value()));
if (tag.get("line_width") instanceof NumberBinaryTag lineWidth)
meta.setLineWidth(lineWidth.intValue());
if (tag.get("background") instanceof NumberBinaryTag background)
meta.setBackgroundColor(background.intValue());
if (tag.get("text_opacity") instanceof NumberBinaryTag textOpacity)
meta.setTextOpacity(textOpacity.byteValue());
if (tag.get("shadow") instanceof NumberBinaryTag shadow)
meta.setShadow(shadow.byteValue() != 0);
if (tag.get("see_through") instanceof NumberBinaryTag seeThrough)
meta.setSeeThrough(seeThrough.byteValue() != 0);
if (tag.get("default_background") instanceof NumberBinaryTag defaultBackground)
meta.setUseDefaultBackground(defaultBackground.byteValue() != 0);
if (tag.get("alignment") instanceof StringBinaryTag align) {
meta.setAlignLeft("left".equals(align.value()) || "center".equals(align.value()));
meta.setAlignRight("right".equals(align.value()) || "center".equals(align.value()));
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment