From dfeff51f65cb5a3dc0ee79da9a6f8a528be445e8 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sat, 6 Dec 2025 21:25:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0text=20display=E5=AE=B6?= =?UTF-8?q?=E5=85=B7=E5=85=83=E7=B4=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ItemDisplayBlockEntityElementConfig.java | 6 + .../TextDisplayBlockEntityElementConfig.java | 50 +++- .../entity/data/TextDisplayEntityData.java | 36 +++ .../BukkitFurnitureElementConfigs.java | 1 + .../element/ItemDisplayFurnitureElement.java | 3 +- .../ItemDisplayFurnitureElementConfig.java | 35 +-- .../element/TextDisplayFurnitureElement.java | 61 +++++ .../TextDisplayFurnitureElementConfig.java | 252 ++++++++++++++++++ .../src/main/resources/translations/en.yml | 1 + .../src/main/resources/translations/zh_cn.yml | 1 + .../element/BlockEntityElementConfigs.java | 9 +- .../entity/display/TextDisplayAlignment.java | 8 + .../element/FurnitureElementConfigs.java | 10 +- 13 files changed, 437 insertions(+), 36 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/TextDisplayFurnitureElement.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/TextDisplayFurnitureElementConfig.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/entity/display/TextDisplayAlignment.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElementConfig.java index 6b4c3e2e6..a4bca98cc 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElementConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemDisplayBlockEntityElementConfig.java @@ -2,6 +2,7 @@ package net.momirealms.craftengine.bukkit.block.entity.renderer.element; import com.google.common.base.Objects; import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; +import net.momirealms.craftengine.bukkit.entity.data.TextDisplayEntityData; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfig; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory; @@ -78,6 +79,9 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo if (glowColor != null) { ItemDisplayEntityData.SharedFlags.addEntityData((byte) 0x40, dataValues); ItemDisplayEntityData.GlowColorOverride.addEntityData(glowColor.color(), dataValues); + } else { + ItemDisplayEntityData.SharedFlags.addEntityData((byte) 0x0, dataValues); + ItemDisplayEntityData.GlowColorOverride.addEntityData(-1, dataValues); } ItemDisplayEntityData.DisplayedItem.addEntityData(item.apply(player).getLiteralObject(), dataValues); ItemDisplayEntityData.Scale.addEntityData(this.scale, dataValues); @@ -89,6 +93,8 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo ItemDisplayEntityData.ShadowStrength.addEntityData(this.shadowStrength, dataValues); if (this.blockLight != -1 && this.skyLight != -1) { ItemDisplayEntityData.BrightnessOverride.addEntityData(this.blockLight << 4 | this.skyLight << 20, dataValues); + } else { + ItemDisplayEntityData.BrightnessOverride.addEntityData(-1, dataValues); } ItemDisplayEntityData.ViewRange.addEntityData((float) (this.viewRange * player.displayEntityViewDistance()), dataValues); return dataValues; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElementConfig.java index dc6fa84d9..10b04468f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElementConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/TextDisplayBlockEntityElementConfig.java @@ -8,6 +8,7 @@ import net.momirealms.craftengine.bukkit.util.ComponentUtils; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfig; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory; import net.momirealms.craftengine.core.entity.display.Billboard; +import net.momirealms.craftengine.core.entity.display.TextDisplayAlignment; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.util.AdventureHelper; @@ -37,6 +38,13 @@ public class TextDisplayBlockEntityElementConfig implements BlockEntityElementCo public final int blockLight; public final int skyLight; public final float viewRange; + public final int lineWidth; + public final int backgroundColor; + public final byte opacity; + public final boolean hasShadow; + public final boolean isSeeThrough; + public final boolean useDefaultBackgroundColor; + public final TextDisplayAlignment alignment; public TextDisplayBlockEntityElementConfig(String text, Vector3f scale, @@ -49,7 +57,14 @@ public class TextDisplayBlockEntityElementConfig implements BlockEntityElementCo @Nullable Color glowColor, int blockLight, int skyLight, - float viewRange) { + float viewRange, + int lineWidth, + int backgroundColor, + byte opacity, + boolean hasShadow, + boolean isSeeThrough, + boolean useDefaultBackgroundColor, + TextDisplayAlignment alignment) { this.text = text; this.scale = scale; this.position = position; @@ -62,21 +77,37 @@ public class TextDisplayBlockEntityElementConfig implements BlockEntityElementCo this.blockLight = blockLight; this.skyLight = skyLight; this.viewRange = viewRange; + this.lineWidth = lineWidth; + this.backgroundColor = backgroundColor; + this.opacity = opacity; + this.hasShadow = hasShadow; + this.useDefaultBackgroundColor = useDefaultBackgroundColor; + this.alignment = alignment; + this.isSeeThrough = isSeeThrough; this.lazyMetadataPacket = player -> { List dataValues = new ArrayList<>(); if (glowColor != null) { - ItemDisplayEntityData.SharedFlags.addEntityData((byte) 0x40, dataValues); - ItemDisplayEntityData.GlowColorOverride.addEntityData(glowColor.color(), dataValues); + TextDisplayEntityData.SharedFlags.addEntityData((byte) 0x40, dataValues); + TextDisplayEntityData.GlowColorOverride.addEntityData(glowColor.color(), dataValues); + } else { + TextDisplayEntityData.SharedFlags.addEntityData((byte) 0x0, dataValues); + TextDisplayEntityData.GlowColorOverride.addEntityData(-1, dataValues); } TextDisplayEntityData.Text.addEntityData(ComponentUtils.adventureToMinecraft(text(player)), dataValues); TextDisplayEntityData.Scale.addEntityData(this.scale, dataValues); TextDisplayEntityData.RotationLeft.addEntityData(this.rotation, dataValues); TextDisplayEntityData.BillboardConstraints.addEntityData(this.billboard.id(), dataValues); TextDisplayEntityData.Translation.addEntityData(this.translation, dataValues); + TextDisplayEntityData.LineWidth.addEntityData(this.lineWidth, dataValues); + TextDisplayEntityData.BackgroundColor.addEntityData(this.backgroundColor, dataValues); + TextDisplayEntityData.TextOpacity.addEntityData(this.opacity, dataValues); + TextDisplayEntityData.TextDisplayMasks.addEntityData(TextDisplayEntityData.encodeMask(this.hasShadow, this.isSeeThrough, this.useDefaultBackgroundColor, this.alignment), dataValues); if (this.blockLight != -1 && this.skyLight != -1) { - ItemDisplayEntityData.BrightnessOverride.addEntityData(this.blockLight << 4 | this.skyLight << 20, dataValues); + TextDisplayEntityData.BrightnessOverride.addEntityData(this.blockLight << 4 | this.skyLight << 20, dataValues); + } else { + TextDisplayEntityData.BrightnessOverride.addEntityData(-1, dataValues); } - ItemDisplayEntityData.ViewRange.addEntityData((float) (this.viewRange * player.displayEntityViewDistance()), dataValues); + TextDisplayEntityData.ViewRange.addEntityData((float) (this.viewRange * player.displayEntityViewDistance()), dataValues); return dataValues; }; } @@ -170,7 +201,14 @@ public class TextDisplayBlockEntityElementConfig implements BlockEntityElementCo Optional.ofNullable(arguments.get("glow-color")).map(it -> Color.fromStrings(it.toString().split(","))).orElse(null), ResourceConfigUtils.getAsInt(brightness.getOrDefault("block-light", -1), "block-light"), ResourceConfigUtils.getAsInt(brightness.getOrDefault("sky-light", -1), "sky-light"), - ResourceConfigUtils.getAsFloat(arguments.getOrDefault("view-range", 1f), "view-range") + ResourceConfigUtils.getAsFloat(arguments.getOrDefault("view-range", 1f), "view-range"), + ResourceConfigUtils.getAsInt(arguments.getOrDefault("line-width", 200), "line-width"), + ResourceConfigUtils.getOrDefault(arguments.get("background-color"), o -> Color.fromStrings(o.toString().split(",")).color(), 0x40000000), + (byte) ResourceConfigUtils.getAsInt(arguments.getOrDefault("text-opacity", -1), "text-opacity"), + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("has-shadow", false), "has-shadow"), + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("is-see-through", false), "is-see-through"), + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("use-default-background-color", false), "use-default-background-color"), + ResourceConfigUtils.getAsEnum(arguments.get("alignment"), TextDisplayAlignment.class, TextDisplayAlignment.CENTER) ); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/TextDisplayEntityData.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/TextDisplayEntityData.java index 73a801d3b..840dde225 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/TextDisplayEntityData.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/TextDisplayEntityData.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.bukkit.entity.data; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; +import net.momirealms.craftengine.core.entity.display.TextDisplayAlignment; public class TextDisplayEntityData extends DisplayEntityData { public static final TextDisplayEntityData Text = new TextDisplayEntityData<>(TextDisplayEntityData.class, EntityDataValue.Serializers$COMPONENT, CoreReflections.instance$Component$empty); @@ -12,4 +13,39 @@ public class TextDisplayEntityData extends DisplayEntityData { public TextDisplayEntityData(Class clazz, Object serializer, T defaultValue) { super(clazz, serializer, defaultValue); } + + public static final int HAS_SHADOW = 0x01; + public static final int IS_SEE_THROUGH = 0x02; + public static final int USE_DEFAULT_BG_COLOR = 0x04; + private static final int LEFT_ALIGNMENT = 0x08; // 8 + private static final int RIGHT_ALIGNMENT = 0x10; // 16 + + public static byte encodeMask(boolean hasShadow, boolean isSeeThrough, boolean useDefaultBackground, TextDisplayAlignment alignment) { + int bitMask = 0; + + if (hasShadow) { + bitMask |= HAS_SHADOW; + } + if (isSeeThrough) { + bitMask |= IS_SEE_THROUGH; + } + if (useDefaultBackground) { + bitMask |= USE_DEFAULT_BG_COLOR; + } + + switch (alignment) { + case CENTER: // CENTER + break; + case LEFT: // LEFT + bitMask |= LEFT_ALIGNMENT; + break; + case RIGHT: // RIGHT + bitMask |= RIGHT_ALIGNMENT; + break; + default: + throw new IllegalArgumentException("Invalid alignment value"); + } + + return (byte) bitMask; + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/BukkitFurnitureElementConfigs.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/BukkitFurnitureElementConfigs.java index 4ce2d57f2..aac2804da 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/BukkitFurnitureElementConfigs.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/BukkitFurnitureElementConfigs.java @@ -6,6 +6,7 @@ public class BukkitFurnitureElementConfigs extends FurnitureElementConfigs { static { register(ITEM_DISPLAY, ItemDisplayFurnitureElementConfig.FACTORY); + register(TEXT_DISPLAY, TextDisplayFurnitureElementConfig.FACTORY); } private BukkitFurnitureElementConfigs() {} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElement.java index 8557e6493..b21d957e0 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElement.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElement.java @@ -8,6 +8,7 @@ import net.momirealms.craftengine.core.entity.furniture.Furniture; import net.momirealms.craftengine.core.entity.furniture.FurnitureColorSource; import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement; import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.WorldPosition; @@ -29,7 +30,7 @@ public class ItemDisplayFurnitureElement implements FurnitureElement { WorldPosition furniturePos = furniture.position(); Vec3d position = Furniture.getRelativePosition(furniturePos, config.position()); this.position = new WorldPosition(furniturePos.world, position.x, position.y, position.z, furniturePos.xRot, furniturePos.yRot); - this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(entityId); }}); + this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(MiscUtils.init(new IntArrayList(), a -> a.add(entityId))); this.colorSource = furniture.dataAccessor.getColorSource(); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java index d5658154c..dabbfdc1f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java @@ -101,17 +101,17 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig ItemDisplayEntityData.GlowColorOverride.addEntityData(glowColor.color(), dataValues); } ItemDisplayEntityData.DisplayedItem.addEntityData(itemFunction.apply(player, source).getLiteralObject(), dataValues); - ItemDisplayEntityData.Scale.addEntityData(this.scale, dataValues); - ItemDisplayEntityData.RotationLeft.addEntityData(this.rotation, dataValues); - ItemDisplayEntityData.BillboardConstraints.addEntityData(this.billboard.id(), dataValues); - ItemDisplayEntityData.Translation.addEntityData(this.translation, dataValues); - ItemDisplayEntityData.DisplayType.addEntityData(this.displayContext.id(), dataValues); - ItemDisplayEntityData.ShadowRadius.addEntityData(this.shadowRadius, dataValues); - ItemDisplayEntityData.ShadowStrength.addEntityData(this.shadowStrength, dataValues); + ItemDisplayEntityData.Scale.addEntityDataIfNotDefaultValue(this.scale, dataValues); + ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(this.rotation, dataValues); + ItemDisplayEntityData.BillboardConstraints.addEntityDataIfNotDefaultValue(this.billboard.id(), dataValues); + ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(this.translation, dataValues); + ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(this.displayContext.id(), dataValues); + ItemDisplayEntityData.ShadowRadius.addEntityDataIfNotDefaultValue(this.shadowRadius, dataValues); + ItemDisplayEntityData.ShadowStrength.addEntityDataIfNotDefaultValue(this.shadowStrength, dataValues); if (this.blockLight != -1 && this.skyLight != -1) { ItemDisplayEntityData.BrightnessOverride.addEntityData(this.blockLight << 4 | this.skyLight << 20, dataValues); } - ItemDisplayEntityData.ViewRange.addEntityData((float) (this.viewRange * player.displayEntityViewDistance()), dataValues); + ItemDisplayEntityData.ViewRange.addEntityDataIfNotDefaultValue((float) (this.viewRange * player.displayEntityViewDistance()), dataValues); return dataValues; }; } @@ -217,23 +217,4 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig ); } } - - @Override - public String toString() { - return "ItemDisplayFurnitureElementConfig{" + - "metadata=" + metadata + - ", itemId=" + itemId + - ", scale=" + scale + - ", position=" + position + - ", translation=" + translation + - ", xRot=" + xRot + - ", yRot=" + yRot + - ", rotation=" + rotation + - ", displayContext=" + displayContext + - ", billboard=" + billboard + - ", shadowRadius=" + shadowRadius + - ", shadowStrength=" + shadowStrength + - ", applyDyedColor=" + applyDyedColor + - '}'; - } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/TextDisplayFurnitureElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/TextDisplayFurnitureElement.java new file mode 100644 index 000000000..eb2771d4b --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/TextDisplayFurnitureElement.java @@ -0,0 +1,61 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.element; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.FurnitureColorSource; +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.util.MiscUtils; +import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.WorldPosition; + +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; + +public class TextDisplayFurnitureElement implements FurnitureElement { + private final TextDisplayFurnitureElementConfig config; + private final WorldPosition position; + private final int entityId; + private final Object despawnPacket; + private final UUID uuid = UUID.randomUUID(); + + public TextDisplayFurnitureElement(Furniture furniture, TextDisplayFurnitureElementConfig config) { + this.config = config; + this.entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); + WorldPosition furniturePos = furniture.position(); + Vec3d position = Furniture.getRelativePosition(furniturePos, config.position()); + this.position = new WorldPosition(furniturePos.world, position.x, position.y, position.z, furniturePos.xRot, furniturePos.yRot); + this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(MiscUtils.init(new IntArrayList(), a -> a.add(entityId))); + } + + @Override + public void show(Player player) { + player.sendPacket(FastNMS.INSTANCE.constructor$ClientboundBundlePacket(List.of( + FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + this.entityId, this.uuid, + this.position.x, this.position.y, this.position.z, 0, this.position.yRot, + MEntityTypes.TEXT_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0 + ), + FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadata.apply(player)) + )), false); + } + + @Override + public void hide(Player player) { + player.sendPacket(this.despawnPacket, false); + } + + @Override + public int[] virtualEntityIds() { + return new int[] {this.entityId}; + } + + @Override + public void collectVirtualEntityId(Consumer collector) { + collector.accept(this.entityId); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/TextDisplayFurnitureElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/TextDisplayFurnitureElementConfig.java new file mode 100644 index 000000000..5c2ae4b7e --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/TextDisplayFurnitureElementConfig.java @@ -0,0 +1,252 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.element; + +import net.momirealms.craftengine.bukkit.entity.data.TextDisplayEntityData; +import net.momirealms.craftengine.bukkit.util.ComponentUtils; +import net.momirealms.craftengine.core.entity.display.Billboard; +import net.momirealms.craftengine.core.entity.display.ItemDisplayContext; +import net.momirealms.craftengine.core.entity.display.TextDisplayAlignment; +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig; +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigFactory; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.context.NetworkTextReplaceContext; +import net.momirealms.craftengine.core.util.AdventureHelper; +import net.momirealms.craftengine.core.util.Color; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.joml.Quaternionf; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +public class TextDisplayFurnitureElementConfig implements FurnitureElementConfig { + public static final Factory FACTORY = new Factory(); + public final Function> metadata; + public final String text; + public final Vector3f scale; + public final Vector3f position; + public final Vector3f translation; + public final float xRot; + public final float yRot; + public final Quaternionf rotation; + public final ItemDisplayContext displayContext; + public final Billboard billboard; + public final float shadowRadius; + public final float shadowStrength; + public final Color glowColor; + public final int blockLight; + public final int skyLight; + public final float viewRange; + public final int lineWidth; + public final int backgroundColor; + public final byte opacity; + public final boolean hasShadow; + public final boolean isSeeThrough; + public final boolean useDefaultBackgroundColor; + public final TextDisplayAlignment alignment; + + public TextDisplayFurnitureElementConfig(String text, + Vector3f scale, + Vector3f position, + Vector3f translation, + float xRot, + float yRot, + Quaternionf rotation, + ItemDisplayContext displayContext, + Billboard billboard, + float shadowRadius, + float shadowStrength, + @Nullable Color glowColor, + int blockLight, + int skyLight, + float viewRange, + int lineWidth, + int backgroundColor, + byte opacity, + boolean hasShadow, + boolean isSeeThrough, + boolean useDefaultBackgroundColor, + TextDisplayAlignment alignment) { + this.text = text; + this.scale = scale; + this.position = position; + this.translation = translation; + this.xRot = xRot; + this.yRot = yRot; + this.rotation = rotation; + this.displayContext = displayContext; + this.billboard = billboard; + this.shadowRadius = shadowRadius; + this.shadowStrength = shadowStrength; + this.glowColor = glowColor; + this.blockLight = blockLight; + this.skyLight = skyLight; + this.viewRange = viewRange; + this.lineWidth = lineWidth; + this.backgroundColor = backgroundColor; + this.opacity = opacity; + this.hasShadow = hasShadow; + this.useDefaultBackgroundColor = useDefaultBackgroundColor; + this.alignment = alignment; + this.isSeeThrough = isSeeThrough; + this.metadata = (player) -> { + List dataValues = new ArrayList<>(); + if (glowColor != null) { + TextDisplayEntityData.SharedFlags.addEntityData((byte) 0x40, dataValues); + TextDisplayEntityData.GlowColorOverride.addEntityData(glowColor.color(), dataValues); + } + TextDisplayEntityData.Scale.addEntityDataIfNotDefaultValue(this.scale, dataValues); + TextDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(this.rotation, dataValues); + TextDisplayEntityData.BillboardConstraints.addEntityDataIfNotDefaultValue(this.billboard.id(), dataValues); + TextDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(this.translation, dataValues); + TextDisplayEntityData.ShadowRadius.addEntityDataIfNotDefaultValue(this.shadowRadius, dataValues); + TextDisplayEntityData.ShadowStrength.addEntityDataIfNotDefaultValue(this.shadowStrength, dataValues); + TextDisplayEntityData.Text.addEntityData(ComponentUtils.adventureToMinecraft(AdventureHelper.miniMessage().deserialize(this.text, NetworkTextReplaceContext.of(player).tagResolvers())), dataValues); + TextDisplayEntityData.LineWidth.addEntityDataIfNotDefaultValue(this.lineWidth, dataValues); + TextDisplayEntityData.BackgroundColor.addEntityDataIfNotDefaultValue(this.backgroundColor, dataValues); + TextDisplayEntityData.TextOpacity.addEntityDataIfNotDefaultValue(this.opacity, dataValues); + TextDisplayEntityData.TextDisplayMasks.addEntityDataIfNotDefaultValue(TextDisplayEntityData.encodeMask(this.hasShadow, this.isSeeThrough, this.useDefaultBackgroundColor, this.alignment), dataValues); + if (this.blockLight != -1 && this.skyLight != -1) { + TextDisplayEntityData.BrightnessOverride.addEntityData(this.blockLight << 4 | this.skyLight << 20, dataValues); + } + TextDisplayEntityData.ViewRange.addEntityDataIfNotDefaultValue((float) (this.viewRange * player.displayEntityViewDistance()), dataValues); + return dataValues; + }; + } + + public Vector3f scale() { + return this.scale; + } + + public Vector3f position() { + return this.position; + } + + public Vector3f translation() { + return this.translation; + } + + public float xRot() { + return this.xRot; + } + + public float yRot() { + return this.yRot; + } + + public Quaternionf rotation() { + return this.rotation; + } + + public ItemDisplayContext displayContext() { + return this.displayContext; + } + + public Billboard billboard() { + return this.billboard; + } + + public float shadowRadius() { + return this.shadowRadius; + } + + public float shadowStrength() { + return this.shadowStrength; + } + + public Function> metadata() { + return this.metadata; + } + + @Nullable + public Color glowColor() { + return this.glowColor; + } + + public int blockLight() { + return this.blockLight; + } + + public int skyLight() { + return this.skyLight; + } + + public float viewRange() { + return this.viewRange; + } + + public String text() { + return this.text; + } + + public int lineWidth() { + return this.lineWidth; + } + + public int backgroundColor() { + return this.backgroundColor; + } + + public byte opacity() { + return this.opacity; + } + + public boolean hasShadow() { + return this.hasShadow; + } + + public boolean isSeeThrough() { + return this.isSeeThrough; + } + + public boolean useDefaultBackgroundColor() { + return this.useDefaultBackgroundColor; + } + + public TextDisplayAlignment alignment() { + return this.alignment; + } + + @Override + public TextDisplayFurnitureElement create(@NotNull Furniture furniture) { + return new TextDisplayFurnitureElement(furniture, this); + } + + public static class Factory implements FurnitureElementConfigFactory { + + @Override + public TextDisplayFurnitureElementConfig create(Map arguments) { + String text = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("text"), "warning.config.furniture.element.text_display.missing_text"); + Map brightness = ResourceConfigUtils.getAsMap(arguments.getOrDefault("brightness", Map.of()), "brightness"); + return new TextDisplayFurnitureElementConfig( + text, + ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("scale", 1f), "scale"), + ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0f), "position"), + ResourceConfigUtils.getAsVector3f(arguments.get("translation"), "translation"), + ResourceConfigUtils.getAsFloat(arguments.getOrDefault("pitch", 0f), "pitch"), + ResourceConfigUtils.getAsFloat(arguments.getOrDefault("yaw", 0f), "yaw"), + ResourceConfigUtils.getAsQuaternionf(arguments.getOrDefault("rotation", 0f), "rotation"), + ResourceConfigUtils.getAsEnum(ResourceConfigUtils.get(arguments, "display-context", "display-transform"), ItemDisplayContext.class, ItemDisplayContext.NONE), + ResourceConfigUtils.getAsEnum(arguments.get("billboard"), Billboard.class, Billboard.FIXED), + ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-radius", 0f), "shadow-radius"), + ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-strength", 1f), "shadow-strength"), + Optional.ofNullable(arguments.get("glow-color")).map(it -> Color.fromStrings(it.toString().split(","))).orElse(null), + ResourceConfigUtils.getAsInt(brightness.getOrDefault("block-light", -1), "block-light"), + ResourceConfigUtils.getAsInt(brightness.getOrDefault("sky-light", -1), "sky-light"), + ResourceConfigUtils.getAsFloat(arguments.getOrDefault("view-range", 1f), "view-range"), + ResourceConfigUtils.getAsInt(arguments.getOrDefault("line-width", 200), "line-width"), + ResourceConfigUtils.getOrDefault(arguments.get("background-color"), o -> Color.fromStrings(o.toString().split(",")).color(), 0x40000000), + (byte) ResourceConfigUtils.getAsInt(arguments.getOrDefault("text-opacity", -1), "text-opacity"), + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("has-shadow", false), "has-shadow"), + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("is-see-through", false), "is-see-through"), + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("use-default-background-color", false), "use-default-background-color"), + ResourceConfigUtils.getAsEnum(arguments.get("alignment"), TextDisplayAlignment.class, TextDisplayAlignment.CENTER) + ); + } + } +} diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index 1a1ebdd0c..25492ff33 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -236,6 +236,7 @@ warning.config.furniture.duplicate: "Issue found in file - Dupli warning.config.furniture.missing_variants: "Issue found in file - The furniture '' is missing the required 'variants' argument." warning.config.furniture.element.invalid_type: "Issue found in file - The furniture '' is using an invalid element type ''." warning.config.furniture.element.item_display.missing_item: "Issue found in file - The furniture '' is missing the required 'item' argument for 'item_display' element." +warning.config.furniture.element.text_display.missing_text: "Issue found in file - The furniture '' is missing the required 'text' argument for 'text_display' element." warning.config.furniture.settings.unknown: "Issue found in file - The furniture '' is using an unknown setting type ''." warning.config.furniture.hitbox.invalid_type: "Issue found in file - The furniture '' is using an invalid hitbox type ''." warning.config.furniture.hitbox.custom.invalid_entity: "Issue found in file - The furniture '' is using a custom hitbox with invalid entity type ''." diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index 4219c13b6..74b33e5a4 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -236,6 +236,7 @@ warning.config.furniture.duplicate: "在文件 发现问题 - warning.config.furniture.missing_variants: "在文件 发现问题 - 家具 '' 缺少必需的 'variants' 参数" warning.config.furniture.element.invalid_type: "在文件 发现问题 - 家具 '' 使用了无效的元素类型 ''" warning.config.furniture.element.item_display.missing_item: "在文件 发现问题 - 家具 '' 的 'item_display' 元素缺少必需的 'item' 参数" +warning.config.furniture.element.text_display.missing_text: "在文件 发现问题 - 家具 '' 的 'text_display' 元素缺少必需的 'text' 参数" warning.config.furniture.settings.unknown: "在文件 发现问题 - 家具 '' 使用了未知的设置类型 ''" warning.config.furniture.hitbox.invalid_type: "在文件 发现问题 - 家具 '' 使用了无效的碰撞箱类型 ''" warning.config.furniture.hitbox.custom.invalid_entity: "在文件 发现问题 - 家具 '' 的自定义碰撞箱使用了无效的实体类型 ''" diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java index a267612c9..380ece537 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/render/element/BlockEntityElementConfigs.java @@ -22,7 +22,14 @@ public abstract class BlockEntityElementConfigs { } public static BlockEntityElementConfig fromMap(Map arguments) { - Key type = Optional.ofNullable(arguments.get("type")).map(String::valueOf).map(it -> Key.withDefaultNamespace(it, "craftengine")).orElse(ITEM_DISPLAY); + Key type = Optional.ofNullable(arguments.get("type")).map(String::valueOf).map(it -> Key.withDefaultNamespace(it, "craftengine")).orElse(null); + if (type == null) { + if (arguments.containsKey("text")) { + type = TEXT_DISPLAY; + } else { + type = ITEM_DISPLAY; + } + } @SuppressWarnings("unchecked") BlockEntityElementConfigFactory factory = (BlockEntityElementConfigFactory) BuiltInRegistries.BLOCK_ENTITY_ELEMENT_TYPE.getValue(type); if (factory == null) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/display/TextDisplayAlignment.java b/core/src/main/java/net/momirealms/craftengine/core/entity/display/TextDisplayAlignment.java new file mode 100644 index 000000000..17c79fb26 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/display/TextDisplayAlignment.java @@ -0,0 +1,8 @@ +package net.momirealms.craftengine.core.entity.display; + +public enum TextDisplayAlignment { + CENTER, + LEFT, + RIGHT +} + diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfigs.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfigs.java index 7247cdf0e..10a7b4d09 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfigs.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfigs.java @@ -14,6 +14,7 @@ public class FurnitureElementConfigs { public static final Key ITEM_DISPLAY = Key.of("craftengine:item_display"); public static final Key TEXT_DISPLAY = Key.of("craftengine:text_display"); public static final Key ITEM = Key.of("craftengine:item"); + public static final Key ARMOR_STAND = Key.of("craftengine:armor_stand"); public static void register(Key key, FurnitureElementConfigFactory type) { ((WritableRegistry>) BuiltInRegistries.FURNITURE_ELEMENT_TYPE) @@ -21,7 +22,14 @@ public class FurnitureElementConfigs { } public static FurnitureElementConfig fromMap(Map arguments) { - Key type = Optional.ofNullable(arguments.get("type")).map(String::valueOf).map(it -> Key.withDefaultNamespace(it, "craftengine")).orElse(ITEM_DISPLAY); + Key type = Optional.ofNullable(arguments.get("type")).map(String::valueOf).map(it -> Key.withDefaultNamespace(it, "craftengine")).orElse(null); + if (type == null) { + if (arguments.containsKey("text")) { + type = TEXT_DISPLAY; + } else { + type = ITEM_DISPLAY; + } + } @SuppressWarnings("unchecked") FurnitureElementConfigFactory factory = (FurnitureElementConfigFactory) BuiltInRegistries.FURNITURE_ELEMENT_TYPE.getValue(type); if (factory == null) {