diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ArmorStandBlockEntityElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ArmorStandBlockEntityElementConfig.java index 6953c474f..f20b8100c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ArmorStandBlockEntityElementConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ArmorStandBlockEntityElementConfig.java @@ -8,10 +8,12 @@ import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityEl import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemKeys; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.World; +import org.bukkit.inventory.ItemStack; import org.joml.Vector3f; import java.util.ArrayList; @@ -22,20 +24,20 @@ import java.util.function.Function; public class ArmorStandBlockEntityElementConfig implements BlockEntityElementConfig { public static final Factory FACTORY = new Factory(); private final Function> lazyMetadataPacket; - private final Function> item; - private final Vector3f scale; + private final Key itemId; + private final float scale; private final Vector3f position; private final float xRot; private final float yRot; private final boolean small; - public ArmorStandBlockEntityElementConfig(Function> item, - Vector3f scale, + public ArmorStandBlockEntityElementConfig(Key itemId, + float scale, Vector3f position, float xRot, float yRot, boolean small) { - this.item = item; + this.itemId = itemId; this.scale = scale; this.position = position; this.xRot = xRot; @@ -79,10 +81,15 @@ public class ArmorStandBlockEntityElementConfig implements BlockEntityElementCon } public Item item(Player player) { - return this.item.apply(player); + Item wrappedItem = BukkitItemManager.instance().createWrappedItem(this.itemId, player); + return wrappedItem == null ? BukkitItemManager.instance().createWrappedItem(ItemKeys.BARRIER, player) : wrappedItem ; } - public Vector3f scale() { + public Key itemId() { + return this.itemId; + } + + public float scale() { return this.scale; } @@ -116,10 +123,9 @@ public class ArmorStandBlockEntityElementConfig implements BlockEntityElementCon @Override public ArmorStandBlockEntityElementConfig create(Map arguments) { - Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.block.state.entity_renderer.armor_stand.missing_item")); return new ArmorStandBlockEntityElementConfig( - player -> BukkitItemManager.instance().createWrappedItem(itemId, player), - ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("scale", 1f), "scale"), + Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.block.state.entity_renderer.armor_stand.missing_item")), + ResourceConfigUtils.getAsFloat(arguments.getOrDefault("scale", 1f), "scale"), ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0.5f), "position"), ResourceConfigUtils.getAsFloat(arguments.getOrDefault("pitch", 0f), "pitch"), ResourceConfigUtils.getAsFloat(arguments.getOrDefault("yaw", 0f), "yaw"), diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java index de5f09f40..f49fd65f5 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/renderer/element/ItemBlockEntityElementConfig.java @@ -6,29 +6,36 @@ import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityEl import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemKeys; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.World; +import org.bukkit.inventory.ItemStack; import org.joml.Vector3f; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.function.Function; public class ItemBlockEntityElementConfig implements BlockEntityElementConfig { public static final Factory FACTORY = new Factory(); private final Function> lazyMetadataPacket; - private final Function> item; + private final Key itemId; private final Vector3f position; - public ItemBlockEntityElementConfig(Function> item, Vector3f position) { - this.item = item; + public ItemBlockEntityElementConfig(Key itemId, Vector3f position) { + this.itemId = itemId; this.position = position; this.lazyMetadataPacket = player -> { List dataValues = new ArrayList<>(); - ItemEntityData.Item.addEntityData(item.apply(player).getLiteralObject(), dataValues); + Item wrappedItem = BukkitItemManager.instance().createWrappedItem(itemId, player); + if (wrappedItem == null) { + wrappedItem = Objects.requireNonNull(BukkitItemManager.instance().createWrappedItem(ItemKeys.BARRIER, player)); + } + ItemEntityData.Item.addEntityData(wrappedItem.getLiteralObject(), dataValues); ItemEntityData.NoGravity.addEntityData(true, dataValues); return dataValues; }; @@ -61,8 +68,8 @@ public class ItemBlockEntityElementConfig implements BlockEntityElementConfig item(Player player) { - return this.item.apply(player); + public Key itemId() { + return itemId; } public List metadataValues(Player player) { @@ -77,9 +84,8 @@ public class ItemBlockEntityElementConfig implements BlockEntityElementConfig arguments) { - Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.block.state.entity_renderer.item_display.missing_item")); return new ItemBlockEntityElementConfig( - player -> BukkitItemManager.instance().createWrappedItem(itemId, player), + Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.block.state.entity_renderer.item.missing_item")), ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0.5f), "position") ); } 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 a4bca98cc..ec00776e8 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,7 +2,6 @@ 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; @@ -10,11 +9,13 @@ import net.momirealms.craftengine.core.entity.display.Billboard; import net.momirealms.craftengine.core.entity.display.ItemDisplayContext; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemKeys; import net.momirealms.craftengine.core.util.Color; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.World; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; import org.joml.Quaternionf; import org.joml.Vector3f; @@ -28,7 +29,7 @@ import java.util.function.Function; public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementConfig { public static final Factory FACTORY = new Factory(); private final Function> lazyMetadataPacket; - private final Function> item; + private final Key itemId; private final Vector3f scale; private final Vector3f position; private final Vector3f translation; @@ -44,7 +45,7 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo private final int skyLight; private final float viewRange; - public ItemDisplayBlockEntityElementConfig(Function> item, + public ItemDisplayBlockEntityElementConfig(Key itemId, Vector3f scale, Vector3f position, Vector3f translation, @@ -59,7 +60,7 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo int blockLight, int skyLight, float viewRange) { - this.item = item; + this.itemId = itemId; this.scale = scale; this.position = position; this.translation = translation; @@ -83,7 +84,11 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo ItemDisplayEntityData.SharedFlags.addEntityData((byte) 0x0, dataValues); ItemDisplayEntityData.GlowColorOverride.addEntityData(-1, dataValues); } - ItemDisplayEntityData.DisplayedItem.addEntityData(item.apply(player).getLiteralObject(), dataValues); + Item wrappedItem = BukkitItemManager.instance().createWrappedItem(itemId, player); + if (wrappedItem == null) { + wrappedItem = java.util.Objects.requireNonNull(BukkitItemManager.instance().createWrappedItem(ItemKeys.BARRIER, player)); + } + ItemDisplayEntityData.DisplayedItem.addEntityData(wrappedItem.getLiteralObject(), dataValues); ItemDisplayEntityData.Scale.addEntityData(this.scale, dataValues); ItemDisplayEntityData.RotationLeft.addEntityData(this.rotation, dataValues); ItemDisplayEntityData.BillboardConstraints.addEntityData(this.billboard.id(), dataValues); @@ -128,8 +133,12 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo return ItemDisplayBlockEntityElement.class; } - public Item item(Player player) { - return this.item.apply(player); + public Color glowColor() { + return glowColor; + } + + public Key itemId() { + return itemId; } public Vector3f scale() { @@ -188,10 +197,9 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo @Override public ItemDisplayBlockEntityElementConfig create(Map arguments) { - Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.block.state.entity_renderer.item_display.missing_item")); Map brightness = ResourceConfigUtils.getAsMap(arguments.getOrDefault("brightness", Map.of()), "brightness"); return new ItemDisplayBlockEntityElementConfig( - player -> BukkitItemManager.instance().createWrappedItem(itemId, player), + Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.block.state.entity_renderer.item_display.missing_item")), ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("scale", 1f), "scale"), ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0.5f), "position"), ResourceConfigUtils.getAsVector3f(arguments.get("translation"), "translation"), 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 10b04468f..3c27ed7d8 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 @@ -2,7 +2,6 @@ package net.momirealms.craftengine.bukkit.block.entity.renderer.element; import com.google.common.base.Objects; import net.kyori.adventure.text.Component; -import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; import net.momirealms.craftengine.bukkit.entity.data.TextDisplayEntityData; import net.momirealms.craftengine.bukkit.util.ComponentUtils; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfig; @@ -10,7 +9,7 @@ import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityEl 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.plugin.context.NetworkTextReplaceContext; import net.momirealms.craftengine.core.util.AdventureHelper; import net.momirealms.craftengine.core.util.Color; import net.momirealms.craftengine.core.util.ResourceConfigUtils; @@ -139,8 +138,12 @@ public class TextDisplayBlockEntityElementConfig implements BlockEntityElementCo return TextDisplayBlockEntityElement.class; } + public String text() { + return text; + } + public Component text(Player player) { - return AdventureHelper.miniMessage().deserialize(this.text, PlayerOptionalContext.of(player).tagResolvers()); + return AdventureHelper.miniMessage().deserialize(this.text, NetworkTextReplaceContext.of(player).tagResolvers()); } public Vector3f scale() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ArmorStandFurnitureElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ArmorStandFurnitureElement.java new file mode 100644 index 000000000..ba6495647 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ArmorStandFurnitureElement.java @@ -0,0 +1,61 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.element; + +import com.mojang.datafixers.util.Pair; +import it.unimi.dsi.fastutil.ints.IntList; +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.world.Vec3d; +import net.momirealms.craftengine.core.world.WorldPosition; + +import java.util.List; +import java.util.UUID; +import java.util.function.Consumer; + +public class ArmorStandFurnitureElement implements FurnitureElement { + private final ArmorStandFurnitureElementConfig config; + public final int entityId; + private final FurnitureColorSource colorSource; + public final Object cachedSpawnPacket; + public final Object cachedDespawnPacket; + + public ArmorStandFurnitureElement(Furniture furniture, ArmorStandFurnitureElementConfig config) { + this.config = config; + this.entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); + WorldPosition furniturePos = furniture.position(); + Vec3d position = Furniture.getRelativePosition(furniturePos, config.position()); + this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityId, UUID.randomUUID(), position.x, position.y, position.z, + furniturePos.xRot, furniturePos.yRot, MEntityTypes.ARMOR_STAND, 0, CoreReflections.instance$Vec3$Zero, furniturePos.yRot + ); + this.colorSource = furniture.dataAccessor.getColorSource(); + this.cachedDespawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(IntList.of(entityId)); + } + + @Override + public void show(Player player) { + player.sendPackets(List.of(this.cachedSpawnPacket, FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadata.apply(player))), false); + player.sendPacket(FastNMS.INSTANCE.constructor$ClientboundSetEquipmentPacket(this.entityId, List.of( + Pair.of(CoreReflections.instance$EquipmentSlot$HEAD, this.config.item(player, this.colorSource).getLiteralObject()) + )), false); + } + + @Override + public void hide(Player player) { + player.sendPacket(this.cachedDespawnPacket, 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/ArmorStandFurnitureElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ArmorStandFurnitureElementConfig.java new file mode 100644 index 000000000..f24d95a48 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ArmorStandFurnitureElementConfig.java @@ -0,0 +1,109 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.element; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.momirealms.craftengine.bukkit.entity.data.ArmorStandData; +import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.FurnitureColorSource; +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.item.Item; +import net.momirealms.craftengine.core.item.ItemKeys; +import net.momirealms.craftengine.core.item.data.FireworkExplosion; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +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 ArmorStandFurnitureElementConfig implements FurnitureElementConfig { + public static final Factory FACTORY = new Factory(); + public final Function> metadata; + public final Key itemId; + public final float scale; + public final boolean applyDyedColor; + public final Vector3f position; + public final boolean small; + + public ArmorStandFurnitureElementConfig(Key itemId, + float scale, + Vector3f position, + boolean applyDyedColor, + boolean small) { + this.position = position; + this.applyDyedColor = applyDyedColor; + this.small = small; + this.scale = scale; + this.itemId = itemId; + this.metadata = (player) -> { + List dataValues = new ArrayList<>(2); + BaseEntityData.SharedFlags.addEntityData((byte) 0x20, dataValues); + if (small) { + ArmorStandData.ArmorStandFlags.addEntityData((byte) 0x01, dataValues); + } + return dataValues; + }; + } + + public Item item(Player player, FurnitureColorSource colorSource) { + Item wrappedItem = BukkitItemManager.instance().createWrappedItem(itemId, player); + if (applyDyedColor && colorSource != null && wrappedItem != null) { + Optional.ofNullable(colorSource.dyedColor()).ifPresent(wrappedItem::dyedColor); + Optional.ofNullable(colorSource.fireworkColors()).ifPresent(colors -> wrappedItem.fireworkExplosion(new FireworkExplosion( + FireworkExplosion.Shape.SMALL_BALL, + new IntArrayList(colors), + new IntArrayList(), + false, + false + ))); + } + return Optional.ofNullable(wrappedItem).orElseGet(() -> BukkitItemManager.instance().createWrappedItem(ItemKeys.BARRIER, null)); + } + + public float scale() { + return scale; + } + + public boolean small() { + return small; + } + + public Vector3f position() { + return this.position; + } + + public boolean applyDyedColor() { + return this.applyDyedColor; + } + + public Key itemId() { + return this.itemId; + } + + @Override + public ArmorStandFurnitureElement create(@NotNull Furniture furniture) { + return new ArmorStandFurnitureElement(furniture, this); + } + + public static class Factory implements FurnitureElementConfigFactory { + + @Override + public ArmorStandFurnitureElementConfig create(Map arguments) { + return new ArmorStandFurnitureElementConfig( + Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.furniture.element.armor_stand.missing_item")), + ResourceConfigUtils.getAsFloat(arguments.getOrDefault("scale", 1f), "scale"), + ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0f), "position"), + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("apply-dyed-color", true), "apply-dyed-color"), + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("small", false), "small") + ); + } + } +} 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 aac2804da..fc328fa1d 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 @@ -7,6 +7,8 @@ public class BukkitFurnitureElementConfigs extends FurnitureElementConfigs { static { register(ITEM_DISPLAY, ItemDisplayFurnitureElementConfig.FACTORY); register(TEXT_DISPLAY, TextDisplayFurnitureElementConfig.FACTORY); + register(ITEM, ItemFurnitureElementConfig.FACTORY); + register(ARMOR_STAND, ArmorStandFurnitureElementConfig.FACTORY); } private BukkitFurnitureElementConfigs() {} 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 dabbfdc1f..3a4c9d38e 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 @@ -194,11 +194,9 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig @Override public ItemDisplayFurnitureElementConfig create(Map arguments) { - Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.furniture.element.item_display.missing_item")); - boolean applyDyedColor = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("apply-dyed-color", true), "apply-dyed-color"); Map brightness = ResourceConfigUtils.getAsMap(arguments.getOrDefault("brightness", Map.of()), "brightness"); return new ItemDisplayFurnitureElementConfig( - itemId, + Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.furniture.element.item_display.missing_item")), ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("scale", 1f), "scale"), ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0f), "position"), ResourceConfigUtils.getAsVector3f(arguments.get("translation"), "translation"), @@ -209,7 +207,7 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig 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"), - applyDyedColor, + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("apply-dyed-color", true), "apply-dyed-color"), 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"), diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemFurnitureElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemFurnitureElement.java new file mode 100644 index 000000000..26621dd33 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemFurnitureElement.java @@ -0,0 +1,78 @@ +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 ItemFurnitureElement implements FurnitureElement { + private final ItemFurnitureElementConfig config; + public final int entityId1; + public final int entityId2; + private final Object despawnPacket; + private final FurnitureColorSource colorSource; + public final Object cachedSpawnPacket1; + public final Object cachedSpawnPacket2; + public final Object cachedRidePacket; + + public ItemFurnitureElement(Furniture furniture, ItemFurnitureElementConfig config) { + this.config = config; + this.entityId1 = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); + this.entityId2 = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); + WorldPosition furniturePos = furniture.position(); + Vec3d position = Furniture.getRelativePosition(furniturePos, config.position()); + this.cachedSpawnPacket1 = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityId1, UUID.randomUUID(), position.x, position.y, position.z, + 0, 0, MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0 + ); + this.cachedSpawnPacket2 = FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( + entityId2, UUID.randomUUID(), position.x, position.y, position.z, + 0, 0, MEntityTypes.ITEM, 0, CoreReflections.instance$Vec3$Zero, 0 + ); + this.cachedRidePacket = FastNMS.INSTANCE.constructor$ClientboundSetPassengersPacket(entityId1, entityId2); + this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(MiscUtils.init(new IntArrayList(), + a -> { + a.add(entityId1); + a.add(entityId2); + } + )); + this.colorSource = furniture.dataAccessor.getColorSource(); + } + + @Override + public void show(Player player) { + player.sendPackets(List.of( + this.cachedSpawnPacket1, + this.cachedSpawnPacket2, + this.cachedRidePacket, + FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId2, this.config.metadata().apply(player, this.colorSource) + )), false); + } + + @Override + public void hide(Player player) { + player.sendPacket(this.despawnPacket, false); + } + + @Override + public int[] virtualEntityIds() { + return new int[] {this.entityId1, this.entityId2}; + } + + @Override + public void collectVirtualEntityId(Consumer collector) { + collector.accept(this.entityId1); + collector.accept(this.entityId2); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemFurnitureElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemFurnitureElementConfig.java new file mode 100644 index 000000000..af3808b69 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemFurnitureElementConfig.java @@ -0,0 +1,93 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.element; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.momirealms.craftengine.bukkit.entity.data.ItemEntityData; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.FurnitureColorSource; +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.item.Item; +import net.momirealms.craftengine.core.item.ItemKeys; +import net.momirealms.craftengine.core.item.data.FireworkExplosion; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.joml.Vector3f; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.BiFunction; + +public class ItemFurnitureElementConfig implements FurnitureElementConfig { + public static final Factory FACTORY = new Factory(); + public final BiFunction> metadata; + public final Key itemId; + public final boolean applyDyedColor; + public final Vector3f position; + + public ItemFurnitureElementConfig(Key itemId, + Vector3f position, + boolean applyDyedColor) { + this.position = position; + this.applyDyedColor = applyDyedColor; + this.itemId = itemId; + BiFunction> itemFunction = (player, colorSource) -> { + Item wrappedItem = BukkitItemManager.instance().createWrappedItem(itemId, player); + if (applyDyedColor && colorSource != null && wrappedItem != null) { + Optional.ofNullable(colorSource.dyedColor()).ifPresent(wrappedItem::dyedColor); + Optional.ofNullable(colorSource.fireworkColors()).ifPresent(colors -> wrappedItem.fireworkExplosion(new FireworkExplosion( + FireworkExplosion.Shape.SMALL_BALL, + new IntArrayList(colors), + new IntArrayList(), + false, + false + ))); + } + return Optional.ofNullable(wrappedItem).orElseGet(() -> BukkitItemManager.instance().createWrappedItem(ItemKeys.BARRIER, null)); + }; + this.metadata = (player, source) -> { + List dataValues = new ArrayList<>(); + ItemEntityData.Item.addEntityData(itemFunction.apply(player, source).getLiteralObject(), dataValues); + ItemEntityData.NoGravity.addEntityData(true, dataValues); + return dataValues; + }; + } + + public Vector3f position() { + return this.position; + } + + public boolean applyDyedColor() { + return this.applyDyedColor; + } + + public BiFunction> metadata() { + return this.metadata; + } + + public Key itemId() { + return this.itemId; + } + + @Override + public ItemFurnitureElement create(@NotNull Furniture furniture) { + return new ItemFurnitureElement(furniture, this); + } + + public static class Factory implements FurnitureElementConfigFactory { + + @Override + public ItemFurnitureElementConfig create(Map arguments) { + return new ItemFurnitureElementConfig( + Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("item"), "warning.config.furniture.element.item.missing_item")), + ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0f), "position"), + ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("apply-dyed-color", true), "apply-dyed-color") + ); + } + } +} 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 index eb2771d4b..a68e1c483 100644 --- 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 @@ -5,7 +5,6 @@ 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; 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 index 5c2ae4b7e..614efbad3 100644 --- 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 @@ -221,10 +221,9 @@ public class TextDisplayFurnitureElementConfig implements FurnitureElementConfig @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.requireNonEmptyStringOrThrow(arguments.get("text"), "warning.config.furniture.element.text_display.missing_text"), ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("scale", 1f), "scale"), ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0f), "position"), ResourceConfigUtils.getAsVector3f(arguments.get("translation"), "translation"), diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index 25492ff33..edac2828b 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -237,6 +237,8 @@ warning.config.furniture.missing_variants: "Issue found in file 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.element.item.missing_item: "Issue found in file - The furniture '' is missing the required 'item' argument for 'item' element." +warning.config.furniture.element.armor_stand.missing_item: "Issue found in file - The furniture '' is missing the required 'item' argument for 'armor_stand' 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 ''." @@ -351,6 +353,8 @@ warning.config.block.state.entity_renderer.item_display.missing_item: "I warning.config.block.state.entity_renderer.text_display.missing_text: "Issue found in file - The block '' is missing the required 'text' argument for 'text_display' entity renderer." warning.config.block.state.entity_renderer.better_model.missing_model: "Issue found in file - The block '' is missing the required 'model' argument for 'better_model' entity renderer." warning.config.block.state.entity_renderer.model_engine.missing_model: "Issue found in file - The block '' is missing the required 'model' argument for 'model_engine' entity renderer." +warning.config.block.state.entity_renderer.armor_stand.missing_item: "Issue found in file - The block '' is missing the required 'item' argument for 'armor_stand' entity renderer." +warning.config.block.state.entity_renderer.item.missing_item: "Issue found in file - The block '' is missing the required 'item' argument for 'item' entity renderer." warning.config.block.state.variant.invalid_appearance: "Issue found in file - The block '' has an error that the variant '' is using a non-existing appearance ''." warning.config.block.state.invalid_vanilla: "Issue found in file - The block '' is using an invalid vanilla block state ''." warning.config.block.state.invalid_auto_state: "Issue found in file - The block '' is using an invalid auto-state ''. Allowed values: []." diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index 74b33e5a4..5ea020fd7 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -237,6 +237,8 @@ warning.config.furniture.missing_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.element.item.missing_item: "在文件 发现问题 - 家具 '' 的 'item' 元素缺少必需的 'item' 参数" +warning.config.furniture.element.armor_stand.missing_item: "在文件 发现问题 - 家具 '' 的 'armor_stand' 元素缺少必需的 'item' 参数" warning.config.furniture.settings.unknown: "在文件 发现问题 - 家具 '' 使用了未知的设置类型 ''" warning.config.furniture.hitbox.invalid_type: "在文件 发现问题 - 家具 '' 使用了无效的碰撞箱类型 ''" warning.config.furniture.hitbox.custom.invalid_entity: "在文件 发现问题 - 家具 '' 的自定义碰撞箱使用了无效的实体类型 ''" @@ -351,6 +353,8 @@ warning.config.block.state.entity_renderer.item_display.missing_item: " warning.config.block.state.entity_renderer.text_display.missing_text: "在文件 发现问题 - 方块 '' 缺少 'text_display' 实体渲染器所需的 'text' 参数" warning.config.block.state.entity_renderer.better_model.missing_model: "在文件 发现问题 - 方块 '' 缺少 'better_model' 实体渲染器所需的 'model' 参数" warning.config.block.state.entity_renderer.model_engine.missing_model: "在文件 发现问题 - 方块 '' 缺少 'model_engine' 实体渲染器所需的 'model' 参数" +warning.config.block.state.entity_renderer.armor_stand.missing_item: "在文件 发现问题 - 方块 '' 缺少 'armor_stand' 实体渲染器所需的 'item' 参数" +warning.config.block.state.entity_renderer.item.missing_item: "在文件 发现问题 - 方块 '' 缺少 'item' 实体渲染器所需的 'item' 参数" warning.config.block.state.variant.invalid_appearance: "在文件 发现问题 - 方块 '' 的变体 '' 使用了不存在的 appearance ''" warning.config.block.state.invalid_vanilla: "在文件 发现问题 - 方块 '' 使用了无效的原版方块状态 ''" warning.config.block.state.invalid_auto_state: "在文件 发现问题 - 方块 '' 使用了无效的自动状态 ''. 允许的值: []"