diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java index 4a47cd615..8f61765d3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineFurniture.java @@ -8,9 +8,8 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.entity.furniture.AnchorType; -import net.momirealms.craftengine.core.entity.furniture.CustomFurniture; import net.momirealms.craftengine.core.entity.furniture.Furniture; -import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData; +import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.loot.LootTable; @@ -46,7 +45,7 @@ public final class CraftEngineFurniture { * @return a non-null map containing all loaded custom furniture */ @NotNull - public static Map loadedFurniture() { + public static Map loadedFurniture() { return BukkitFurnitureManager.instance().loadedFurniture(); } @@ -56,7 +55,7 @@ public final class CraftEngineFurniture { * @param id id * @return the custom furniture */ - public static CustomFurniture byId(@NotNull Key id) { + public static FurnitureConfig byId(@NotNull Key id) { return BukkitFurnitureManager.instance().furnitureById(id).orElse(null); } @@ -69,9 +68,11 @@ public final class CraftEngineFurniture { */ @Nullable public static BukkitFurniture place(Location location, Key furnitureId) { - CustomFurniture furniture = byId(furnitureId); + FurnitureConfig furniture = byId(furnitureId); if (furniture == null) return null; - return place(location, furnitureId, furniture.getAnyAnchorType()); + // fixme API +// return place(location, furnitureId, furniture.getAnyAnchorType()); + return null; } /** @@ -79,14 +80,17 @@ public final class CraftEngineFurniture { * * @param location location * @param furnitureId furniture to place - * @param anchorType anchor type + * @param anchorType anchor id * @return the loaded furniture */ @Nullable + @Deprecated(since = "0.0.66", forRemoval = true) public static BukkitFurniture place(Location location, Key furnitureId, AnchorType anchorType) { - CustomFurniture furniture = byId(furnitureId); + FurnitureConfig furniture = byId(furnitureId); if (furniture == null) return null; - return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true); + // fixme API +// return BukkitFurnitureManager.instance().place(location, furniture, FurnitureDataAccessor.builder().anchorType(anchorType).build(), true); + return null; } /** @@ -94,12 +98,15 @@ public final class CraftEngineFurniture { * * @param location location * @param furniture furniture to place - * @param anchorType anchor type + * @param anchorType anchor id * @return the loaded furniture */ @NotNull - public static BukkitFurniture place(Location location, CustomFurniture furniture, AnchorType anchorType) { - return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true); + @Deprecated(since = "0.0.66", forRemoval = true) + public static BukkitFurniture place(Location location, FurnitureConfig furniture, AnchorType anchorType) { + // fixme API +// return BukkitFurnitureManager.instance().place(location, furniture, FurnitureDataAccessor.builder().anchorType(anchorType).build(), true); + return null; } /** @@ -107,15 +114,18 @@ public final class CraftEngineFurniture { * * @param location location * @param furnitureId furniture to place - * @param anchorType anchor type + * @param anchorType anchor id * @param playSound whether to play place sounds * @return the loaded furniture */ @Nullable + @Deprecated(since = "0.0.66", forRemoval = true) public static BukkitFurniture place(Location location, Key furnitureId, AnchorType anchorType, boolean playSound) { - CustomFurniture furniture = byId(furnitureId); + FurnitureConfig furniture = byId(furnitureId); if (furniture == null) return null; - return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound); + // fixme API +// return BukkitFurnitureManager.instance().place(location, furniture, FurnitureDataAccessor.builder().anchorType(anchorType).build(), playSound); + return null; } /** @@ -123,13 +133,16 @@ public final class CraftEngineFurniture { * * @param location location * @param furniture furniture to place - * @param anchorType anchor type + * @param anchorType anchor id * @param playSound whether to play place sounds * @return the loaded furniture */ @NotNull - public static BukkitFurniture place(Location location, CustomFurniture furniture, AnchorType anchorType, boolean playSound) { - return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound); + @Deprecated(since = "0.0.66", forRemoval = true) + public static BukkitFurniture place(Location location, FurnitureConfig furniture, AnchorType anchorType, boolean playSound) { + // fixme API +// return BukkitFurnitureManager.instance().place(location, furniture, FurnitureDataAccessor.builder().anchorType(anchorType).build(), playSound); + return null; } /** @@ -286,7 +299,7 @@ public final class CraftEngineFurniture { boolean dropLoot, boolean playSound) { if (!furniture.isValid()) return; - Location location = ((BukkitFurniture) furniture).dropLocation(); + Location location = ((BukkitFurniture) furniture).getDropLocation(); furniture.destroy(); LootTable lootTable = (LootTable) furniture.config().lootTable(); World world = new BukkitWorld(location.getWorld()); @@ -295,7 +308,7 @@ public final class CraftEngineFurniture { ContextHolder.Builder builder = ContextHolder.builder() .withParameter(DirectContextParameters.POSITION, position) .withParameter(DirectContextParameters.FURNITURE, furniture) - .withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, furniture.extraData().item().orElse(null)); + .withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, furniture.dataAccessor().item().orElse(null)); if (player != null) { Item itemInHand = player.getItemInHand(InteractionHand.MAIN_HAND); builder.withParameter(DirectContextParameters.PLAYER, player) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/AsyncResourcePackCacheEvent.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/AsyncResourcePackCacheEvent.java index dfa064fa3..62099bba8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/AsyncResourcePackCacheEvent.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/AsyncResourcePackCacheEvent.java @@ -49,7 +49,7 @@ public final class AsyncResourcePackCacheEvent extends Event { * Adds an external resource pack to the cache. *

* This method accepts either a .zip file or a directory path representing a resource pack. - * The resource pack will be added to the appropriate cache collection based on its type. + * The resource pack will be added to the appropriate cache collection based on its id. *

* * @param path the file system path to the resource pack. Must be either a .zip file or a directory. diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureAttemptPlaceEvent.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureAttemptPlaceEvent.java index 6d0a54209..dd1920ca0 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureAttemptPlaceEvent.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureAttemptPlaceEvent.java @@ -1,7 +1,7 @@ package net.momirealms.craftengine.bukkit.api.event; import net.momirealms.craftengine.core.entity.furniture.AnchorType; -import net.momirealms.craftengine.core.entity.furniture.CustomFurniture; +import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig; import net.momirealms.craftengine.core.entity.player.InteractionHand; import org.bukkit.Location; import org.bukkit.block.Block; @@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull; public final class FurnitureAttemptPlaceEvent extends PlayerEvent implements Cancellable { private static final HandlerList HANDLER_LIST = new HandlerList(); private boolean cancelled; - private final CustomFurniture furniture; + private final FurnitureConfig furniture; private final Location location; private final AnchorType anchorType; private final BlockFace clickedFace; @@ -23,7 +23,7 @@ public final class FurnitureAttemptPlaceEvent extends PlayerEvent implements Can private final InteractionHand hand; public FurnitureAttemptPlaceEvent(@NotNull Player player, - @NotNull CustomFurniture furniture, + @NotNull FurnitureConfig furniture, @NotNull AnchorType anchorType, @NotNull Location location, @NotNull BlockFace clickedFace, @@ -69,7 +69,7 @@ public final class FurnitureAttemptPlaceEvent extends PlayerEvent implements Can } @NotNull - public CustomFurniture furniture() { + public FurnitureConfig furniture() { return furniture; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureInteractEvent.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureInteractEvent.java index 1e1adcf47..ebe8850fb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureInteractEvent.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/FurnitureInteractEvent.java @@ -1,7 +1,7 @@ package net.momirealms.craftengine.bukkit.api.event; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture; -import net.momirealms.craftengine.core.entity.furniture.HitBox; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBox; import net.momirealms.craftengine.core.entity.player.InteractionHand; import org.bukkit.Location; import org.bukkit.entity.Player; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/NearLiquidBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/NearLiquidBlockBehavior.java index 9c9b02c65..060282f7d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/NearLiquidBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/NearLiquidBlockBehavior.java @@ -45,7 +45,7 @@ public class NearLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior { public static class Factory implements BlockBehaviorFactory { @Override public BlockBehavior create(CustomBlock block, Map arguments) { - List liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-type", List.of("water"))); + List liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-id", List.of("water"))); boolean stackable = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("stackable", false), "stackable"); int delay = ResourceConfigUtils.getAsInt(arguments.getOrDefault("delay", 0), "delay"); List positionsToCheck = MiscUtils.getAsStringList(arguments.getOrDefault("positions", List.of())); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/OnLiquidBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/OnLiquidBlockBehavior.java index e71780c7c..3e8a3fed1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/OnLiquidBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/OnLiquidBlockBehavior.java @@ -40,7 +40,7 @@ public class OnLiquidBlockBehavior extends AbstractCanSurviveBlockBehavior { public static class Factory implements BlockBehaviorFactory { @Override public BlockBehavior create(CustomBlock block, Map arguments) { - List liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-type", List.of("water"))); + List liquidTypes = MiscUtils.getAsStringList(arguments.getOrDefault("liquid-id", List.of("water"))); boolean stackable = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("stackable", false), "stackable"); int delay = ResourceConfigUtils.getAsInt(arguments.getOrDefault("delay", 0), "delay"); return new OnLiquidBlockBehavior(block, delay, stackable, liquidTypes.contains("water"), liquidTypes.contains("lava")); 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 daa220d7d..dbda0e1e0 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 @@ -6,8 +6,8 @@ import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement; 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.Billboard; -import net.momirealms.craftengine.core.entity.ItemDisplayContext; +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.util.Key; @@ -19,7 +19,6 @@ import org.joml.Vector3f; import java.util.ArrayList; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.function.Function; @@ -173,8 +172,8 @@ public class ItemDisplayBlockEntityElementConfig implements BlockEntityElementCo ResourceConfigUtils.getAsFloat(arguments.getOrDefault("pitch", 0f), "pitch"), ResourceConfigUtils.getAsFloat(arguments.getOrDefault("yaw", 0f), "yaw"), ResourceConfigUtils.getAsQuaternionf(arguments.getOrDefault("rotation", 0f), "rotation"), - ItemDisplayContext.valueOf(arguments.getOrDefault("display-context", "none").toString().toUpperCase(Locale.ROOT)), - Billboard.valueOf(arguments.getOrDefault("billboard", "fixed").toString().toUpperCase(Locale.ROOT)), + 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") ); 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 12012724d..dc450d1fe 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 @@ -7,7 +7,7 @@ import net.momirealms.craftengine.bukkit.util.ComponentUtils; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement; 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.Billboard; +import net.momirealms.craftengine.core.entity.display.Billboard; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.util.AdventureHelper; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitItemEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitItemEntity.java index 449fc5ebb..7ee3115ae 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitItemEntity.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/BukkitItemEntity.java @@ -1,7 +1,7 @@ package net.momirealms.craftengine.bukkit.entity; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; -import net.momirealms.craftengine.core.entity.ItemEntity; +import net.momirealms.craftengine.core.entity.item.ItemEntity; import org.bukkit.entity.Item; public class BukkitItemEntity extends BukkitEntity implements ItemEntity { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemDisplayEntityData.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemDisplayEntityData.java index 09d39ebdc..091f8654e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemDisplayEntityData.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/data/ItemDisplayEntityData.java @@ -6,7 +6,7 @@ public class ItemDisplayEntityData extends DisplayEntityData { // Item display only public static final ItemDisplayEntityData DisplayedItem = new ItemDisplayEntityData<>(ItemDisplayEntityData.class, EntityDataValue.Serializers$ITEM_STACK, CoreReflections.instance$ItemStack$EMPTY); /** - * Display type: + * Display id: * 0 = NONE * 1 = THIRD_PERSON_LEFT_HAND * 2 = THIRD_PERSON_RIGHT_HAND diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCustomFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCustomFurniture.java deleted file mode 100644 index dcad38455..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitCustomFurniture.java +++ /dev/null @@ -1,74 +0,0 @@ -package net.momirealms.craftengine.bukkit.entity.furniture; - -import net.momirealms.craftengine.core.entity.furniture.AbstractCustomFurniture; -import net.momirealms.craftengine.core.entity.furniture.AnchorType; -import net.momirealms.craftengine.core.entity.furniture.CustomFurniture; -import net.momirealms.craftengine.core.entity.furniture.FurnitureSettings; -import net.momirealms.craftengine.core.loot.LootTable; -import net.momirealms.craftengine.core.plugin.context.Context; -import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; -import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.util.Key; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Map; - -public class BukkitCustomFurniture extends AbstractCustomFurniture { - - protected BukkitCustomFurniture(@NotNull Key id, - @NotNull FurnitureSettings settings, - @NotNull Map placements, - @NotNull Map>> events, - @Nullable LootTable lootTable) { - super(id, settings, placements, events, lootTable); - } - - public static Builder builder() { - return new BuilderImpl(); - } - - public static class BuilderImpl implements Builder { - private Key id; - private Map placements; - private FurnitureSettings settings; - private Map>> events; - private LootTable lootTable; - - @Override - public CustomFurniture build() { - return new BukkitCustomFurniture(id, settings, placements, events, lootTable); - } - - @Override - public Builder id(Key id) { - this.id = id; - return this; - } - - @Override - public Builder placement(Map placements) { - this.placements = placements; - return this; - } - - @Override - public Builder settings(FurnitureSettings settings) { - this.settings = settings; - return this; - } - - @Override - public Builder lootTable(LootTable lootTable) { - this.lootTable = lootTable; - return this; - } - - @Override - public Builder events(Map>> events) { - this.events = events; - return this; - } - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java index 37d64bbf6..fe9bec331 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java @@ -1,184 +1,166 @@ package net.momirealms.craftengine.bukkit.entity.furniture; -import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import net.momirealms.craftengine.bukkit.entity.BukkitEntity; -import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.util.LocationUtils; -import net.momirealms.craftengine.core.entity.furniture.*; -import net.momirealms.craftengine.core.entity.seat.Seat; -import net.momirealms.craftengine.core.plugin.CraftEngine; -import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig; +import net.momirealms.craftengine.core.entity.furniture.FurnitureDataAccessor; +import net.momirealms.craftengine.core.entity.furniture.FurnitureVariant; +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement; +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.entityculling.CullingData; import net.momirealms.craftengine.core.util.QuaternionUtils; import net.momirealms.craftengine.core.world.WorldPosition; +import net.momirealms.sparrow.nbt.CompoundTag; import org.bukkit.Location; import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.joml.Quaternionf; import org.joml.Vector3f; -import java.io.IOException; import java.lang.ref.WeakReference; -import java.util.*; +import java.util.Optional; +import java.util.UUID; public class BukkitFurniture implements Furniture { - private final CustomFurniture furniture; - private final CustomFurniture.Placement placement; - private FurnitureExtraData extraData; - // location - private final Location location; - // base entity - private final WeakReference baseEntity; - private final int baseEntityId; - // colliders - private final Collider[] colliderEntities; - // cache - private final List fakeEntityIds; - private final List entityIds; - private final Map hitBoxes = new Int2ObjectArrayMap<>(); - private final Map hitBoxParts = new Int2ObjectArrayMap<>(); - private final boolean minimized; - private final boolean hasExternalModel; - // cached spawn packet - private Object cachedSpawnPacket; - private Object cachedMinimizedSpawnPacket; + private static final UUID INVALID_UUID = new UUID(0, 0); + @NotNull + private final FurnitureConfig config; + @NotNull + private final FurnitureDataAccessor dataAccessor; - public BukkitFurniture(Entity baseEntity, - CustomFurniture furniture, - FurnitureExtraData extraData) { - this.extraData = extraData; - this.baseEntityId = baseEntity.getEntityId(); - this.location = baseEntity.getLocation(); - this.baseEntity = new WeakReference<>(baseEntity); - this.furniture = furniture; - this.minimized = furniture.settings().minimized(); - this.placement = furniture.getValidPlacement(extraData.anchorType().orElseGet(furniture::getAnyAnchorType)); + private WeakReference baseEntity; + private FurnitureVariant currentVariant; + private Location location; + private boolean valid; + private UUID uuid; + private int entityId; - List fakeEntityIds = new IntArrayList(); - List mainEntityIds = new IntArrayList(); - mainEntityIds.add(this.baseEntityId); + private FurnitureElement[] elements; - // 绑定外部模型 - Optional optionalExternal = placement.externalModel(); - if (optionalExternal.isPresent()) { - try { - optionalExternal.get().bindModel(new BukkitEntity(baseEntity)); - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to load external model for furniture " + id(), e); - } - this.hasExternalModel = true; - } else { - this.hasExternalModel = false; - } + public BukkitFurniture(@NotNull FurnitureConfig config, + @NotNull CompoundTag data) { + this.dataAccessor = FurnitureDataAccessor.of(data); + this.currentVariant = Optional.ofNullable(getVariant()).orElseGet(config::anyVariant); + this.config = config; + this.baseEntity = new WeakReference<>(null); + this.valid = false; + this.entityId = -1; + this.uuid = INVALID_UUID; + } - Quaternionf conjugated = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - this.location.getYaw()), 0).conjugate(); - List packets = new ArrayList<>(); - List minimizedPackets = new ArrayList<>(); - List colliders = new ArrayList<>(4); + private void sync() { WorldPosition position = position(); - - - // 初始化家具的元素 - for (FurnitureElement element : placement.elements()) { - int entityId = CoreReflections.instance$Entity$ENTITY_COUNTER.incrementAndGet(); - fakeEntityIds.add(entityId); - element.initPackets(this, entityId, conjugated, packet -> { - packets.add(packet); - if (this.minimized) minimizedPackets.add(packet); - }); + FurnitureElementConfig[] elementConfigs = this.currentVariant.elements(); + FurnitureElement[] elements = new FurnitureElement[elementConfigs.length]; + for (int i = 0; i < elementConfigs.length; i++) { + FurnitureElement o = elementConfigs[i].create(position); + elements[i] = o; } + this.elements = elements; + } - // 初始化碰撞箱 - for (HitBoxConfig hitBoxConfig : this.placement.hitBoxConfigs()) { - int[] ids = hitBoxConfig.acquireEntityIds(CoreReflections.instance$Entity$ENTITY_COUNTER::incrementAndGet); - List aabbs = new ArrayList<>(); - - hitBoxConfig.initPacketsAndColliders(ids, position, conjugated, (packet, canBeMinimized) -> { - packets.add(packet); - if (this.minimized && !canBeMinimized) { - minimizedPackets.add(packet); - } - }, colliders::add, part -> { - this.hitBoxParts.put(part.entityId(), part); - aabbs.add(part); - }); - - BukkitHitBox hitBox = new BukkitHitBox(this, hitBoxConfig, aabbs.toArray(new HitBoxPart[0])); - for (int entityId : ids) { - fakeEntityIds.add(entityId); - mainEntityIds.add(entityId); - this.hitBoxes.put(entityId, hitBox); - } - } - - // 初始化缓存的家具包 - try { - this.cachedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(packets); - if (this.minimized) { - this.cachedMinimizedSpawnPacket = FastNMS.INSTANCE.constructor$ClientboundBundlePacket(minimizedPackets); - } - } catch (Exception e) { - CraftEngine.instance().logger().warn("Failed to init spawn packets for furniture " + id(), e); - } - - - this.fakeEntityIds = fakeEntityIds; - this.entityIds = mainEntityIds; - this.colliderEntities = colliders.toArray(new Collider[0]); + public void addToWorld(Location location) { + this.setLocation(location); + this.valid = true; + Entity baseEntity = null; // fixme 处理生成 + this.baseEntity = new WeakReference<>(baseEntity); + this.uuid = baseEntity.getUniqueId(); + this.entityId = baseEntity.getEntityId(); + this.sync(); } @Override - public void initializeColliders() { - Object world = FastNMS.INSTANCE.field$CraftWorld$ServerLevel(this.location.getWorld()); - for (Collider entity : this.colliderEntities) { - FastNMS.INSTANCE.method$LevelWriter$addFreshEntity(world, entity.handle()); - Entity bukkitEntity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity.handle()); - bukkitEntity.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_COLLISION, PersistentDataType.BYTE, (byte) 1); + public void show(Player player) { + for (FurnitureElement element : this.elements) { + element.show(player); } } - @NotNull - public Object spawnPacket(Player player) { - // TODO hasPermission might be slow, can we use a faster way in the future? - // TODO Make it based on conditions. So we can dynamically control which furniture should be sent to the player - if (!this.minimized || player.hasPermission(FurnitureManager.FURNITURE_ADMIN_NODE)) { - return this.cachedSpawnPacket; - } else { - return this.cachedMinimizedSpawnPacket; + @Override + public void hide(Player player) { + for (FurnitureElement element : this.elements) { + element.hide(player); } } + @Nullable + @Override + public CullingData cullingData() { + return this.config.cullingData(); + } + + @NotNull + @Override + public FurnitureConfig config() { + return this.config; + } + + @NotNull + @Override + public FurnitureDataAccessor dataAccessor() { + return this.dataAccessor; + } + @Override public WorldPosition position() { return LocationUtils.toWorldPosition(this.location); } - @NotNull - public Location location() { - return this.location.clone(); - } - - @NotNull - public Entity baseEntity() { - Entity entity = this.baseEntity.get(); - if (entity == null) { - throw new RuntimeException("Base entity not found. It might be unloaded."); - } - return entity; + @Override + public boolean isValid() { + return this.valid; } @Override - public boolean isValid() { - return baseEntity().isValid(); + public void destroy() { + this.valid = false; + Optional.ofNullable(this.baseEntity.get()).ifPresent(Entity::remove); } - @NotNull - public Location dropLocation() { - Optional dropOffset = this.placement.dropOffset(); + @Override + public UUID uuid() { + return this.uuid; + } + + @Override + public int entityId() { + return this.entityId; + } + + public void teleport(WorldPosition position) { + Location newLocation = LocationUtils.toLocation(position); + if (newLocation.equals(this.location)) { + return; + } + this.setLocation(newLocation); + this.sync(); + } + + public Location location() { + return location; + } + + private void setLocation(Location location) { + this.location = location; + } + + public FurnitureVariant getVariant() { + return this.config.getVariant(this.dataAccessor.variant().orElseGet(this.config::anyVariantName)); + } + + public void setVariant(String variant) { + FurnitureVariant newVariant = this.config.getVariant(variant); + if (newVariant != this.currentVariant) { + this.currentVariant = newVariant; + this.sync(); + } + } + + // 获取掉落物的位置,受到家具变种的影响 + public Location getDropLocation() { + Optional dropOffset = this.getVariant().dropOffset(); if (dropOffset.isEmpty()) { return location(); } @@ -186,105 +168,4 @@ public class BukkitFurniture implements Furniture { Vector3f offset = conjugated.transform(new Vector3f(dropOffset.get())); return new Location(this.location.getWorld(), this.location.getX() + offset.x, this.location.getY() + offset.y, this.location.getZ() - offset.z); } - - @Override - public void destroy() { - if (!isValid()) { - return; - } - this.baseEntity().remove(); - this.destroyColliders(); - this.destroySeats(); - } - - @Override - public void destroyColliders() { - for (Collider entity : this.colliderEntities) { - if (entity != null) - entity.destroy(); - } - } - - @Override - public void destroySeats() { - for (HitBox hitBox : this.hitBoxes.values()) { - for (Seat seat : hitBox.seats()) { - seat.destroy(); - } - } - } - - @Override - public UUID uuid() { - return this.baseEntity().getUniqueId(); - } - - @Override - public int baseEntityId() { - return this.baseEntityId; - } - - @NotNull - public List entityIds() { - return Collections.unmodifiableList(this.entityIds); - } - - @NotNull - public List fakeEntityIds() { - return Collections.unmodifiableList(this.fakeEntityIds); - } - - public Collider[] collisionEntities() { - return this.colliderEntities; - } - - @Override - public @Nullable HitBox hitBoxByEntityId(int id) { - return this.hitBoxes.get(id); - } - - @Override - public @Nullable HitBoxPart hitBoxPartByEntityId(int id) { - return this.hitBoxParts.get(id); - } - - @Override - public @NotNull AnchorType anchorType() { - return this.placement.anchorType(); - } - - @Override - public @NotNull Key id() { - return this.furniture.id(); - } - - @Override - public @NotNull CustomFurniture config() { - return this.furniture; - } - - @Override - public boolean hasExternalModel() { - return hasExternalModel; - } - - @Override - public FurnitureExtraData extraData() { - return this.extraData; - } - - @Override - public void setExtraData(FurnitureExtraData extraData) { - this.extraData = extraData; - this.save(); - } - - @Override - public void save() { - try { - this.baseEntity().getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY, this.extraData.toBytes()); - } catch (IOException e) { - CraftEngine.instance().logger().warn("Failed to save furniture data.", e); - } - } } \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java deleted file mode 100644 index 83ca3fa4d..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureElement.java +++ /dev/null @@ -1,177 +0,0 @@ -package net.momirealms.craftengine.bukkit.entity.furniture; - -import it.unimi.dsi.fastutil.ints.IntArrayList; -import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; -import net.momirealms.craftengine.bukkit.item.BukkitItemManager; -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.Billboard; -import net.momirealms.craftengine.core.entity.ItemDisplayContext; -import net.momirealms.craftengine.core.entity.furniture.AbstractFurnitureElement; -import net.momirealms.craftengine.core.entity.furniture.Furniture; -import net.momirealms.craftengine.core.entity.furniture.FurnitureElement; -import net.momirealms.craftengine.core.item.Item; -import net.momirealms.craftengine.core.item.data.FireworkExplosion; -import net.momirealms.craftengine.core.util.Color; -import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.world.WorldPosition; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -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.UUID; -import java.util.function.Consumer; - -public class BukkitFurnitureElement extends AbstractFurnitureElement { - private final List commonValues; - - public BukkitFurnitureElement(Key item, - Billboard billboard, - ItemDisplayContext transform, - Vector3f scale, - Vector3f translation, - Vector3f position, - Quaternionf rotation, - float shadowRadius, - float shadowStrength, - boolean applyDyedColor) { - super(item, billboard, transform, scale, translation, position, rotation, shadowRadius, shadowStrength, applyDyedColor); - this.commonValues = new ArrayList<>(); - ItemDisplayEntityData.Scale.addEntityDataIfNotDefaultValue(scale(), this.commonValues); - ItemDisplayEntityData.RotationLeft.addEntityDataIfNotDefaultValue(rotation(), this.commonValues); - ItemDisplayEntityData.BillboardConstraints.addEntityDataIfNotDefaultValue(billboard().id(), this.commonValues); - ItemDisplayEntityData.Translation.addEntityDataIfNotDefaultValue(translation(), this.commonValues); - ItemDisplayEntityData.DisplayType.addEntityDataIfNotDefaultValue(transform().id(), this.commonValues); - ItemDisplayEntityData.ShadowRadius.addEntityDataIfNotDefaultValue(shadowRadius, this.commonValues); - ItemDisplayEntityData.ShadowStrength.addEntityDataIfNotDefaultValue(shadowStrength, this.commonValues); - } - - @Override - public void initPackets(Furniture furniture, int entityId, @NotNull Quaternionf conjugated, Consumer packets) { - WorldPosition position = furniture.position(); - Vector3f offset = conjugated.transform(new Vector3f(position())); - packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( - entityId, UUID.randomUUID(), position.x() + offset.x, position.y() + offset.y, position.z() - offset.z, 0, position.yRot(), - MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0 - )); - if (applyDyedColor()) { - packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, getCachedValues( - furniture.extraData().dyedColor().orElse(null), - furniture.extraData().fireworkExplosionColors().orElse(null) - ))); - } else { - packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId, getCachedValues(null, null))); - } - } - - private synchronized List getCachedValues(@Nullable Color color, int @Nullable [] colors) { - List cachedValues = new ArrayList<>(this.commonValues); - Item item = BukkitItemManager.instance().createWrappedItem(item(), null); - if (item == null) { - item = BukkitItemManager.instance().wrap(new ItemStack(Material.BARRIER)); - } else { - if (color != null) { - item.dyedColor(color); - } - if (colors != null) { - item.fireworkExplosion(new FireworkExplosion( - FireworkExplosion.Shape.SMALL_BALL, - new IntArrayList(colors), - new IntArrayList(), - false, - false - )); - } - } - ItemDisplayEntityData.DisplayedItem.addEntityDataIfNotDefaultValue(item.getLiteralObject(), cachedValues); - return cachedValues; - } - - public static Builder builder() { - return new BuilderImpl(); - } - - public static class BuilderImpl implements Builder { - private boolean applyDyedColor; - private Key item; - private Billboard billboard; - private ItemDisplayContext transform; - private Vector3f scale; - private Vector3f translation; - private Vector3f position; - private Quaternionf rotation; - private float shadowRadius; - private float shadowStrength; - - @Override - public Builder applyDyedColor(boolean applyDyedColor) { - this.applyDyedColor = applyDyedColor; - return this; - } - - @Override - public Builder item(Key item) { - this.item = item; - return this; - } - - @Override - public Builder billboard(Billboard billboard) { - this.billboard = billboard; - return this; - } - - @Override - public Builder transform(ItemDisplayContext transform) { - this.transform = transform; - return this; - } - - @Override - public Builder scale(Vector3f scale) { - this.scale = scale; - return this; - } - - @Override - public Builder translation(Vector3f translation) { - this.translation = translation; - return this; - } - - @Override - public Builder position(Vector3f position) { - this.position = position; - return this; - } - - @Override - public Builder rotation(Quaternionf rotation) { - this.rotation = rotation; - return this; - } - - @Override - public Builder shadowStrength(float shadowStrength) { - this.shadowStrength = shadowStrength; - return this; - } - - @Override - public Builder shadowRadius(float shadowRadius) { - this.shadowRadius = shadowRadius; - return this; - } - - @Override - public FurnitureElement build() { - return new BukkitFurnitureElement(item, billboard, transform, scale, translation, position, rotation, shadowRadius, shadowStrength, applyDyedColor); - } - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java index f946e4888..969727e89 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java @@ -1,34 +1,23 @@ package net.momirealms.craftengine.bukkit.entity.furniture; -import net.momirealms.craftengine.bukkit.api.BukkitAdaptors; import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.InteractionHitBoxConfig; -import net.momirealms.craftengine.bukkit.nms.CollisionEntity; -import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.bukkit.plugin.network.handler.FurniturePacketHandler; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; -import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; -import net.momirealms.craftengine.bukkit.util.EntityUtils; import net.momirealms.craftengine.bukkit.util.KeyUtils; -import net.momirealms.craftengine.bukkit.util.LocationUtils; import net.momirealms.craftengine.core.entity.furniture.*; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfig; import net.momirealms.craftengine.core.plugin.config.Config; -import net.momirealms.craftengine.core.sound.SoundData; -import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.WorldPosition; -import org.bukkit.*; -import org.bukkit.entity.*; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Boat; +import org.bukkit.entity.Interaction; import org.bukkit.event.HandlerList; -import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.Nullable; -import java.io.IOException; -import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.BiConsumer; public class BukkitFurnitureManager extends AbstractFurnitureManager { public static final NamespacedKey FURNITURE_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_KEY); @@ -56,30 +45,32 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { } @Override - public Furniture place(WorldPosition position, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) { - return this.place(LocationUtils.toLocation(position), furniture, extraData, playSound); + public Furniture place(WorldPosition position, FurnitureConfig furniture, FurnitureDataAccessor dataAccessor, boolean playSound) { +// return this.place(LocationUtils.toLocation(position), furniture, dataAccessor, playSound); + return null; } - public BukkitFurniture place(Location location, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) { - Optional optionalAnchorType = extraData.anchorType(); - if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) { - extraData.anchorType(furniture.getAnyAnchorType()); - } - Entity furnitureEntity = EntityUtils.spawnEntity(location.getWorld(), location, EntityType.ITEM_DISPLAY, entity -> { - ItemDisplay display = (ItemDisplay) entity; - display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_KEY, PersistentDataType.STRING, furniture.id().toString()); - try { - display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY, extraData.toBytes()); - } catch (IOException e) { - this.plugin.logger().warn("Failed to set furniture PDC for " + furniture.id().toString(), e); - } - handleBaseEntityLoadEarly(display); - }); - if (playSound) { - SoundData data = furniture.settings().sounds().placeSound(); - location.getWorld().playSound(location, data.id().toString(), SoundCategory.BLOCKS, data.volume().get(), data.pitch().get()); - } - return loadedFurnitureByRealEntityId(furnitureEntity.getEntityId()); + public BukkitFurniture place(Location location, FurnitureConfig furniture, FurnitureDataAccessor extraData, boolean playSound) { +// Optional optionalAnchorType = extraData.anchorType(); +// if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) { +// extraData.anchorType(furniture.getAnyAnchorType()); +// } +// Entity furnitureEntity = EntityUtils.spawnEntity(location.getWorld(), location, EntityType.ITEM_DISPLAY, entity -> { +// ItemDisplay display = (ItemDisplay) entity; +// display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_KEY, PersistentDataType.STRING, furniture.id().toString()); +// try { +// display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY, extraData.toBytes()); +// } catch (IOException e) { +// this.plugin.logger().warn("Failed to set furniture PDC for " + furniture.id().toString(), e); +// } +// handleBaseEntityLoadEarly(display); +// }); +// if (playSound) { +// SoundData data = furniture.settings().sounds().placeSound(); +// location.getWorld().playSound(location, data.id().toString(), SoundCategory.BLOCKS, data.volume().get(), data.pitch().get()); +// } +// return loadedFurnitureByRealEntityId(furnitureEntity.getEntityId()); + return null; } @Override @@ -88,34 +79,34 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { NMS_COLLISION_ENTITY_TYPE = Config.colliderType() == ColliderType.INTERACTION ? MEntityTypes.INTERACTION : MEntityTypes.OAK_BOAT; COLLISION_ENTITY_TYPE = Config.colliderType(); Bukkit.getPluginManager().registerEvents(this.furnitureEventListener, this.plugin.javaPlugin()); - if (VersionHelper.isFolia()) { - BiConsumer taskExecutor = (entity, runnable) -> entity.getScheduler().run(this.plugin.javaPlugin(), (t) -> runnable.run(), () -> {}); - for (World world : Bukkit.getWorlds()) { - List entities = world.getEntities(); - for (Entity entity : entities) { - if (entity instanceof ItemDisplay display) { - taskExecutor.accept(entity, () -> handleBaseEntityLoadEarly(display)); - } else if (entity instanceof Interaction interaction) { - taskExecutor.accept(entity, () -> handleCollisionEntityLoadOnEntitiesLoad(interaction)); - } else if (entity instanceof Boat boat) { - taskExecutor.accept(entity, () -> handleCollisionEntityLoadOnEntitiesLoad(boat)); - } - } - } - } else { - for (World world : Bukkit.getWorlds()) { - List entities = world.getEntities(); - for (Entity entity : entities) { - if (entity instanceof ItemDisplay display) { - handleBaseEntityLoadEarly(display); - } else if (entity instanceof Interaction interaction) { - handleCollisionEntityLoadOnEntitiesLoad(interaction); - } else if (entity instanceof Boat boat) { - handleCollisionEntityLoadOnEntitiesLoad(boat); - } - } - } - } +// if (VersionHelper.isFolia()) { +// BiConsumer taskExecutor = (entity, runnable) -> entity.getScheduler().run(this.plugin.javaPlugin(), (t) -> runnable.run(), () -> {}); +// for (World world : Bukkit.getWorlds()) { +// List entities = world.getEntities(); +// for (Entity entity : entities) { +// if (entity instanceof ItemDisplay display) { +// taskExecutor.accept(entity, () -> handleBaseEntityLoadEarly(display)); +// } else if (entity instanceof Interaction interaction) { +// taskExecutor.accept(entity, () -> handleCollisionEntityLoadOnEntitiesLoad(interaction)); +// } else if (entity instanceof Boat boat) { +// taskExecutor.accept(entity, () -> handleCollisionEntityLoadOnEntitiesLoad(boat)); +// } +// } +// } +// } else { +// for (World world : Bukkit.getWorlds()) { +// List entities = world.getEntities(); +// for (Entity entity : entities) { +// if (entity instanceof ItemDisplay display) { +// handleBaseEntityLoadEarly(display); +// } else if (entity instanceof Interaction interaction) { +// handleCollisionEntityLoadOnEntitiesLoad(interaction); +// } else if (entity instanceof Boat boat) { +// handleCollisionEntityLoadOnEntitiesLoad(boat); +// } +// } +// } +// } } @Override @@ -141,174 +132,165 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { return this.furnitureByEntityId.get(entityId); } - @Override - protected CustomFurniture.Builder furnitureBuilder() { - return BukkitCustomFurniture.builder(); - } - - @Override - protected FurnitureElement.Builder furnitureElementBuilder() { - return BukkitFurnitureElement.builder(); - } - - protected void handleBaseEntityUnload(Entity entity) { - int id = entity.getEntityId(); - BukkitFurniture furniture = this.furnitureByRealEntityId.remove(id); - if (furniture != null) { - Location location = entity.getLocation(); - boolean isPreventing = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4); - if (!isPreventing) { - furniture.destroySeats(); - } - for (int sub : furniture.entityIds()) { - this.furnitureByEntityId.remove(sub); - } - } - } - - protected void handleCollisionEntityUnload(Entity entity) { - int id = entity.getEntityId(); - this.furnitureByRealEntityId.remove(id); - } - - @SuppressWarnings("deprecation") // just a misleading name `getTrackedPlayers` - protected void handleBaseEntityLoadLate(ItemDisplay display, int depth) { - // must be a furniture item - String id = display.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING); - if (id == null) return; - - Key key = Key.of(id); - Optional optionalFurniture = furnitureById(key); - if (optionalFurniture.isEmpty()) return; - - CustomFurniture customFurniture = optionalFurniture.get(); - BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); - if (previous != null) return; - - Location location = display.getLocation(); - boolean above1_20_1 = VersionHelper.isOrAbove1_20_2(); - boolean preventChange = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4); - if (above1_20_1) { - if (!preventChange) { - BukkitFurniture furniture = addNewFurniture(display, customFurniture); - furniture.initializeColliders(); - for (Player player : display.getTrackedPlayers()) { - BukkitAdaptors.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds())); - this.plugin.networkManager().sendPacket(BukkitAdaptors.adapt(player), furniture.spawnPacket(player)); - } - } - } else { - BukkitFurniture furniture = addNewFurniture(display, customFurniture); - for (Player player : display.getTrackedPlayers()) { - BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player); - serverPlayer.entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds())); - this.plugin.networkManager().sendPacket(serverPlayer, furniture.spawnPacket(player)); - } - if (preventChange) { - this.plugin.scheduler().sync().runLater(furniture::initializeColliders, 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); - } else { - furniture.initializeColliders(); - } - } - if (depth > 2) return; - this.plugin.scheduler().sync().runLater(() -> handleBaseEntityLoadLate(display, depth + 1), 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); - } - - protected void handleCollisionEntityLoadLate(Entity entity, int depth) { - // remove the entity if it's not a collision entity, it might be wrongly copied by WorldEdit - if (FastNMS.INSTANCE.method$CraftEntity$getHandle(entity) instanceof CollisionEntity) { - return; - } - // not a collision entity - Byte flag = entity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE); - if (flag == null || flag != 1) { - return; - } - - Location location = entity.getLocation(); - World world = location.getWorld(); - int chunkX = location.getBlockX() >> 4; - int chunkZ = location.getBlockZ() >> 4; - if (!FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world), chunkX, chunkZ)) { - entity.remove(); - return; - } - - if (depth > 2) return; - plugin.scheduler().sync().runLater(() -> { - handleCollisionEntityLoadLate(entity, depth + 1); - }, 1, world, chunkX, chunkZ); - } - - public void handleBaseEntityLoadEarly(ItemDisplay display) { - String id = display.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING); - if (id == null) return; - // Remove the entity if it's not a valid furniture - if (Config.handleInvalidFurniture()) { - String mapped = Config.furnitureMappings().get(id); - if (mapped != null) { - if (mapped.isEmpty()) { - display.remove(); - return; - } else { - id = mapped; - display.getPersistentDataContainer().set(FURNITURE_KEY, PersistentDataType.STRING, id); - } - } - } - - Key key = Key.of(id); - Optional optionalFurniture = furnitureById(key); - if (optionalFurniture.isPresent()) { - CustomFurniture customFurniture = optionalFurniture.get(); - BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); - if (previous != null) return; - BukkitFurniture furniture = addNewFurniture(display, customFurniture); - furniture.initializeColliders(); // safely do it here - } - } - - public void handleCollisionEntityLoadOnEntitiesLoad(Entity collisionEntity) { - // faster - if (FastNMS.INSTANCE.method$CraftEntity$getHandle(collisionEntity) instanceof CollisionEntity) { - collisionEntity.remove(); - return; - } - - // not a collision entity - Byte flag = collisionEntity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE); - if (flag == null || flag != 1) { - return; - } - - collisionEntity.remove(); - } - - private FurnitureExtraData getFurnitureExtraData(Entity baseEntity) throws IOException { - byte[] extraData = baseEntity.getPersistentDataContainer().get(FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY); - if (extraData == null) return FurnitureExtraData.builder().build(); - return FurnitureExtraData.fromBytes(extraData); - } - - private synchronized BukkitFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture) { - FurnitureExtraData extraData; - try { - extraData = getFurnitureExtraData(display); - } catch (IOException e) { - extraData = FurnitureExtraData.builder().build(); - plugin.logger().warn("Furniture extra data could not be loaded", e); - } - BukkitFurniture bukkitFurniture = new BukkitFurniture(display, furniture, extraData); - this.furnitureByRealEntityId.put(bukkitFurniture.baseEntityId(), bukkitFurniture); - for (int entityId : bukkitFurniture.entityIds()) { - this.furnitureByEntityId.put(entityId, bukkitFurniture); - } - for (Collider collisionEntity : bukkitFurniture.collisionEntities()) { - int collisionEntityId = FastNMS.INSTANCE.method$Entity$getId(collisionEntity.handle()); - this.furnitureByRealEntityId.put(collisionEntityId, bukkitFurniture); - } - return bukkitFurniture; - } +// +// protected void handleBaseEntityUnload(Entity entity) { +// int id = entity.getEntityId(); +// BukkitFurniture furniture = this.furnitureByRealEntityId.remove(id); +// if (furniture != null) { +// Location location = entity.getLocation(); +// boolean isPreventing = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4); +// if (!isPreventing) { +// furniture.destroySeats(); +// } +// for (int sub : furniture.entityIds()) { +// this.furnitureByEntityId.remove(sub); +// } +// } +// } +// +// protected void handleCollisionEntityUnload(Entity entity) { +// int id = entity.getEntityId(); +// this.furnitureByRealEntityId.remove(id); +// } +// +// @SuppressWarnings("deprecation") // just a misleading name `getTrackedPlayers` +// protected void handleBaseEntityLoadLate(ItemDisplay display, int depth) { +// // must be a furniture item +// String id = display.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING); +// if (id == null) return; +// +// Key key = Key.of(id); +// Optional optionalFurniture = furnitureById(key); +// if (optionalFurniture.isEmpty()) return; +// +// FurnitureConfig customFurniture = optionalFurniture.get(); +// BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); +// if (previous != null) return; +// +// Location location = display.getLocation(); +// boolean above1_20_1 = VersionHelper.isOrAbove1_20_2(); +// boolean preventChange = FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(location.getWorld()), location.getBlockX() >> 4, location.getBlockZ() >> 4); +// if (above1_20_1) { +// if (!preventChange) { +// BukkitFurniture furniture = addNewFurniture(display, customFurniture); +// furniture.initializeColliders(); +// for (Player player : display.getTrackedPlayers()) { +// BukkitAdaptors.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds())); +// this.plugin.networkManager().sendPacket(BukkitAdaptors.adapt(player), furniture.spawnPacket(player)); +// } +// } +// } else { +// BukkitFurniture furniture = addNewFurniture(display, customFurniture); +// for (Player player : display.getTrackedPlayers()) { +// BukkitServerPlayer serverPlayer = BukkitAdaptors.adapt(player); +// serverPlayer.entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds())); +// this.plugin.networkManager().sendPacket(serverPlayer, furniture.spawnPacket(player)); +// } +// if (preventChange) { +// this.plugin.scheduler().sync().runLater(furniture::initializeColliders, 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); +// } else { +// furniture.initializeColliders(); +// } +// } +// if (depth > 2) return; +// this.plugin.scheduler().sync().runLater(() -> handleBaseEntityLoadLate(display, depth + 1), 1, location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); +// } +// +// protected void handleCollisionEntityLoadLate(Entity entity, int depth) { +// // remove the entity if it's not a collision entity, it might be wrongly copied by WorldEdit +// if (FastNMS.INSTANCE.method$CraftEntity$getHandle(entity) instanceof CollisionEntity) { +// return; +// } +// // not a collision entity +// Byte flag = entity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE); +// if (flag == null || flag != 1) { +// return; +// } +// +// Location location = entity.getLocation(); +// World world = location.getWorld(); +// int chunkX = location.getBlockX() >> 4; +// int chunkZ = location.getBlockZ() >> 4; +// if (!FastNMS.INSTANCE.method$ServerLevel$isPreventingStatusUpdates(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(world), chunkX, chunkZ)) { +// entity.remove(); +// return; +// } +// +// if (depth > 2) return; +// plugin.scheduler().sync().runLater(() -> { +// handleCollisionEntityLoadLate(entity, depth + 1); +// }, 1, world, chunkX, chunkZ); +// } +// +// public void handleBaseEntityLoadEarly(ItemDisplay display) { +// String id = display.getPersistentDataContainer().get(FURNITURE_KEY, PersistentDataType.STRING); +// if (id == null) return; +// // Remove the entity if it's not a valid furniture +// if (Config.handleInvalidFurniture()) { +// String mapped = Config.furnitureMappings().get(id); +// if (mapped != null) { +// if (mapped.isEmpty()) { +// display.remove(); +// return; +// } else { +// id = mapped; +// display.getPersistentDataContainer().set(FURNITURE_KEY, PersistentDataType.STRING, id); +// } +// } +// } +// +// Key key = Key.of(id); +// Optional optionalFurniture = furnitureById(key); +// if (optionalFurniture.isPresent()) { +// FurnitureConfig customFurniture = optionalFurniture.get(); +// BukkitFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); +// if (previous != null) return; +// BukkitFurniture furniture = addNewFurniture(display, customFurniture); +// furniture.initializeColliders(); // safely do it here +// } +// } +// +// public void handleCollisionEntityLoadOnEntitiesLoad(Entity collisionEntity) { +// // faster +// if (FastNMS.INSTANCE.method$CraftEntity$getHandle(collisionEntity) instanceof CollisionEntity) { +// collisionEntity.remove(); +// return; +// } +// +// // not a collision entity +// Byte flag = collisionEntity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE); +// if (flag == null || flag != 1) { +// return; +// } +// +// collisionEntity.remove(); +// } +// +// private FurnitureDataAccessor getFurnitureExtraData(Entity baseEntity) throws IOException { +// byte[] extraData = baseEntity.getPersistentDataContainer().get(FURNITURE_EXTRA_DATA_KEY, PersistentDataType.BYTE_ARRAY); +// if (extraData == null) return FurnitureDataAccessor.builder().build(); +// return FurnitureDataAccessor.fromBytes(extraData); +// } +// +// private synchronized BukkitFurniture addNewFurniture(ItemDisplay display, FurnitureConfig furniture) { +// FurnitureDataAccessor extraData; +// try { +// extraData = getFurnitureExtraData(display); +// } catch (IOException e) { +// extraData = FurnitureDataAccessor.builder().build(); +// plugin.logger().warn("Furniture extra data could not be loaded", e); +// } +// BukkitFurniture bukkitFurniture = new BukkitFurniture(display, furniture, extraData); +// this.furnitureByRealEntityId.put(bukkitFurniture.baseEntityId(), bukkitFurniture); +// for (int entityId : bukkitFurniture.entityIds()) { +// this.furnitureByEntityId.put(entityId, bukkitFurniture); +// } +// for (Collider collisionEntity : bukkitFurniture.collisionEntities()) { +// int collisionEntityId = FastNMS.INSTANCE.method$Entity$getId(collisionEntity.handle()); +// this.furnitureByRealEntityId.put(collisionEntityId, bukkitFurniture); +// } +// return bukkitFurniture; +// } @Override protected HitBoxConfig defaultHitBox() { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java index ce4864b90..5fa382018 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/FurnitureEventListener.java @@ -1,18 +1,6 @@ package net.momirealms.craftengine.bukkit.entity.furniture; -import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent; -import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent; -import org.bukkit.entity.Entity; -import org.bukkit.entity.ItemDisplay; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; -import org.bukkit.event.world.ChunkUnloadEvent; -import org.bukkit.event.world.EntitiesLoadEvent; -import org.bukkit.event.world.WorldLoadEvent; -import org.bukkit.event.world.WorldUnloadEvent; - -import java.util.List; public class FurnitureEventListener implements Listener { private final BukkitFurnitureManager manager; @@ -21,77 +9,77 @@ public class FurnitureEventListener implements Listener { this.manager = manager; } - /* - * Load Entities - */ - @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) - public void onEntitiesLoadEarly(EntitiesLoadEvent event) { - List entities = event.getEntities(); - for (Entity entity : entities) { - if (entity instanceof ItemDisplay itemDisplay) { - this.manager.handleBaseEntityLoadEarly(itemDisplay); - } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { - this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity); - } - } - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) - public void onWorldLoad(WorldLoadEvent event) { - List entities = event.getWorld().getEntities(); - for (Entity entity : entities) { - if (entity instanceof ItemDisplay itemDisplay) { - this.manager.handleBaseEntityLoadEarly(itemDisplay); - } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { - this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity); - } - } - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) - public void onEntityLoad(EntityAddToWorldEvent event) { - Entity entity = event.getEntity(); - if (entity instanceof ItemDisplay itemDisplay) { - this.manager.handleBaseEntityLoadLate(itemDisplay, 0); - } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { - this.manager.handleCollisionEntityLoadLate(entity, 0); - } - } - - /* - * Unload Entities - */ - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void onChunkUnload(ChunkUnloadEvent event) { - Entity[] entities = event.getChunk().getEntities(); - for (Entity entity : entities) { - if (entity instanceof ItemDisplay) { - this.manager.handleBaseEntityUnload(entity); - } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { - this.manager.handleCollisionEntityUnload(entity); - } - } - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void onWorldUnload(WorldUnloadEvent event) { - List entities = event.getWorld().getEntities(); - for (Entity entity : entities) { - if (entity instanceof ItemDisplay) { - this.manager.handleBaseEntityUnload(entity); - } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { - this.manager.handleCollisionEntityUnload(entity); - } - } - } - - @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) - public void onEntityUnload(EntityRemoveFromWorldEvent event) { - Entity entity = event.getEntity(); - if (entity instanceof ItemDisplay) { - this.manager.handleBaseEntityUnload(entity); - } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { - this.manager.handleCollisionEntityUnload(entity); - } - } +// /* +// * Load Entities +// */ +// @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) +// public void onEntitiesLoadEarly(EntitiesLoadEvent event) { +// List entities = event.getEntities(); +// for (Entity entity : entities) { +// if (entity instanceof ItemDisplay itemDisplay) { +// this.manager.handleBaseEntityLoadEarly(itemDisplay); +// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { +// this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity); +// } +// } +// } +// +// @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) +// public void onWorldLoad(WorldLoadEvent event) { +// List entities = event.getWorld().getEntities(); +// for (Entity entity : entities) { +// if (entity instanceof ItemDisplay itemDisplay) { +// this.manager.handleBaseEntityLoadEarly(itemDisplay); +// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { +// this.manager.handleCollisionEntityLoadOnEntitiesLoad(entity); +// } +// } +// } +// +// @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) +// public void onEntityLoad(EntityAddToWorldEvent event) { +// Entity entity = event.getEntity(); +// if (entity instanceof ItemDisplay itemDisplay) { +// this.manager.handleBaseEntityLoadLate(itemDisplay, 0); +// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { +// this.manager.handleCollisionEntityLoadLate(entity, 0); +// } +// } +// +// /* +// * Unload Entities +// */ +// @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) +// public void onChunkUnload(ChunkUnloadEvent event) { +// Entity[] entities = event.getChunk().getEntities(); +// for (Entity entity : entities) { +// if (entity instanceof ItemDisplay) { +// this.manager.handleBaseEntityUnload(entity); +// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { +// this.manager.handleCollisionEntityUnload(entity); +// } +// } +// } +// +// @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) +// public void onWorldUnload(WorldUnloadEvent event) { +// List entities = event.getWorld().getEntities(); +// for (Entity entity : entities) { +// if (entity instanceof ItemDisplay) { +// this.manager.handleBaseEntityUnload(entity); +// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { +// this.manager.handleCollisionEntityUnload(entity); +// } +// } +// } +// +// @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) +// public void onEntityUnload(EntityRemoveFromWorldEvent event) { +// Entity entity = event.getEntity(); +// if (entity instanceof ItemDisplay) { +// this.manager.handleBaseEntityUnload(entity); +// } else if (BukkitFurnitureManager.COLLISION_ENTITY_CLASS.isInstance(entity)) { +// this.manager.handleCollisionEntityUnload(entity); +// } +// } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/ItemColorSource.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/ItemColorSource.java new file mode 100644 index 000000000..339dad09d --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/ItemColorSource.java @@ -0,0 +1,6 @@ +package net.momirealms.craftengine.bukkit.entity.furniture; + +import net.momirealms.craftengine.core.util.Color; + +public record ItemColorSource(Color dyedColor, int[] fireworkColors) { +} 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 new file mode 100644 index 000000000..4ce2d57f2 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/BukkitFurnitureElementConfigs.java @@ -0,0 +1,15 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.element; + +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigs; + +public class BukkitFurnitureElementConfigs extends FurnitureElementConfigs { + + static { + register(ITEM_DISPLAY, ItemDisplayFurnitureElementConfig.FACTORY); + } + + private BukkitFurnitureElementConfigs() {} + + public static void init() { + } +} 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 new file mode 100644 index 000000000..5c92715cf --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElement.java @@ -0,0 +1,22 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.element; + +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement; +import net.momirealms.craftengine.core.entity.player.Player; + +public class ItemDisplayFurnitureElement implements FurnitureElement { + private final ItemDisplayFurnitureElementConfig config; + + public ItemDisplayFurnitureElement(ItemDisplayFurnitureElementConfig config) { + this.config = config; + } + + @Override + public void show(Player player) { + + } + + @Override + public void hide(Player player) { + + } +} 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 new file mode 100644 index 000000000..8edc5d489 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java @@ -0,0 +1,169 @@ +package net.momirealms.craftengine.bukkit.entity.furniture.element; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; +import net.momirealms.craftengine.bukkit.entity.furniture.ItemColorSource; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.core.entity.display.Billboard; +import net.momirealms.craftengine.core.entity.display.ItemDisplayContext; +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement; +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 net.momirealms.craftengine.core.world.WorldPosition; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +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.BiFunction; + +public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig { + public static final Factory FACTORY = new Factory(); + private final BiFunction> lazyMetadataPacket; + private final BiFunction> item; + private final Vector3f scale; + private final Vector3f position; + private final Vector3f translation; + private final float xRot; + private final float yRot; + private final Quaternionf rotation; + private final ItemDisplayContext displayContext; + private final Billboard billboard; + private final float shadowRadius; + private final float shadowStrength; + private final boolean applyDyedColor; + + public ItemDisplayFurnitureElementConfig(BiFunction> item, + Vector3f scale, + Vector3f position, + Vector3f translation, + float xRot, + float yRot, + Quaternionf rotation, + ItemDisplayContext displayContext, + Billboard billboard, + float shadowRadius, + float shadowStrength, + boolean applyDyedColor) { + 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.applyDyedColor = applyDyedColor; + this.item = item; + this.lazyMetadataPacket = (player, source) -> { + List dataValues = new ArrayList<>(); + ItemDisplayEntityData.DisplayedItem.addEntityData(item.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); + return dataValues; + }; + } + + public Vector3f scale() { + return scale; + } + + public Vector3f position() { + return position; + } + + public Vector3f translation() { + return translation; + } + + public float xRot() { + return xRot; + } + + public float yRot() { + return yRot; + } + + public Quaternionf rotation() { + return rotation; + } + + public ItemDisplayContext displayContext() { + return displayContext; + } + + public Billboard billboard() { + return billboard; + } + + public float shadowRadius() { + return shadowRadius; + } + + public float shadowStrength() { + return shadowStrength; + } + + public boolean applyDyedColor() { + return applyDyedColor; + } + + @Override + public ItemDisplayFurnitureElement create(@NotNull WorldPosition position) { + return new ItemDisplayFurnitureElement(this); + } + + public static class Factory implements FurnitureElementConfigFactory { + + @SuppressWarnings("unchecked") + @Override + public FurnitureElementConfig 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"); + return (FurnitureElementConfig) new ItemDisplayFurnitureElementConfig( + (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)); + }, + ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("scale", 1f), "scale"), + ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", 0.5f), "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"), + applyDyedColor + ); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitHitBoxTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitHitBoxTypes.java index 4d92bd7c8..017824a2a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitHitBoxTypes.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/BukkitHitBoxTypes.java @@ -1,6 +1,6 @@ package net.momirealms.craftengine.bukkit.entity.furniture.hitbox; -import net.momirealms.craftengine.core.entity.furniture.HitBoxTypes; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxTypes; public class BukkitHitBoxTypes extends HitBoxTypes { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomHitBoxConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomHitBoxConfig.java index fa8e974a8..2b5abc32e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomHitBoxConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/CustomHitBoxConfig.java @@ -1,42 +1,34 @@ package net.momirealms.craftengine.bukkit.entity.furniture.hitbox; -import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData; -import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections; -import net.momirealms.craftengine.core.entity.furniture.*; +import net.momirealms.craftengine.core.entity.furniture.hitbox.AbstractHitBoxConfig; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfig; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfigFactory; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxTypes; import net.momirealms.craftengine.core.entity.seat.SeatConfig; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceConfigUtils; -import net.momirealms.craftengine.core.util.VersionHelper; -import net.momirealms.craftengine.core.world.WorldPosition; -import net.momirealms.craftengine.core.world.collision.AABB; import org.bukkit.NamespacedKey; import org.bukkit.Registry; import org.bukkit.entity.EntityType; -import org.joml.Quaternionf; import org.joml.Vector3f; -import java.util.*; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Supplier; +import java.util.Map; public class CustomHitBoxConfig extends AbstractHitBoxConfig { public static final Factory FACTORY = new Factory(); private final float scale; private final EntityType entityType; - private final List cachedValues = new ArrayList<>(); - public CustomHitBoxConfig(SeatConfig[] seats, Vector3f position, EntityType type, float scale, boolean blocksBuilding, boolean canBeHitByProjectile) { + public CustomHitBoxConfig(SeatConfig[] seats, + Vector3f position, + EntityType type, + float scale, + boolean blocksBuilding, + boolean canBeHitByProjectile) { super(seats, position, false, blocksBuilding, canBeHitByProjectile); this.scale = scale; this.entityType = type; - BaseEntityData.NoGravity.addEntityDataIfNotDefaultValue(true, this.cachedValues); - BaseEntityData.Silent.addEntityDataIfNotDefaultValue(true, this.cachedValues); - BaseEntityData.SharedFlags.addEntityDataIfNotDefaultValue((byte) 0x20, this.cachedValues); } public EntityType entityType() { @@ -52,41 +44,13 @@ public class CustomHitBoxConfig extends AbstractHitBoxConfig { return HitBoxTypes.CUSTOM; } - @Override - public void initPacketsAndColliders(int[] entityId, WorldPosition position, Quaternionf conjugated, BiConsumer packets, Consumer collider, Consumer aabb) { - Vector3f offset = conjugated.transform(new Vector3f(position())); - try { - packets.accept(FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( - entityId[0], UUID.randomUUID(), position.x() + offset.x, position.y() + offset.y, position.z() - offset.z, 0, position.yRot(), - FastNMS.INSTANCE.method$CraftEntityType$toNMSEntityType(this.entityType), 0, CoreReflections.instance$Vec3$Zero, 0 - ), true); - packets.accept(FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(entityId[0], List.copyOf(this.cachedValues)), true); - if (VersionHelper.isOrAbove1_20_5() && this.scale != 1) { - Object attributeInstance = CoreReflections.constructor$AttributeInstance.newInstance(MAttributeHolders.SCALE, (Consumer) (o) -> {}); - CoreReflections.method$AttributeInstance$setBaseValue.invoke(attributeInstance, this.scale); - packets.accept(NetworkReflections.constructor$ClientboundUpdateAttributesPacket0.newInstance(entityId[0], Collections.singletonList(attributeInstance)), false); - } - } catch (ReflectiveOperationException e) { - throw new RuntimeException("Failed to construct custom hitbox spawn packet", e); - } - } - - @Override - public void initShapeForPlacement(double x, double y, double z, float yaw, Quaternionf conjugated, Consumer aabbs) { - } - - @Override - public int[] acquireEntityIds(Supplier entityIdSupplier) { - return new int[] {entityIdSupplier.get()}; - } - public static class Factory implements HitBoxConfigFactory { @Override public HitBoxConfig create(Map arguments) { Vector3f position = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("position", "0"), "position"); float scale = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("scale", 1), "scale"); - String type = (String) arguments.getOrDefault("entity-type", "slime"); + String type = (String) arguments.getOrDefault("entity-id", "slime"); EntityType entityType = Registry.ENTITY_TYPE.get(new NamespacedKey("minecraft", type)); if (entityType == null) { throw new LocalizedResourceConfigException("warning.config.furniture.hitbox.custom.invalid_entity", new IllegalArgumentException("EntityType not found: " + type), type); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastHitBoxConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastHitBoxConfig.java index 5663b9f87..df7d249fe 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastHitBoxConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/HappyGhastHitBoxConfig.java @@ -7,7 +7,8 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeHolders; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections; -import net.momirealms.craftengine.core.entity.furniture.*; +import net.momirealms.craftengine.core.entity.furniture.Collider; +import net.momirealms.craftengine.core.entity.furniture.hitbox.*; import net.momirealms.craftengine.core.entity.seat.SeatConfig; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceConfigUtils; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionHitBoxConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionHitBoxConfig.java index 60bec26d4..0d29c0ad2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionHitBoxConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/InteractionHitBoxConfig.java @@ -5,7 +5,8 @@ import net.momirealms.craftengine.bukkit.entity.furniture.BukkitCollider; 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.*; +import net.momirealms.craftengine.core.entity.furniture.Collider; +import net.momirealms.craftengine.core.entity.furniture.hitbox.*; import net.momirealms.craftengine.core.entity.seat.SeatConfig; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceConfigUtils; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerHitBoxConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerHitBoxConfig.java index 57034cc9a..f24f79b10 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerHitBoxConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/hitbox/ShulkerHitBoxConfig.java @@ -9,7 +9,8 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MAttributeH import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.NetworkReflections; import net.momirealms.craftengine.bukkit.util.DirectionUtils; -import net.momirealms.craftengine.core.entity.furniture.*; +import net.momirealms.craftengine.core.entity.furniture.Collider; +import net.momirealms.craftengine.core.entity.furniture.hitbox.*; import net.momirealms.craftengine.core.entity.seat.SeatConfig; import net.momirealms.craftengine.core.util.*; import net.momirealms.craftengine.core.world.Vec3d; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java index 81df0accb..b92b4440e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/FurnitureItemBehavior.java @@ -1,43 +1,18 @@ package net.momirealms.craftengine.bukkit.item.behavior; -import net.momirealms.craftengine.bukkit.api.event.FurnitureAttemptPlaceEvent; -import net.momirealms.craftengine.bukkit.api.event.FurniturePlaceEvent; -import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; -import net.momirealms.craftengine.bukkit.nms.FastNMS; -import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.bukkit.util.DirectionUtils; -import net.momirealms.craftengine.bukkit.util.EventUtils; -import net.momirealms.craftengine.bukkit.util.LocationUtils; -import net.momirealms.craftengine.core.entity.furniture.AnchorType; -import net.momirealms.craftengine.core.entity.furniture.CustomFurniture; -import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData; -import net.momirealms.craftengine.core.entity.furniture.HitBoxConfig; import net.momirealms.craftengine.core.entity.player.InteractionResult; -import net.momirealms.craftengine.core.entity.player.Player; -import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; import net.momirealms.craftengine.core.item.context.UseOnContext; import net.momirealms.craftengine.core.pack.Pack; import net.momirealms.craftengine.core.pack.PendingConfigSection; -import net.momirealms.craftengine.core.plugin.CraftEngine; -import net.momirealms.craftengine.core.plugin.context.ContextHolder; -import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; -import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; -import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; -import net.momirealms.craftengine.core.util.*; -import net.momirealms.craftengine.core.world.Vec3d; -import net.momirealms.craftengine.core.world.collision.AABB; -import org.bukkit.Location; -import org.bukkit.World; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.MiscUtils; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; import java.util.Map; -import java.util.Optional; public class FurnitureItemBehavior extends ItemBehavior { public static final Factory FACTORY = new Factory(); @@ -57,121 +32,121 @@ public class FurnitureItemBehavior extends ItemBehavior { } public InteractionResult place(UseOnContext context) { - Optional optionalCustomFurniture = BukkitFurnitureManager.instance().furnitureById(this.id); - if (optionalCustomFurniture.isEmpty()) { - CraftEngine.instance().logger().warn("Furniture " + this.id + " not found"); - return InteractionResult.FAIL; - } - CustomFurniture customFurniture = optionalCustomFurniture.get(); - - Direction clickedFace = context.getClickedFace(); - AnchorType anchorType = switch (clickedFace) { - case EAST, WEST, NORTH, SOUTH -> AnchorType.WALL; - case UP -> AnchorType.GROUND; - case DOWN -> AnchorType.CEILING; - }; - - CustomFurniture.Placement placement = customFurniture.getPlacement(anchorType); - if (placement == null) { - return InteractionResult.FAIL; - } - - Player player = context.getPlayer(); - // todo adventure check - if (player != null && player.isAdventureMode()) { - return InteractionResult.FAIL; - } - - Vec3d clickedPosition = context.getClickLocation(); - - // trigger event - org.bukkit.entity.Player bukkitPlayer = player != null ? (org.bukkit.entity.Player) player.platformPlayer() : null; - World world = (World) context.getLevel().platformWorld(); - - // get position and rotation for placement - Vec3d finalPlacePosition; - double furnitureYaw; - if (anchorType == AnchorType.WALL) { - furnitureYaw = Direction.getYaw(clickedFace); - if (clickedFace == Direction.EAST || clickedFace == Direction.WEST) { - Pair xz = placement.alignmentRule().apply(Pair.of(clickedPosition.y(), clickedPosition.z())); - finalPlacePosition = new Vec3d(clickedPosition.x(), xz.left(), xz.right()); - } else { - Pair xz = placement.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.y())); - finalPlacePosition = new Vec3d(xz.left(), xz.right(), clickedPosition.z()); - } - } else { - furnitureYaw = placement.rotationRule().apply(180 + (player != null ? player.yRot() : 0)); - Pair xz = placement.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.z())); - finalPlacePosition = new Vec3d(xz.left(), clickedPosition.y(), xz.right()); - } - - Location furnitureLocation = new Location(world, finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, 0); - - List aabbs = new ArrayList<>(); - for (HitBoxConfig hitBoxConfig : placement.hitBoxConfigs()) { - hitBoxConfig.initShapeForPlacement(finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - furnitureYaw), 0).conjugate(), aabbs::add); - } - if (!aabbs.isEmpty()) { - if (!FastNMS.INSTANCE.checkEntityCollision(context.getLevel().serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList())) { - return InteractionResult.FAIL; - } - } - - if (!BukkitCraftEngine.instance().antiGriefProvider().canPlace(bukkitPlayer, furnitureLocation)) { - return InteractionResult.FAIL; - } - - if (player != null) { - FurnitureAttemptPlaceEvent attemptPlaceEvent = new FurnitureAttemptPlaceEvent(bukkitPlayer, customFurniture, anchorType, furnitureLocation.clone(), - DirectionUtils.toBlockFace(clickedFace), context.getHand(), world.getBlockAt(context.getClickedPos().x(), context.getClickedPos().y(), context.getClickedPos().z())); - if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) { - return InteractionResult.FAIL; - } - } - - Item item = context.getItem(); - // 不可能 - if (ItemUtils.isEmpty(item)) return InteractionResult.FAIL; - - BukkitFurniture bukkitFurniture = BukkitFurnitureManager.instance().place( - furnitureLocation.clone(), customFurniture, - FurnitureExtraData.builder() - .item(item.copyWithCount(1)) - .anchorType(anchorType) - .dyedColor(item.dyedColor().orElse(null)) - .fireworkExplosionColors(item.fireworkExplosion().map(explosion -> explosion.colors().toIntArray()).orElse(null)) - .build(), false); - - if (player != null) { - FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, bukkitFurniture, furnitureLocation, context.getHand()); - if (EventUtils.fireAndCheckCancel(placeEvent)) { - bukkitFurniture.destroy(); - return InteractionResult.FAIL; - } - } - - Cancellable dummy = Cancellable.dummy(); - PlayerOptionalContext functionContext = PlayerOptionalContext.of(player, ContextHolder.builder() - .withParameter(DirectContextParameters.FURNITURE, bukkitFurniture) - .withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(furnitureLocation)) - .withParameter(DirectContextParameters.EVENT, dummy) - .withParameter(DirectContextParameters.HAND, context.getHand()) - .withParameter(DirectContextParameters.ITEM_IN_HAND, item) - ); - customFurniture.execute(functionContext, EventTrigger.PLACE); - if (dummy.isCancelled()) { - return InteractionResult.SUCCESS_AND_CANCEL; - } - - if (player != null) { - if (!player.canInstabuild()) { - item.count(item.count() - 1); - } - player.swingHand(context.getHand()); - } - - context.getLevel().playBlockSound(finalPlacePosition, customFurniture.settings().sounds().placeSound()); +// Optional optionalCustomFurniture = BukkitFurnitureManager.instance().furnitureById(this.id); +// if (optionalCustomFurniture.isEmpty()) { +// CraftEngine.instance().logger().warn("Furniture " + this.id + " not found"); +// return InteractionResult.FAIL; +// } +// FurnitureConfig customFurniture = optionalCustomFurniture.get(); +// +// Direction clickedFace = context.getClickedFace(); +// AnchorType anchorType = switch (clickedFace) { +// case EAST, WEST, NORTH, SOUTH -> AnchorType.WALL; +// case UP -> AnchorType.GROUND; +// case DOWN -> AnchorType.CEILING; +// }; +// +// FurnitureConfig.Variant placement = customFurniture.getPlacement(anchorType); +// if (placement == null) { +// return InteractionResult.FAIL; +// } +// +// Player player = context.getPlayer(); +// // todo adventure check +// if (player != null && player.isAdventureMode()) { +// return InteractionResult.FAIL; +// } +// +// Vec3d clickedPosition = context.getClickLocation(); +// +// // trigger event +// org.bukkit.entity.Player bukkitPlayer = player != null ? (org.bukkit.entity.Player) player.platformPlayer() : null; +// World world = (World) context.getLevel().platformWorld(); +// +// // get position and rotation for placement +// Vec3d finalPlacePosition; +// double furnitureYaw; +// if (anchorType == AnchorType.WALL) { +// furnitureYaw = Direction.getYaw(clickedFace); +// if (clickedFace == Direction.EAST || clickedFace == Direction.WEST) { +// Pair xz = placement.alignmentRule().apply(Pair.of(clickedPosition.y(), clickedPosition.z())); +// finalPlacePosition = new Vec3d(clickedPosition.x(), xz.left(), xz.right()); +// } else { +// Pair xz = placement.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.y())); +// finalPlacePosition = new Vec3d(xz.left(), xz.right(), clickedPosition.z()); +// } +// } else { +// furnitureYaw = placement.rotationRule().apply(180 + (player != null ? player.yRot() : 0)); +// Pair xz = placement.alignmentRule().apply(Pair.of(clickedPosition.x(), clickedPosition.z())); +// finalPlacePosition = new Vec3d(xz.left(), clickedPosition.y(), xz.right()); +// } +// +// Location furnitureLocation = new Location(world, finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, 0); +// +// List aabbs = new ArrayList<>(); +// for (HitBoxConfig hitBoxConfig : placement.hitBoxConfigs()) { +// hitBoxConfig.initShapeForPlacement(finalPlacePosition.x(), finalPlacePosition.y(), finalPlacePosition.z(), (float) furnitureYaw, QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - furnitureYaw), 0).conjugate(), aabbs::add); +// } +// if (!aabbs.isEmpty()) { +// if (!FastNMS.INSTANCE.checkEntityCollision(context.getLevel().serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList())) { +// return InteractionResult.FAIL; +// } +// } +// +// if (!BukkitCraftEngine.instance().antiGriefProvider().canPlace(bukkitPlayer, furnitureLocation)) { +// return InteractionResult.FAIL; +// } +// +// if (player != null) { +// FurnitureAttemptPlaceEvent attemptPlaceEvent = new FurnitureAttemptPlaceEvent(bukkitPlayer, customFurniture, anchorType, furnitureLocation.clone(), +// DirectionUtils.toBlockFace(clickedFace), context.getHand(), world.getBlockAt(context.getClickedPos().x(), context.getClickedPos().y(), context.getClickedPos().z())); +// if (EventUtils.fireAndCheckCancel(attemptPlaceEvent)) { +// return InteractionResult.FAIL; +// } +// } +// +// Item item = context.getItem(); +// // 不可能 +// if (ItemUtils.isEmpty(item)) return InteractionResult.FAIL; +// +// BukkitFurniture bukkitFurniture = BukkitFurnitureManager.instance().place( +// furnitureLocation.clone(), customFurniture, +// FurnitureDataAccessor.builder() +// .item(item.copyWithCount(1)) +// .anchorType(anchorType) +// .dyedColor(item.dyedColor().orElse(null)) +// .fireworkExplosionColors(item.fireworkExplosion().map(explosion -> explosion.colors().toIntArray()).orElse(null)) +// .build(), false); +// +// if (player != null) { +// FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, bukkitFurniture, furnitureLocation, context.getHand()); +// if (EventUtils.fireAndCheckCancel(placeEvent)) { +// bukkitFurniture.destroy(); +// return InteractionResult.FAIL; +// } +// } +// +// Cancellable dummy = Cancellable.dummy(); +// PlayerOptionalContext functionContext = PlayerOptionalContext.of(player, ContextHolder.builder() +// .withParameter(DirectContextParameters.FURNITURE, bukkitFurniture) +// .withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(furnitureLocation)) +// .withParameter(DirectContextParameters.EVENT, dummy) +// .withParameter(DirectContextParameters.HAND, context.getHand()) +// .withParameter(DirectContextParameters.ITEM_IN_HAND, item) +// ); +// customFurniture.execute(functionContext, EventTrigger.PLACE); +// if (dummy.isCancelled()) { +// return InteractionResult.SUCCESS_AND_CANCEL; +// } +// +// if (player != null) { +// if (!player.canInstabuild()) { +// item.count(item.count() - 1); +// } +// player.swingHand(context.getHand()); +// } +// +// context.getLevel().playBlockSound(finalPlacePosition, customFurniture.settings().sounds().placeSound()); return InteractionResult.SUCCESS; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java index ce298bf65..d312a801d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitCraftEngine.java @@ -7,6 +7,7 @@ import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.block.behavior.BukkitBlockBehaviors; import net.momirealms.craftengine.bukkit.block.entity.renderer.element.BukkitBlockEntityElementConfigs; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; +import net.momirealms.craftengine.bukkit.entity.furniture.element.BukkitFurnitureElementConfigs; import net.momirealms.craftengine.bukkit.entity.furniture.hitbox.BukkitHitBoxTypes; import net.momirealms.craftengine.bukkit.entity.projectile.BukkitProjectileManager; import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeatManager; @@ -162,6 +163,7 @@ public class BukkitCraftEngine extends CraftEngine { BukkitItemBehaviors.init(); BukkitHitBoxTypes.init(); BukkitBlockEntityElementConfigs.init(); + BukkitFurnitureElementConfigs.init(); // 初始化 onload 阶段的兼容性 super.compatibilityManager().onLoad(); // 创建网络管理器 diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitPlatform.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitPlatform.java index 9a6729b0a..352ffd619 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitPlatform.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/BukkitPlatform.java @@ -39,7 +39,7 @@ public class BukkitPlatform implements Platform { Map map = (Map) MRegistryOps.NBT.convertTo(MRegistryOps.JAVA, tag); return map.get("root"); } catch (CommandSyntaxException e) { - throw new LocalizedResourceConfigException("warning.config.type.snbt.invalid_syntax", e, nbt); + throw new LocalizedResourceConfigException("warning.config.id.snbt.invalid_syntax", e, nbt); } } @@ -55,7 +55,7 @@ public class BukkitPlatform implements Platform { CompoundTag map = (CompoundTag) MRegistryOps.NBT.convertTo(MRegistryOps.SPARROW_NBT, tag); return map.get("root"); } catch (CommandSyntaxException e) { - throw new LocalizedResourceConfigException("warning.config.type.snbt.invalid_syntax", e, nbt); + throw new LocalizedResourceConfigException("warning.config.id.snbt.invalid_syntax", e, nbt); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugItemDataCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugItemDataCommand.java index 861c01eb5..1b4b1a942 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugItemDataCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugItemDataCommand.java @@ -115,7 +115,7 @@ public class DebugItemDataCommand extends BukkitCommandFeature { } else if (nbt instanceof short[]) { value = Arrays.toString((short[]) nbt); } else { - value = "Unknown array type"; + value = "Unknown array id"; } } else { value = nbt.toString(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugSpawnFurnitureCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugSpawnFurnitureCommand.java index a6333f2d5..e1d29f243 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugSpawnFurnitureCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/DebugSpawnFurnitureCommand.java @@ -5,7 +5,7 @@ import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; import net.momirealms.craftengine.bukkit.util.KeyUtils; import net.momirealms.craftengine.core.entity.furniture.AnchorType; -import net.momirealms.craftengine.core.entity.furniture.CustomFurniture; +import net.momirealms.craftengine.core.entity.furniture.FurnitureConfig; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.command.CraftEngineCommandManager; import net.momirealms.craftengine.core.plugin.command.FlagKeys; @@ -42,19 +42,19 @@ public class DebugSpawnFurnitureCommand extends BukkitCommandFeature { NamespacedKey namespacedKey = context.get("id"); Key id = KeyUtils.namespacedKey2Key(namespacedKey); BukkitFurnitureManager furnitureManager = BukkitFurnitureManager.instance(); - Optional optionalCustomFurniture = furnitureManager.furnitureById(id); + Optional optionalCustomFurniture = furnitureManager.furnitureById(id); if (optionalCustomFurniture.isEmpty()) { return; } Location location = context.get("location"); - CustomFurniture customFurniture = optionalCustomFurniture.get(); - AnchorType anchorType = (AnchorType) context.optional("anchor-type").orElse(customFurniture.getAnyAnchorType()); + FurnitureConfig customFurniture = optionalCustomFurniture.get(); + AnchorType anchorType = (AnchorType) context.optional("anchor-id").orElse(customFurniture.getAnyAnchorType()); boolean playSound = context.flags().hasFlag("silent"); CraftEngineFurniture.place(location, customFurniture, anchorType, playSound); }); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ToggleEntityCullingCommand.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ToggleEntityCullingCommand.java index b46f47699..29971f70a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ToggleEntityCullingCommand.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/command/feature/ToggleEntityCullingCommand.java @@ -15,7 +15,6 @@ import org.bukkit.entity.Player; import org.incendo.cloud.Command; import org.incendo.cloud.bukkit.parser.PlayerParser; import org.incendo.cloud.parser.standard.BooleanParser; -import org.incendo.cloud.parser.standard.DoubleParser; import java.util.Optional; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java index 8ea7189f7..92686686d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/BukkitNetworkManager.java @@ -59,8 +59,8 @@ import net.momirealms.craftengine.bukkit.world.BukkitWorldManager; import net.momirealms.craftengine.core.advancement.network.AdvancementHolder; import net.momirealms.craftengine.core.advancement.network.AdvancementProgress; import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.entity.furniture.HitBox; -import net.momirealms.craftengine.core.entity.furniture.HitBoxPart; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBox; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxPart; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.seat.Seat; import net.momirealms.craftengine.core.font.FontManager; @@ -3711,11 +3711,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes if (actionType == 1) { // ATTACK boolean usingSecondaryAction = buf.readBoolean(); - if (entityId != furniture.baseEntityId()) { + if (entityId != furniture.entityId()) { event.setChanged(true); buf.clear(); buf.writeVarInt(event.packetID()); - buf.writeVarInt(furniture.baseEntityId()); + buf.writeVarInt(furniture.entityId()); buf.writeVarInt(actionType); buf.writeBoolean(usingSecondaryAction); } @@ -3765,11 +3765,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes float z = buf.readFloat(); InteractionHand hand = buf.readVarInt() == 0 ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; boolean usingSecondaryAction = buf.readBoolean(); - if (entityId != furniture.baseEntityId()) { + if (entityId != furniture.entityId()) { event.setChanged(true); buf.clear(); buf.writeVarInt(event.packetID()); - buf.writeVarInt(furniture.baseEntityId()); + buf.writeVarInt(furniture.entityId()); buf.writeVarInt(actionType); buf.writeFloat(x).writeFloat(y).writeFloat(z); buf.writeVarInt(hand == InteractionHand.MAIN_HAND ? 0 : 1); @@ -3864,11 +3864,11 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes } else if (actionType == 0) { int hand = buf.readVarInt(); boolean usingSecondaryAction = buf.readBoolean(); - if (entityId != furniture.baseEntityId()) { + if (entityId != furniture.entityId()) { event.setChanged(true); buf.clear(); buf.writeVarInt(event.packetID()); - buf.writeVarInt(furniture.baseEntityId()); + buf.writeVarInt(furniture.entityId()); buf.writeVarInt(actionType); buf.writeVarInt(hand); buf.writeBoolean(usingSecondaryAction); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/ProjectilePacketHandler.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/ProjectilePacketHandler.java index 81ad7c893..62390bef7 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/ProjectilePacketHandler.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/ProjectilePacketHandler.java @@ -63,7 +63,7 @@ public class ProjectilePacketHandler implements EntityPacketHandler { public void convertAddCustomProjectilePacket(FriendlyByteBuf buf, ByteBufPacketEvent event) { UUID uuid = buf.readUUID(); - buf.readVarInt(); // type + buf.readVarInt(); // id double x = buf.readDouble(); double y = buf.readDouble(); double z = buf.readDouble(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/PayloadHelper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/PayloadHelper.java index 716ad2f0d..ba1b1804a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/PayloadHelper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/payload/PayloadHelper.java @@ -35,7 +35,7 @@ public class PayloadHelper { @SuppressWarnings("unchecked") NetworkCodec codec = (NetworkCodec) BuiltInRegistries.MOD_PACKET.getValue(data.type()); if (codec == null) { - CraftEngine.instance().logger().warn("Unknown data type class: " + data.getClass().getName()); + CraftEngine.instance().logger().warn("Unknown data id class: " + data.getClass().getName()); return; } FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer()); @@ -65,7 +65,7 @@ public class PayloadHelper { @SuppressWarnings("unchecked") NetworkCodec codec = (NetworkCodec) BuiltInRegistries.MOD_PACKET.getValue(type); if (codec == null) { - Debugger.COMMON.debug(() -> "Unknown data type received: " + type); + Debugger.COMMON.debug(() -> "Unknown data id received: " + type); return; } diff --git a/common-files/src/main/resources/resources/default/configuration/furniture/bench.yml b/common-files/src/main/resources/resources/default/configuration/furniture/bench.yml index be22a435c..06523d269 100644 --- a/common-files/src/main/resources/resources/default/configuration/furniture/bench.yml +++ b/common-files/src/main/resources/resources/default/configuration/furniture/bench.yml @@ -12,12 +12,9 @@ items: sounds: break: minecraft:block.bamboo_wood.break place: minecraft:block.bamboo_wood.place - placement: + variants: ground: loot-spawn-offset: 0.5,0.5,0 - rules: - rotation: FOUR - alignment: CENTER elements: - item: default:bench display-transform: NONE diff --git a/common-files/src/main/resources/translations/de.yml b/common-files/src/main/resources/translations/de.yml index 5ce8d8ef8..1d523d817 100644 --- a/common-files/src/main/resources/translations/de.yml +++ b/common-files/src/main/resources/translations/de.yml @@ -160,8 +160,8 @@ warning.config.sound.missing_name: "Problem in Datei gefunden - warning.config.jukebox_song.duplicate: "Problem in Datei gefunden - Doppelter Jukebox-Song ''. Bitte prüfe, ob dieselbe Konfiguration in anderen Dateien vorhanden ist." warning.config.jukebox_song.missing_sound: "Problem in Datei gefunden - Beim Jukebox-Song '' fehlt das erforderliche 'sound'-Argument." warning.config.furniture.duplicate: "Problem in Datei gefunden - Doppeltes Furniture ''. Bitte prüfe, ob dieselbe Konfiguration in anderen Dateien vorhanden ist." -warning.config.furniture.missing_placement: "Problem in Datei gefunden - Beim Furniture '' fehlt das erforderliche 'placement'-Argument." -warning.config.furniture.element.missing_item: "Problem in Datei gefunden - Beim Furniture '' fehlt das erforderliche 'item'-Argument für eines seiner Elemente." +warning.config.furniture.missing_variants: "Problem in Datei gefunden - Beim Furniture '' fehlt das erforderliche 'variants'-Argument." +warning.config.furniture.element.item_display.missing_item: "Problem in Datei gefunden - Beim Furniture '' fehlt das erforderliche 'item'-Argument für eines seiner Elemente." warning.config.furniture.settings.unknown: "Problem in Datei gefunden - Das Furniture '' verwendet einen unbekannten Einstellungs-Typ ''." warning.config.furniture.hitbox.invalid_type: "Problem in Datei gefunden - Das Furniture '' verwendet einen ungültigen Hitbox-Typ ''." warning.config.furniture.hitbox.custom.invalid_entity: "Problem in Datei gefunden - Das Furniture '' verwendet eine benutzerdefinierte Hitbox mit ungültigem Entity-Typ ''." diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index c7e538f21..013865146 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -190,8 +190,9 @@ warning.config.sound.missing_name: "Issue found in file - The so warning.config.jukebox_song.duplicate: "Issue found in file - Duplicated jukebox song ''. Please check if there is the same configuration in other files." warning.config.jukebox_song.missing_sound: "Issue found in file - The jukebox song '' is missing the required 'sound' argument." warning.config.furniture.duplicate: "Issue found in file - Duplicated furniture ''. Please check if there is the same configuration in other files." -warning.config.furniture.missing_placement: "Issue found in file - The furniture '' is missing the required 'placement' argument." -warning.config.furniture.element.missing_item: "Issue found in file - The furniture '' is missing the required 'item' argument for one of its elements." +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.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/es.yml b/common-files/src/main/resources/translations/es.yml index 0a262c0f3..c52e59568 100644 --- a/common-files/src/main/resources/translations/es.yml +++ b/common-files/src/main/resources/translations/es.yml @@ -111,8 +111,8 @@ warning.config.sound.missing_name: "Problema encontrado en el archivo Problema encontrado en el archivo - Canción de tocadiscos duplicada ''. Verifica si hay la misma configuración en otros archivos." warning.config.jukebox_song.missing_sound: "Problema encontrado en el archivo - La canción de tocadiscos '' carece del argumento requerido 'sound'." warning.config.furniture.duplicate: "Problema encontrado en el archivo - Mueble duplicado ''. Verifica si hay la misma configuración en otros archivos." -warning.config.furniture.missing_placement: "Problema encontrado en el archivo - El mueble '' carece del argumento requerido 'placement'." -warning.config.furniture.element.missing_item: "Problema encontrado en el archivo - El mueble '' carece del argumento requerido 'item' para uno de sus elementos." +warning.config.furniture.missing_variants: "Problema encontrado en el archivo - El mueble '' carece del argumento requerido 'variants'." +warning.config.furniture.element.item_display.missing_item: "Problema encontrado en el archivo - El mueble '' carece del argumento requerido 'item' para uno de sus elementos." warning.config.furniture.settings.unknown: "Problema encontrado en el archivo - El mueble '' está usando un tipo de configuración desconocido ''." warning.config.furniture.hitbox.invalid_type: "Problema encontrado en el archivo - El mueble '' está usando un tipo de hitbox inválido ''." warning.config.furniture.hitbox.custom.invalid_entity: "Problema encontrado en el archivo - El mueble '' está usando un hitbox personalizado con un tipo de entidad inválido ''." diff --git a/common-files/src/main/resources/translations/fr_fr.yml b/common-files/src/main/resources/translations/fr_fr.yml index 49bad7ee0..cf519f058 100644 --- a/common-files/src/main/resources/translations/fr_fr.yml +++ b/common-files/src/main/resources/translations/fr_fr.yml @@ -175,8 +175,8 @@ warning.config.sound.missing_name: "Problème trouvé dans le fichier Problème trouvé dans le fichier - Chanson de jukebox dupliquée ''. Vérifiez s’il existe la même configuration dans d’autres fichiers." warning.config.jukebox_song.missing_sound: "Problème trouvé dans le fichier - La chanson de jukebox '' manque l’argument obligatoire 'sound'." warning.config.furniture.duplicate: "Problème trouvé dans le fichier - Meuble dupliqué ''. Vérifiez s’il existe la même configuration dans d’autres fichiers." -warning.config.furniture.missing_placement: "Problème trouvé dans le fichier - Le meuble '' manque l’argument obligatoire 'placement'." -warning.config.furniture.element.missing_item: "Problème trouvé dans le fichier - Le meuble '' manque l’argument obligatoire 'item' pour un de ses éléments." +warning.config.furniture.missing_variants: "Problème trouvé dans le fichier - Le meuble '' manque l’argument obligatoire 'variants'." +warning.config.furniture.element.item_display.missing_item: "Problème trouvé dans le fichier - Le meuble '' manque l’argument obligatoire 'item' pour un de ses éléments." warning.config.furniture.settings.unknown: "Problème trouvé dans le fichier - Le meuble '' utilise un type de paramètre inconnu ''." warning.config.furniture.hitbox.invalid_type: "Problème trouvé dans le fichier - Le meuble '' utilise un type de hitbox invalide ''." warning.config.furniture.hitbox.custom.invalid_entity: "Problème trouvé dans le fichier - Le meuble '' utilise un hitbox personnalisé avec un type d’entité invalide ''." diff --git a/common-files/src/main/resources/translations/ru_ru.yml b/common-files/src/main/resources/translations/ru_ru.yml index af586317c..6e55efa40 100644 --- a/common-files/src/main/resources/translations/ru_ru.yml +++ b/common-files/src/main/resources/translations/ru_ru.yml @@ -148,8 +148,8 @@ warning.config.sound.missing_name: "Проблема найдена в warning.config.jukebox_song.duplicate: "Проблема найдена в файле - Дублированная песня музыкального автомата ''. Проверьте, есть ли такая же конфигурация в других файлах." warning.config.jukebox_song.missing_sound: "Проблема найдена в файле - В песне музыкального автомата '' отсутствует необходимый 'sound' аргумент." warning.config.furniture.duplicate: "Проблема найдена в файле - Дублированная мебель ''. Проверьте, есть ли такая же конфигурация в других файлах." -warning.config.furniture.missing_placement: "Проблема найдена в файле - В мебели '' отсутствует необходимый 'placement' аргумент." -warning.config.furniture.element.missing_item: "Проблема найдена в файле - В мебели '' отсутствует необходимый 'item' аргумент для одного из его элементов." +warning.config.furniture.missing_variants: "Проблема найдена в файле - В мебели '' отсутствует необходимый 'variants' аргумент." +warning.config.furniture.element.item_display.missing_item: "Проблема найдена в файле - В мебели '' отсутствует необходимый 'item' аргумент для одного из его элементов." warning.config.furniture.settings.unknown: "Проблема найдена в файле - Мебель '' использует неизвестный тип настройки ''." warning.config.furniture.hitbox.invalid_type: "Проблема найдена в файле - Мебель '' использует недопустимый тип хитбокса ''." warning.config.furniture.hitbox.custom.invalid_entity: "Проблема найдена в файле - Мебель '' использует пользовательский хитбокс с недопустимым типом сущности ''." diff --git a/common-files/src/main/resources/translations/tr.yml b/common-files/src/main/resources/translations/tr.yml index 94a56309f..f826f3cc7 100644 --- a/common-files/src/main/resources/translations/tr.yml +++ b/common-files/src/main/resources/translations/tr.yml @@ -110,8 +110,8 @@ warning.config.sound.missing_name: " dosyasında sorun bulundu - warning.config.jukebox_song.duplicate: " dosyasında sorun bulundu - Yinelenen müzik çalar şarkısı ''. Diğer dosyalarda aynı yapılandırmanın olup olmadığını kontrol edin." warning.config.jukebox_song.missing_sound: " dosyasında sorun bulundu - '' müzik çalar şarkısı gerekli 'sound' argümanı eksik." warning.config.furniture.duplicate: " dosyasında sorun bulundu - Yinelenen mobilya ''. Diğer dosyalarda aynı yapılandırmanın olup olmadığını kontrol edin." -warning.config.furniture.missing_placement: " dosyasında sorun bulundu - '' mobilyası gerekli 'placement' argümanı eksik." -warning.config.furniture.element.missing_item: " dosyasında sorun bulundu - '' mobilyası, elementlerinden biri için gerekli 'item' argümanı eksik." +warning.config.furniture.missing_variants: " dosyasında sorun bulundu - '' mobilyası gerekli 'variants' argümanı eksik." +warning.config.furniture.element.item_display.missing_item: " dosyasında sorun bulundu - '' mobilyası, elementlerinden biri için gerekli 'item' argümanı eksik." warning.config.furniture.settings.unknown: " dosyasında sorun bulundu - '' mobilyası bilinmeyen bir ayar türü '' kullanıyor." warning.config.furniture.hitbox.invalid_type: " dosyasında sorun bulundu - '' mobilyası geçersiz bir hitbox türü '' kullanıyor." warning.config.furniture.hitbox.custom.invalid_entity: " dosyasında sorun bulundu - '' mobilyası, geçersiz varlık türü '' olan özel bir hitbox kullanıyor." diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index da06eeff2..1bcf6cb8f 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -183,8 +183,8 @@ warning.config.sound.missing_name: "在文件 发现问题 - 音 warning.config.jukebox_song.duplicate: "在文件 发现问题 - 重复的唱片机歌曲 '' 请检查其他文件中是否存在相同配置" warning.config.jukebox_song.missing_sound: "在文件 发现问题 - 唱片机歌曲 '' 缺少必需的 'sound' 参数" warning.config.furniture.duplicate: "在文件 发现问题 - 重复的家具 '' 请检查其他文件中是否存在相同配置" -warning.config.furniture.missing_placement: "在文件 发现问题 - 家具 '' 缺少必需的 'placement' 参数" -warning.config.furniture.element.missing_item: "在文件 发现问题 - 家具 '' 的某个元素缺少必需的 'item' 参数" +warning.config.furniture.missing_variants: "在文件 发现问题 - 家具 '' 缺少必需的 'variants' 参数" +warning.config.furniture.element.item_display.missing_item: "在文件 发现问题 - 家具 '' 的 'item_display' 元素缺少必需的 'item' 参数" 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/AbstractBlockManager.java b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java index 5b0dbf02b..5707d7b2f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/AbstractBlockManager.java @@ -711,12 +711,8 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem } private CullingData parseCullingData(Object arguments) { - if (arguments instanceof Boolean b && !b) { - return null; - } - if (!(arguments instanceof Map)) { - return new CullingData(DEFAULT_BLOCK_ENTITY_AABB, Config.entityCullingViewDistance(), 0.5, true); - } + if (arguments instanceof Boolean b && !b) return null; + if (!(arguments instanceof Map)) return new CullingData(DEFAULT_BLOCK_ENTITY_AABB, Config.entityCullingViewDistance(), 0.5, true); Map argumentsMap = ResourceConfigUtils.getAsMap(arguments, "entity-culling"); return new CullingData( ResourceConfigUtils.getAsAABB(argumentsMap.getOrDefault("aabb", 1), "aabb"), diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java index 6d794219f..b32258402 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockBehavior.java @@ -78,7 +78,7 @@ public abstract class BlockBehavior { return (boolean) superMethod.call(); } - // 1.20-1.20.4 BlockState state, BlockGetter world, BlockPos pos, PathComputationType type + // 1.20-1.20.4 BlockState state, BlockGetter world, BlockPos pos, PathComputationType id // 1.20.5+ BlockState state, PathComputationType pathComputationType public boolean isPathFindable(Object thisBlock, Object[] args, Callable superMethod) throws Exception { return (boolean) superMethod.call(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java index e2e78a9a4..50a18c120 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockSettings.java @@ -41,6 +41,7 @@ public class BlockSettings { float friction = 0.6f; float speedFactor = 1f; float jumpFactor = 1f; + Map, Object> customData = new IdentityHashMap<>(4); private BlockSettings() {} @@ -107,9 +108,29 @@ public class BlockSettings { newSettings.speedFactor = settings.speedFactor; newSettings.jumpFactor = settings.jumpFactor; newSettings.friction = settings.friction; + newSettings.customData = new IdentityHashMap<>(settings.customData); return newSettings; } + @SuppressWarnings("unchecked") + public T getCustomData(CustomDataType type) { + return (T) this.customData.get(type); + } + + public void clearCustomData() { + this.customData.clear(); + } + + @Nullable + @SuppressWarnings("unchecked") + public T removeCustomData(CustomDataType type) { + return (T) this.customData.remove(type); + } + + public void addCustomData(CustomDataType key, T value) { + this.customData.put(key, value); + } + public Set tags() { return tags; } @@ -542,7 +563,7 @@ public class BlockSettings { })); } - private static void registerFactory(String id, Modifier.Factory factory) { + public static void registerFactory(String id, Modifier.Factory factory) { FACTORIES.put(id, factory); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/IsPathFindableBlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/IsPathFindableBlockBehavior.java index 7fe7d8e06..dca06a1bc 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/IsPathFindableBlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/IsPathFindableBlockBehavior.java @@ -4,7 +4,7 @@ import java.util.concurrent.Callable; public interface IsPathFindableBlockBehavior { - // 1.20-1.20.4 BlockState state, BlockGetter world, BlockPos pos, PathComputationType type + // 1.20-1.20.4 BlockState state, BlockGetter world, BlockPos pos, PathComputationType id // 1.20.5+ BlockState state, PathComputationType pathComputationType boolean isPathFindable(Object thisBlock, Object[] args, Callable superMethod) throws Exception; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntity.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntity.java index 78dc7210a..fffeaaa89 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntity.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntity.java @@ -24,7 +24,7 @@ public abstract class BlockEntity { this.type = type; } - public final CompoundTag saveAsTag() { + public CompoundTag saveAsTag() { CompoundTag tag = new CompoundTag(); this.saveId(tag); this.savePos(tag); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java index d7ca645e6..9c5f1d2e3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java @@ -5,6 +5,7 @@ import net.momirealms.craftengine.core.util.Key; public final class BlockEntityTypeKeys { private BlockEntityTypeKeys() {} + public static final Key INACTIVE = Key.of("craftengine:inactive"); public static final Key UNSAFE_COMPOSITE = Key.of("craftengine:unsafe_composite"); public static final Key SIMPLE_STORAGE = Key.of("craftengine:simple_storage"); public static final Key SIMPLE_PARTICLE = Key.of("craftengine:simple_particle"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypes.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypes.java index c4b725b06..46083cc4b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypes.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypes.java @@ -7,6 +7,7 @@ import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceKey; public abstract class BlockEntityTypes { + public static final BlockEntityType INACTIVE = register(BlockEntityTypeKeys.INACTIVE); public static BlockEntityType register(Key id) { BlockEntityType type = new BlockEntityType<>(id); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/InactiveBlockEntity.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/InactiveBlockEntity.java new file mode 100644 index 000000000..3aa928f83 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/InactiveBlockEntity.java @@ -0,0 +1,21 @@ +package net.momirealms.craftengine.core.block.entity; + +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.sparrow.nbt.CompoundTag; + +public class InactiveBlockEntity extends BlockEntity { + private final CompoundTag tag; + + public InactiveBlockEntity(BlockPos pos, + ImmutableBlockState blockState, + CompoundTag tag) { + super(BlockEntityTypes.INACTIVE, pos, blockState); + this.tag = tag; + } + + @Override + public CompoundTag saveAsTag() { + return this.tag; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntity.java b/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntity.java new file mode 100644 index 000000000..2ea1439a4 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntity.java @@ -0,0 +1,96 @@ +package net.momirealms.craftengine.core.entity; + +import net.momirealms.craftengine.core.world.CEWorld; +import net.momirealms.craftengine.core.world.Cullable; +import net.momirealms.craftengine.core.world.WorldPosition; +import net.momirealms.sparrow.nbt.CompoundTag; + +import java.util.UUID; + +public abstract class CustomEntity implements Cullable { + protected final CustomEntityType type; + protected final UUID uuid; + protected WorldPosition position; + protected boolean valid = true; + + protected CustomEntity(CustomEntityType type, WorldPosition position, UUID uuid) { + this.position = position; + this.type = type; + this.uuid = uuid; + } + + public CompoundTag saveAsTag() { + CompoundTag tag = new CompoundTag(); + this.saveId(tag); + this.savePos(tag); + this.saveCustomData(tag); + return tag; + } + + private void savePos(CompoundTag tag) { + tag.putDouble("x", this.position.x()); + tag.putDouble("y", this.position.y()); + tag.putDouble("z", this.position.z()); + tag.putFloat("x_rot", this.position.xRot()); + tag.putFloat("y_rot", this.position.yRot()); + } + + public boolean isValid() { + return this.valid; + } + + public UUID uuid() { + return uuid; + } + + public double x() { + return this.position.x(); + } + + public double y() { + return this.position.y(); + } + + public double z() { + return this.position.z(); + } + + public float yRot() { + return this.position.yRot(); + } + + public float xRot() { + return this.position.xRot(); + } + + public CustomEntityType entityType() { + return this.type; + } + + protected void saveCustomData(CompoundTag tag) { + } + + public void loadCustomData(CompoundTag tag) { + } + + private void saveId(CompoundTag tag) { + tag.putString("id", this.type.id().asString()); + } + + public void destroy() { + this.valid = false; + } + + public static UUID readUUID(CompoundTag tag) { + return tag.getUUID("uuid"); + } + + public static WorldPosition readPos(CEWorld world, CompoundTag tag) { + double x = tag.getDouble("x"); + double y = tag.getDouble("y"); + double z = tag.getDouble("z"); + float xRot = tag.getFloat("x_rot"); + float yRot = tag.getFloat("y_rot"); + return new WorldPosition(world.world, x, y, z, xRot, yRot); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntityType.java b/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntityType.java new file mode 100644 index 000000000..a7cd7cb33 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntityType.java @@ -0,0 +1,14 @@ +package net.momirealms.craftengine.core.entity; + +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.world.WorldPosition; + +import java.util.UUID; + +public record CustomEntityType(Key id, Factory factory) { + + public interface Factory { + + T create(UUID uuid, WorldPosition position); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntityTypeKeys.java b/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntityTypeKeys.java new file mode 100644 index 000000000..57e36fadc --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntityTypeKeys.java @@ -0,0 +1,10 @@ +package net.momirealms.craftengine.core.entity; + +import net.momirealms.craftengine.core.util.Key; + +public final class CustomEntityTypeKeys { + private CustomEntityTypeKeys() {} + + public static final Key FURNITURE = Key.of("craftengine:furniture"); + public static final Key INACTIVE = Key.of("craftengine:inactive"); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntityTypes.java b/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntityTypes.java new file mode 100644 index 000000000..c5697d9c2 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/CustomEntityTypes.java @@ -0,0 +1,18 @@ +package net.momirealms.craftengine.core.entity; + +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.registry.Registries; +import net.momirealms.craftengine.core.registry.WritableRegistry; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceKey; + +public class CustomEntityTypes { + public static final CustomEntityType INACTIVE = register(CustomEntityTypeKeys.INACTIVE, InactiveCustomEntity::new); + + public static CustomEntityType register(Key id, CustomEntityType.Factory factory) { + CustomEntityType type = new CustomEntityType<>(id, factory); + ((WritableRegistry>) BuiltInRegistries.ENTITY_TYPE) + .register(ResourceKey.create(Registries.ENTITY_TYPE.location(), id), type); + return type; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/InactiveCustomEntity.java b/core/src/main/java/net/momirealms/craftengine/core/entity/InactiveCustomEntity.java new file mode 100644 index 000000000..1c870110a --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/InactiveCustomEntity.java @@ -0,0 +1,54 @@ +package net.momirealms.craftengine.core.entity; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.entityculling.CullingData; +import net.momirealms.craftengine.core.world.WorldPosition; +import net.momirealms.sparrow.nbt.CompoundTag; +import net.momirealms.sparrow.nbt.NBT; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.UUID; + +public class InactiveCustomEntity extends CustomEntity { + public static final CompoundTag INVALID_TAG = new CompoundTag(Map.of("type", NBT.createString(CustomEntityTypes.INACTIVE.id().asMinimalString()))); + private final CompoundTag data; + + public InactiveCustomEntity(UUID uuid, WorldPosition position) { + super(CustomEntityTypes.INACTIVE, position, uuid); + this.data = INVALID_TAG; + } + + public InactiveCustomEntity(UUID uuid, WorldPosition position, CompoundTag data) { + super(CustomEntityTypes.INACTIVE, position, uuid); + this.data = data; + } + + @Override + public CompoundTag saveAsTag() { + return this.data; + } + + @Override + public boolean isValid() { + // 不正常的数据不要存储 + return this.data != INVALID_TAG; + } + + @Override + public void destroy() { + } + + @Override + public void show(Player player) { + } + + @Override + public void hide(Player player) { + } + + @Override + public @Nullable CullingData cullingData() { + return null; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/Billboard.java b/core/src/main/java/net/momirealms/craftengine/core/entity/display/Billboard.java similarity index 80% rename from core/src/main/java/net/momirealms/craftengine/core/entity/Billboard.java rename to core/src/main/java/net/momirealms/craftengine/core/entity/display/Billboard.java index 7533b658b..a415a8e35 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/Billboard.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/display/Billboard.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.entity; +package net.momirealms.craftengine.core.entity.display; public enum Billboard { FIXED(0), diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/ItemDisplayContext.java b/core/src/main/java/net/momirealms/craftengine/core/entity/display/ItemDisplayContext.java similarity index 87% rename from core/src/main/java/net/momirealms/craftengine/core/entity/ItemDisplayContext.java rename to core/src/main/java/net/momirealms/craftengine/core/entity/display/ItemDisplayContext.java index 239488019..fdbe09050 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/ItemDisplayContext.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/display/ItemDisplayContext.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.entity; +package net.momirealms.craftengine.core.entity.display; public enum ItemDisplayContext { NONE(0), diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractCustomFurniture.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractCustomFurniture.java deleted file mode 100644 index 3f4d4bae4..000000000 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractCustomFurniture.java +++ /dev/null @@ -1,89 +0,0 @@ -package net.momirealms.craftengine.core.entity.furniture; - -import net.momirealms.craftengine.core.loot.LootTable; -import net.momirealms.craftengine.core.plugin.context.Context; -import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; -import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.util.Key; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -public abstract class AbstractCustomFurniture implements CustomFurniture { - private final Key id; - private final FurnitureSettings settings; - private final Map placements; - private final Map>> events; - @Nullable - private final LootTable lootTable; - - private final AnchorType anyType; - - protected AbstractCustomFurniture(@NotNull Key id, - @NotNull FurnitureSettings settings, - @NotNull Map placements, - @NotNull Map>> events, - @Nullable LootTable lootTable) { - this.id = id; - this.settings = settings; - this.placements = placements; - this.lootTable = lootTable; - this.events = events; - this.anyType = placements.keySet().stream().findFirst().orElse(null); - } - - @Override - public void execute(Context context, EventTrigger trigger) { - for (Function function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) { - function.run(context); - } - } - - @Override - public Key id() { - return this.id; - } - - @Override - public Map placements() { - return this.placements; - } - - @Override - public FurnitureSettings settings() { - return this.settings; - } - - @Override - public @Nullable LootTable lootTable() { - return this.lootTable; - } - - @Override - public AnchorType getAnyAnchorType() { - return this.anyType; - } - - @Override - public boolean isAllowedPlacement(AnchorType anchorType) { - return this.placements.containsKey(anchorType); - } - - @Override - public Placement getPlacement(AnchorType anchorType) { - return this.placements.get(anchorType); - } - - @Override - public Placement getValidPlacement(AnchorType anchorType) { - Placement placement = this.placements.get(anchorType); - if (placement == null) { - return this.placements.get(getAnyAnchorType()); - } - return placement; - } -} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureElement.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureElement.java deleted file mode 100644 index 9e470cb6d..000000000 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureElement.java +++ /dev/null @@ -1,92 +0,0 @@ -package net.momirealms.craftengine.core.entity.furniture; - -import net.momirealms.craftengine.core.entity.Billboard; -import net.momirealms.craftengine.core.entity.ItemDisplayContext; -import net.momirealms.craftengine.core.util.Key; -import org.joml.Quaternionf; -import org.joml.Vector3f; - -public abstract class AbstractFurnitureElement implements FurnitureElement { - private final Key item; - private final Billboard billboard; - private final ItemDisplayContext transform; - private final Vector3f scale; - private final Vector3f translation; - private final Vector3f position; - private final Quaternionf rotation; - private final boolean applyDyedColor; - private final float shadowRadius; - private final float shadowStrength; - - public AbstractFurnitureElement(Key item, - Billboard billboard, - ItemDisplayContext transform, - Vector3f scale, - Vector3f translation, - Vector3f position, - Quaternionf rotation, - float shadowRadius, - float shadowStrength, - boolean applyDyedColor) { - this.billboard = billboard; - this.transform = transform; - this.scale = scale; - this.translation = translation; - this.item = item; - this.rotation = rotation; - this.position = position; - this.applyDyedColor = applyDyedColor; - this.shadowRadius = shadowRadius; - this.shadowStrength = shadowStrength; - } - - @Override - public float shadowRadius() { - return shadowRadius; - } - - @Override - public float shadowStrength() { - return shadowStrength; - } - - @Override - public boolean applyDyedColor() { - return applyDyedColor; - } - - @Override - public Quaternionf rotation() { - return rotation; - } - - @Override - public Key item() { - return item; - } - - @Override - public Billboard billboard() { - return billboard; - } - - @Override - public ItemDisplayContext transform() { - return transform; - } - - @Override - public Vector3f scale() { - return scale; - } - - @Override - public Vector3f translation() { - return translation; - } - - @Override - public Vector3f position() { - return position; - } -} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java index 52ea8252d..dd67036f8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractFurnitureManager.java @@ -1,19 +1,24 @@ package net.momirealms.craftengine.core.entity.furniture; -import net.momirealms.craftengine.core.entity.Billboard; -import net.momirealms.craftengine.core.entity.ItemDisplayContext; +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig; +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigs; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfig; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxTypes; import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.pack.LoadingSequence; import net.momirealms.craftengine.core.pack.Pack; import net.momirealms.craftengine.core.pack.PendingConfigSection; import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.config.IdSectionConfigParser; import net.momirealms.craftengine.core.plugin.context.event.EventFunctions; +import net.momirealms.craftengine.core.plugin.entityculling.CullingData; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.util.GsonHelper; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.collision.AABB; import org.incendo.cloud.suggestion.Suggestion; import org.joml.Vector3f; @@ -21,7 +26,7 @@ import java.nio.file.Path; import java.util.*; public abstract class AbstractFurnitureManager implements FurnitureManager { - protected final Map byId = new HashMap<>(); + protected final Map byId = new HashMap<>(); private final CraftEngine plugin; private final FurnitureParser furnitureParser; // Cached command suggestions @@ -56,12 +61,12 @@ public abstract class AbstractFurnitureManager implements FurnitureManager { } @Override - public Optional furnitureById(Key id) { + public Optional furnitureById(Key id) { return Optional.ofNullable(this.byId.get(id)); } @Override - public Map loadedFurniture() { + public Map loadedFurniture() { return Collections.unmodifiableMap(this.byId); } @@ -72,10 +77,6 @@ public abstract class AbstractFurnitureManager implements FurnitureManager { protected abstract HitBoxConfig defaultHitBox(); - protected abstract FurnitureElement.Builder furnitureElementBuilder(); - - protected abstract CustomFurniture.Builder furnitureBuilder(); - public class FurnitureParser extends IdSectionConfigParser { public static final String[] CONFIG_SECTION_NAME = new String[] { "furniture" }; private final List pendingConfigSections = new ArrayList<>(); @@ -107,91 +108,72 @@ public abstract class AbstractFurnitureManager implements FurnitureManager { return LoadingSequence.FURNITURE; } - @SuppressWarnings("unchecked") @Override public void parseSection(Pack pack, Path path, String node, Key id, Map section) { if (AbstractFurnitureManager.this.byId.containsKey(id)) { throw new LocalizedResourceConfigException("warning.config.furniture.duplicate"); } - EnumMap placements = new EnumMap<>(AnchorType.class); - Object placementObj = section.get("placement"); - Map placementMap = MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(placementObj, "warning.config.furniture.missing_placement"), false); - if (placementMap.isEmpty()) { - throw new LocalizedResourceConfigException("warning.config.furniture.missing_placement"); - } - for (Map.Entry entry : placementMap.entrySet()) { - // anchor type - AnchorType anchorType = AnchorType.valueOf(entry.getKey().toUpperCase(Locale.ENGLISH)); - Map placementArguments = MiscUtils.castToMap(entry.getValue(), false); - Optional optionalLootSpawnOffset = Optional.ofNullable(placementArguments.get("loot-spawn-offset")).map(it -> ResourceConfigUtils.getAsVector3f(it, "loot-spawn-offset")); - // furniture display elements - List elements = new ArrayList<>(); - List> elementConfigs = (List>) placementArguments.getOrDefault("elements", List.of()); - for (Map element : elementConfigs) { - FurnitureElement furnitureElement = furnitureElementBuilder() - .item(Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(element.get("item"), "warning.config.furniture.element.missing_item"))) - .applyDyedColor(ResourceConfigUtils.getAsBoolean(element.getOrDefault("apply-dyed-color", true), "apply-dyed-color")) - .billboard(ResourceConfigUtils.getOrDefault(element.get("billboard"), o -> Billboard.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), Billboard.FIXED)) - .transform(ResourceConfigUtils.getOrDefault(ResourceConfigUtils.get(element, "transform", "display-transform"), o -> ItemDisplayContext.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), ItemDisplayContext.NONE)) - .scale(ResourceConfigUtils.getAsVector3f(element.getOrDefault("scale", "1"), "scale")) - .position(ResourceConfigUtils.getAsVector3f(element.getOrDefault("position", "0"), "position")) - .translation(ResourceConfigUtils.getAsVector3f(element.getOrDefault("translation", "0"), "translation")) - .rotation(ResourceConfigUtils.getAsQuaternionf(element.getOrDefault("rotation", "0"), "rotation")) - .shadowRadius(ResourceConfigUtils.getAsFloat(element.getOrDefault("shadow-radius", 0f), "shadow-radius")) - .shadowStrength(ResourceConfigUtils.getAsFloat(element.getOrDefault("shadow-strength", 1f), "shadow-strength")) - .build(); - elements.add(furnitureElement); - } - // external model providers + Map variantsMap = ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(ResourceConfigUtils.get(section, "variants", "placement", "variant"), "warning.config.furniture.missing_variants"), "variants"); + if (variantsMap.isEmpty()) { + throw new LocalizedResourceConfigException("warning.config.furniture.missing_variants"); + } + + Map variants = new HashMap<>(); + for (Map.Entry e0 : variantsMap.entrySet()) { + String variantName = e0.getKey(); + Map variantArguments = ResourceConfigUtils.getAsMap(e0.getValue(), variantName); + Optional optionalLootSpawnOffset = Optional.ofNullable(variantArguments.get("loot-spawn-offset")).map(it -> ResourceConfigUtils.getAsVector3f(it, "loot-spawn-offset")); + List> elements = ResourceConfigUtils.parseConfigAsList(variantArguments.get("elements"), FurnitureElementConfigs::fromMap); + + // fixme 外部模型不应该在这 Optional externalModel; - if (placementArguments.containsKey("model-engine")) { - externalModel = Optional.of(plugin.compatibilityManager().createModel("ModelEngine", placementArguments.get("model-engine").toString())); - } else if (placementArguments.containsKey("better-model")) { - externalModel = Optional.of(plugin.compatibilityManager().createModel("BetterModel", placementArguments.get("better-model").toString())); + if (variantArguments.containsKey("model-engine")) { + externalModel = Optional.of(plugin.compatibilityManager().createModel("ModelEngine", variantArguments.get("model-engine").toString())); + } else if (variantArguments.containsKey("better-model")) { + externalModel = Optional.of(plugin.compatibilityManager().createModel("BetterModel", variantArguments.get("better-model").toString())); } else { externalModel = Optional.empty(); } - // add hitboxes - List hitboxes = ResourceConfigUtils.parseConfigAsList(placementArguments.get("hitboxes"), HitBoxTypes::fromMap); + List hitboxes = ResourceConfigUtils.parseConfigAsList(variantArguments.get("hitboxes"), HitBoxTypes::fromMap); if (hitboxes.isEmpty() && externalModel.isEmpty()) { hitboxes = List.of(defaultHitBox()); } - // rules - Map ruleSection = MiscUtils.castToMap(placementArguments.get("rules"), true); - if (ruleSection != null) { - placements.put(anchorType, new CustomFurniture.Placement( - anchorType, - elements.toArray(new FurnitureElement[0]), - hitboxes.toArray(new HitBoxConfig[0]), - ResourceConfigUtils.getOrDefault(ruleSection.get("rotation"), o -> RotationRule.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), RotationRule.ANY), - ResourceConfigUtils.getOrDefault(ruleSection.get("alignment"), o -> AlignmentRule.valueOf(o.toString().toUpperCase(Locale.ENGLISH)), AlignmentRule.CENTER), - externalModel, - optionalLootSpawnOffset - )); - } else { - placements.put(anchorType, new CustomFurniture.Placement( - anchorType, - elements.toArray(new FurnitureElement[0]), - hitboxes.toArray(new HitBoxConfig[0]), - RotationRule.ANY, - AlignmentRule.CENTER, - externalModel, - optionalLootSpawnOffset - )); - } + variants.put(variantName, new FurnitureVariant( + elements.toArray(new FurnitureElementConfig[0]), + hitboxes.toArray(new HitBoxConfig[0]), + externalModel, + optionalLootSpawnOffset + )); } - CustomFurniture furniture = furnitureBuilder() + AABB maxAABB = null; + + FurnitureConfig furniture = FurnitureConfig.builder() .id(id) .settings(FurnitureSettings.fromMap(MiscUtils.castToMap(section.get("settings"), true))) - .placement(placements) + .variants(variants) .events(EventFunctions.parseEvents(ResourceConfigUtils.get(section, "events", "event"))) .lootTable(LootTable.fromMap(MiscUtils.castToMap(section.get("loot"), true))) + .cullingData(parseCullingData(section.get("entity-culling"), maxAABB)) .build(); AbstractFurnitureManager.this.byId.put(id, furniture); } + + private CullingData parseCullingData(Object arguments, AABB maxHitbox) { + if (arguments instanceof Boolean b && !b) + return null; + if (!(arguments instanceof Map)) + return new CullingData(maxHitbox, Config.entityCullingViewDistance(), 0.5, true); + Map argumentsMap = ResourceConfigUtils.getAsMap(arguments, "entity-culling"); + return new CullingData( + ResourceConfigUtils.getAsAABB(argumentsMap.getOrDefault("aabb", maxHitbox), "aabb"), + ResourceConfigUtils.getAsInt(argumentsMap.getOrDefault("view-distance", Config.entityCullingViewDistance()), "view-distance"), + ResourceConfigUtils.getAsDouble(argumentsMap.getOrDefault("aabb-expansion", 0.5), "aabb-expansion"), + ResourceConfigUtils.getAsBoolean(argumentsMap.getOrDefault("ray-tracing", true), "ray-tracing") + ); + } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AnchorType.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AnchorType.java index d3a099b6f..cefebe26b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AnchorType.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AnchorType.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.core.entity.furniture; +@Deprecated(since = "0.0.66", forRemoval = true) public enum AnchorType { GROUND(0), WALL(1), diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java deleted file mode 100644 index 19afdf32f..000000000 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/CustomFurniture.java +++ /dev/null @@ -1,60 +0,0 @@ -package net.momirealms.craftengine.core.entity.furniture; - -import net.momirealms.craftengine.core.loot.LootTable; -import net.momirealms.craftengine.core.plugin.context.Context; -import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; -import net.momirealms.craftengine.core.plugin.context.function.Function; -import net.momirealms.craftengine.core.util.Key; -import org.jetbrains.annotations.Nullable; -import org.joml.Vector3f; - -import java.util.List; -import java.util.Map; -import java.util.Optional; - -// TODO 家具的设计存在问题。家具也应该存在不同的状态,而不是根据放置规则直接决定状态类型 -public interface CustomFurniture { - - void execute(Context context, EventTrigger trigger); - - Key id(); - - Map placements(); - - FurnitureSettings settings(); - - @Nullable - LootTable lootTable(); - - AnchorType getAnyAnchorType(); - - boolean isAllowedPlacement(AnchorType anchorType); - - Placement getPlacement(AnchorType anchorType); - - Placement getValidPlacement(AnchorType anchorType); - - interface Builder { - - Builder id(Key id); - - Builder placement(Map placements); - - Builder settings(FurnitureSettings settings); - - Builder lootTable(LootTable lootTable); - - Builder events(Map>> events); - - CustomFurniture build(); - } - - record Placement(AnchorType anchorType, - FurnitureElement[] elements, - HitBoxConfig[] hitBoxConfigs, - RotationRule rotationRule, - AlignmentRule alignmentRule, - Optional externalModel, - Optional dropOffset) { - } -} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java index e5a2bcd59..1b4661ba1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/Furniture.java @@ -1,48 +1,28 @@ package net.momirealms.craftengine.core.entity.furniture; -import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.entity.CustomEntity; +import net.momirealms.craftengine.core.entity.CustomEntityType; import net.momirealms.craftengine.core.world.WorldPosition; +import net.momirealms.sparrow.nbt.CompoundTag; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.util.UUID; +public abstract class Furniture extends CustomEntity { + protected final FurnitureConfig config; + protected final FurnitureDataAccessor dataAccessor; -public interface Furniture { - void initializeColliders(); - - WorldPosition position(); - - boolean isValid(); - - void destroy(); - - void destroyColliders(); - - void destroySeats(); - - UUID uuid(); - - int baseEntityId(); - - @Nullable - HitBox hitBoxByEntityId(int id); - - @Nullable HitBoxPart hitBoxPartByEntityId(int id); + public Furniture(CustomEntityType type, WorldPosition position, FurnitureConfig config, CompoundTag data) { + super(type, position); + this.dataAccessor = new FurnitureDataAccessor(data); + this.config = config; + } @NotNull - AnchorType anchorType(); + public FurnitureConfig config() { + return this.config; + } @NotNull - Key id(); - - @NotNull - CustomFurniture config(); - - boolean hasExternalModel(); - - FurnitureExtraData extraData(); - - void setExtraData(FurnitureExtraData extraData); - - void save(); + public FurnitureDataAccessor dataAccessor() { + return this.dataAccessor; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfig.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfig.java new file mode 100644 index 000000000..c6f075e60 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfig.java @@ -0,0 +1,67 @@ +package net.momirealms.craftengine.core.entity.furniture; + +import net.momirealms.craftengine.core.entity.furniture.behavior.FurnitureBehavior; +import net.momirealms.craftengine.core.loot.LootTable; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.function.Function; +import net.momirealms.craftengine.core.plugin.entityculling.CullingData; +import net.momirealms.craftengine.core.util.Key; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; + +public interface FurnitureConfig { + + void execute(Context context, EventTrigger trigger); + + Key id(); + + FurnitureSettings settings(); + + @Nullable + LootTable lootTable(); + + Map variants(); + + default FurnitureVariant anyVariant() { + return variants().values().stream().findFirst().get(); + } + + default String anyVariantName() { + return variants().keySet().stream().findFirst().get(); + } + + @Nullable + FurnitureVariant getVariant(String variantName); + + @NotNull + FurnitureBehavior behavior(); + + CullingData cullingData(); + + static Builder builder() { + return new FurnitureConfigImpl.BuilderImpl(); + } + + interface Builder { + + Builder id(Key id); + + Builder variants(Map variants); + + Builder settings(FurnitureSettings settings); + + Builder lootTable(LootTable lootTable); + + Builder events(Map>> events); + + Builder behavior(FurnitureBehavior behavior); + + Builder cullingData(CullingData cullingData); + + FurnitureConfig build(); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfigImpl.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfigImpl.java new file mode 100644 index 000000000..8d6fe94b8 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureConfigImpl.java @@ -0,0 +1,145 @@ +package net.momirealms.craftengine.core.entity.furniture; + +import com.google.common.collect.ImmutableMap; +import net.momirealms.craftengine.core.entity.furniture.behavior.EmptyFurnitureBehavior; +import net.momirealms.craftengine.core.entity.furniture.behavior.FurnitureBehavior; +import net.momirealms.craftengine.core.loot.LootTable; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.event.EventTrigger; +import net.momirealms.craftengine.core.plugin.context.function.Function; +import net.momirealms.craftengine.core.plugin.entityculling.CullingData; +import net.momirealms.craftengine.core.util.Key; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +class FurnitureConfigImpl implements FurnitureConfig { + private final Key id; + private final FurnitureSettings settings; + private final Map variants; + private final Map>> events; + private final FurnitureBehavior behavior; + private final CullingData cullingData; + @Nullable + private final LootTable lootTable; + + private FurnitureConfigImpl(@NotNull Key id, + @NotNull FurnitureSettings settings, + @NotNull Map variants, + @NotNull Map>> events, + @NotNull FurnitureBehavior behavior, + @Nullable CullingData cullingData, + @Nullable LootTable lootTable) { + this.id = id; + this.settings = settings; + this.variants = ImmutableMap.copyOf(variants); + this.lootTable = lootTable; + this.behavior = behavior; + this.cullingData = cullingData; + this.events = events; + } + + @Override + public void execute(Context context, EventTrigger trigger) { + for (Function function : Optional.ofNullable(this.events.get(trigger)).orElse(Collections.emptyList())) { + function.run(context); + } + } + + @Override + public Key id() { + return this.id; + } + + @Override + public FurnitureSettings settings() { + return this.settings; + } + + @Override + public @Nullable LootTable lootTable() { + return this.lootTable; + } + + @Override + public Map variants() { + return this.variants; + } + + @Override + public @NotNull FurnitureBehavior behavior() { + return this.behavior; + } + + @Override + public CullingData cullingData() { + return this.cullingData; + } + + @Nullable + @Override + public FurnitureVariant getVariant(String variantName) { + return this.variants.get(variantName); + } + + public static class BuilderImpl implements Builder { + private Key id; + private Map variants; + private FurnitureSettings settings; + private Map>> events; + private LootTable lootTable; + private FurnitureBehavior behavior = EmptyFurnitureBehavior.INSTANCE; + private CullingData cullingData; + + @Override + public FurnitureConfig build() { + return new FurnitureConfigImpl(this.id, this.settings, this.variants, this.events, this.behavior, this.cullingData, this.lootTable); + } + + @Override + public Builder id(Key id) { + this.id = id; + return this; + } + + @Override + public Builder variants(Map variants) { + this.variants = variants; + return this; + } + + @Override + public Builder settings(FurnitureSettings settings) { + this.settings = settings; + return this; + } + + @Override + public Builder lootTable(LootTable lootTable) { + this.lootTable = lootTable; + return this; + } + + @Override + public Builder events(Map>> events) { + this.events = events; + return this; + } + + @Override + public Builder cullingData(CullingData cullingData) { + this.cullingData = cullingData; + return this; + } + + @Override + public Builder behavior(FurnitureBehavior behavior) { + this.behavior = behavior; + return this; + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureExtraData.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureDataAccessor.java similarity index 57% rename from core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureExtraData.java rename to core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureDataAccessor.java index 72587f2a1..07a6ccbb5 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureExtraData.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureDataAccessor.java @@ -6,34 +6,53 @@ import net.momirealms.craftengine.core.plugin.logger.Debugger; import net.momirealms.craftengine.core.util.Color; import net.momirealms.sparrow.nbt.CompoundTag; import net.momirealms.sparrow.nbt.NBT; +import net.momirealms.sparrow.nbt.Tag; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; import java.io.IOException; import java.util.Optional; -public class FurnitureExtraData { +public class FurnitureDataAccessor { public static final String ITEM = "item"; public static final String DYED_COLOR = "dyed_color"; public static final String FIREWORK_EXPLOSION_COLORS = "firework_explosion_colors"; + public static final String VARIANT = "variant"; + @ApiStatus.Obsolete public static final String ANCHOR_TYPE = "anchor_type"; private final CompoundTag data; - public FurnitureExtraData(CompoundTag data) { + public FurnitureDataAccessor(CompoundTag data) { this.data = data; } - public static FurnitureExtraData of(CompoundTag data) { - return new FurnitureExtraData(data); + public static FurnitureDataAccessor of(CompoundTag data) { + return new FurnitureDataAccessor(data); } public CompoundTag copyTag() { return this.data.copy(); } + @ApiStatus.Internal public CompoundTag unsafeTag() { return this.data; } + public void addCustomData(String key, Tag value) { + this.data.put(key, value); + } + + @Nullable + public Tag getCustomData(String key) { + return this.data.get(key); + } + + public void removeCustomData(String key) { + this.data.remove(key); + } + public Optional> item() { byte[] data = this.data.getByteArray(ITEM); if (data == null) return Optional.empty(); @@ -45,73 +64,57 @@ public class FurnitureExtraData { } } + public void setItem(Item item) { + this.data.putByteArray(ITEM, item.toByteArray()); + } + public Optional fireworkExplosionColors() { if (this.data.containsKey(FIREWORK_EXPLOSION_COLORS)) return Optional.of(this.data.getIntArray(FIREWORK_EXPLOSION_COLORS)); return Optional.empty(); } + public void setFireworkExplosionColors(int[] colors) { + this.data.putIntArray(FIREWORK_EXPLOSION_COLORS, colors); + } + public Optional dyedColor() { if (this.data.containsKey(DYED_COLOR)) return Optional.of(Color.fromDecimal(this.data.getInt(DYED_COLOR))); return Optional.empty(); } + public void setDyedColor(Color color) { + this.data.putInt(DYED_COLOR, color.color()); + } + + public Optional variant() { + return Optional.ofNullable(this.data.getString(VARIANT)); + } + + public void setVariant(String variant) { + this.data.putString(VARIANT, variant); + } + + @ApiStatus.Obsolete public Optional anchorType() { if (this.data.containsKey(ANCHOR_TYPE)) return Optional.of(AnchorType.byId(this.data.getInt(ANCHOR_TYPE))); return Optional.empty(); } - public FurnitureExtraData anchorType(AnchorType type) { + @ApiStatus.Obsolete + public FurnitureDataAccessor anchorType(AnchorType type) { this.data.putInt(ANCHOR_TYPE, type.getId()); return this; } - public static Builder builder() { - return new Builder(); + public static FurnitureDataAccessor fromBytes(final byte[] data) throws IOException { + return new FurnitureDataAccessor(NBT.fromBytes(data)); } - public static FurnitureExtraData fromBytes(final byte[] data) throws IOException { - return new FurnitureExtraData(NBT.fromBytes(data)); - } - - public static byte[] toBytes(final FurnitureExtraData data) throws IOException { + public static byte[] toBytes(final FurnitureDataAccessor data) throws IOException { return NBT.toBytes(data.data); } public byte[] toBytes() throws IOException { return toBytes(this); } - - public static class Builder { - private final CompoundTag data; - - public Builder() { - this.data = new CompoundTag(); - } - - public Builder item(Item item) { - this.data.putByteArray(ITEM, item.toByteArray()); - return this; - } - - public Builder dyedColor(Color color) { - if (color == null) return this; - this.data.putInt(DYED_COLOR, color.color()); - return this; - } - - public Builder fireworkExplosionColors(int[] colors) { - if (colors == null) return this; - this.data.putIntArray(FIREWORK_EXPLOSION_COLORS, colors); - return this; - } - - public Builder anchorType(AnchorType type) { - this.data.putInt(ANCHOR_TYPE, type.getId()); - return this; - } - - public FurnitureExtraData build() { - return new FurnitureExtraData(data); - } - } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureElement.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureElement.java deleted file mode 100644 index 785b24c68..000000000 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureElement.java +++ /dev/null @@ -1,59 +0,0 @@ -package net.momirealms.craftengine.core.entity.furniture; - -import net.momirealms.craftengine.core.entity.Billboard; -import net.momirealms.craftengine.core.entity.ItemDisplayContext; -import net.momirealms.craftengine.core.util.Key; -import org.jetbrains.annotations.NotNull; -import org.joml.Quaternionf; -import org.joml.Vector3f; - -import java.util.function.Consumer; - -public interface FurnitureElement { - Quaternionf rotation(); - - Key item(); - - Billboard billboard(); - - ItemDisplayContext transform(); - - float shadowRadius(); - - float shadowStrength(); - - boolean applyDyedColor(); - - Vector3f scale(); - - Vector3f translation(); - - Vector3f position(); - - void initPackets(Furniture furniture, int entityId, @NotNull Quaternionf conjugated, Consumer packets); - - interface Builder { - - Builder item(Key item); - - Builder billboard(Billboard billboard); - - Builder transform(ItemDisplayContext transform); - - Builder scale(Vector3f scale); - - Builder translation(Vector3f translation); - - Builder position(Vector3f position); - - Builder rotation(Quaternionf rotation); - - Builder applyDyedColor(boolean applyDyedColor); - - Builder shadowStrength(float shadowStrength); - - Builder shadowRadius(float shadowRadius); - - FurnitureElement build(); - } -} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java index e57baec7d..5f8ca181a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java @@ -25,11 +25,11 @@ public interface FurnitureManager extends Manageable { Collection cachedSuggestions(); - Furniture place(WorldPosition position, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound); + Furniture place(WorldPosition position, FurnitureConfig furniture, FurnitureDataAccessor extraData, boolean playSound); - Optional furnitureById(Key id); + Optional furnitureById(Key id); - Map loadedFurniture(); + Map loadedFurniture(); boolean isFurnitureRealEntity(int entityId); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureSettings.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureSettings.java index 298dbc877..f6bf10314 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureSettings.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureSettings.java @@ -1,11 +1,13 @@ package net.momirealms.craftengine.core.entity.furniture; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; +import net.momirealms.craftengine.core.util.CustomDataType; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import org.jetbrains.annotations.Nullable; import java.util.HashMap; +import java.util.IdentityHashMap; import java.util.Map; public class FurnitureSettings { @@ -13,6 +15,7 @@ public class FurnitureSettings { FurnitureSounds sounds = FurnitureSounds.EMPTY; @Nullable Key itemId; + Map, Object> customData = new IdentityHashMap<>(4); private FurnitureSettings() {} @@ -29,6 +32,7 @@ public class FurnitureSettings { newSettings.sounds = settings.sounds; newSettings.itemId = settings.itemId; newSettings.minimized = settings.minimized; + newSettings.customData = new IdentityHashMap<>(settings.customData); return newSettings; } @@ -45,6 +49,25 @@ public class FurnitureSettings { return settings; } + @SuppressWarnings("unchecked") + public T getCustomData(CustomDataType type) { + return (T) this.customData.get(type); + } + + public void clearCustomData() { + this.customData.clear(); + } + + @Nullable + @SuppressWarnings("unchecked") + public T removeCustomData(CustomDataType type) { + return (T) this.customData.remove(type); + } + + public void addCustomData(CustomDataType key, T value) { + this.customData.put(key, value); + } + public FurnitureSounds sounds() { return sounds; } @@ -103,7 +126,7 @@ public class FurnitureSettings { })); } - private static void registerFactory(String id, FurnitureSettings.Modifier.Factory factory) { + public static void registerFactory(String id, FurnitureSettings.Modifier.Factory factory) { FACTORIES.put(id, factory); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureVariant.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureVariant.java new file mode 100644 index 000000000..946f201cd --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureVariant.java @@ -0,0 +1,13 @@ +package net.momirealms.craftengine.core.entity.furniture; + +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfig; +import org.joml.Vector3f; + +import java.util.Optional; + +public record FurnitureVariant(FurnitureElementConfig[] elements, + HitBoxConfig[] hitBoxConfigs, + Optional externalModel, + Optional dropOffset) { +} \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxConfig.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxConfig.java deleted file mode 100644 index fdc574861..000000000 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxConfig.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.momirealms.craftengine.core.entity.furniture; - -import net.momirealms.craftengine.core.entity.seat.SeatConfig; -import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.world.WorldPosition; -import net.momirealms.craftengine.core.world.collision.AABB; -import org.joml.Quaternionf; -import org.joml.Vector3f; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Supplier; - -public interface HitBoxConfig { - - Key type(); - - void initPacketsAndColliders(int[] entityId, WorldPosition position, Quaternionf conjugated, - BiConsumer packets, Consumer collider, Consumer aabb); - - void initShapeForPlacement(double x, double y, double z, float yaw, Quaternionf conjugated, Consumer aabbs); - - int[] acquireEntityIds(Supplier entityIdSupplier); - - SeatConfig[] seats(); - - Vector3f position(); - - boolean blocksBuilding(); - - boolean canBeHitByProjectile(); - - boolean canUseItemOn(); -} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/behavior/EmptyFurnitureBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/behavior/EmptyFurnitureBehavior.java new file mode 100644 index 000000000..439348957 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/behavior/EmptyFurnitureBehavior.java @@ -0,0 +1,7 @@ +package net.momirealms.craftengine.core.entity.furniture.behavior; + +public final class EmptyFurnitureBehavior implements FurnitureBehavior { + private EmptyFurnitureBehavior() {} + + public static final EmptyFurnitureBehavior INSTANCE = new EmptyFurnitureBehavior(); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/behavior/FurnitureBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/behavior/FurnitureBehavior.java new file mode 100644 index 000000000..655168a5a --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/behavior/FurnitureBehavior.java @@ -0,0 +1,15 @@ +package net.momirealms.craftengine.core.entity.furniture.behavior; + +import net.momirealms.craftengine.core.entity.furniture.Furniture; +import net.momirealms.craftengine.core.entity.furniture.tick.FurnitureTicker; + +public interface FurnitureBehavior { + + default FurnitureTicker createSyncFurnitureTicker(T furniture) { + return null; + } + + default FurnitureTicker createAsyncBlockEntityTicker(T furniture) { + return null; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElement.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElement.java new file mode 100644 index 000000000..118d5bd92 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElement.java @@ -0,0 +1,14 @@ +package net.momirealms.craftengine.core.entity.furniture.element; + +import net.momirealms.craftengine.core.entity.player.Player; + +public interface FurnitureElement { + + void show(Player player); + + void hide(Player player); + + default void deactivate() {} + + default void activate() {} +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfig.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfig.java new file mode 100644 index 000000000..c291a43be --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfig.java @@ -0,0 +1,9 @@ +package net.momirealms.craftengine.core.entity.furniture.element; + +import net.momirealms.craftengine.core.world.WorldPosition; +import org.jetbrains.annotations.NotNull; + +public interface FurnitureElementConfig { + + E create(@NotNull WorldPosition position); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfigFactory.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfigFactory.java new file mode 100644 index 000000000..438124560 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfigFactory.java @@ -0,0 +1,8 @@ +package net.momirealms.craftengine.core.entity.furniture.element; + +import java.util.Map; + +public interface FurnitureElementConfigFactory { + + FurnitureElementConfig create(Map args); +} 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 new file mode 100644 index 000000000..8e375a743 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/element/FurnitureElementConfigs.java @@ -0,0 +1,31 @@ +package net.momirealms.craftengine.core.entity.furniture.element; + +import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.registry.Registries; +import net.momirealms.craftengine.core.registry.WritableRegistry; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceKey; + +import java.util.Map; +import java.util.Optional; + +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 void register(Key key, FurnitureElementConfigFactory type) { + ((WritableRegistry) BuiltInRegistries.FURNITURE_ELEMENT_TYPE) + .register(ResourceKey.create(Registries.FURNITURE_ELEMENT_TYPE.location(), key), type); + } + + 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); + FurnitureElementConfigFactory factory = BuiltInRegistries.FURNITURE_ELEMENT_TYPE.getValue(type); + if (factory == null) { + throw new LocalizedResourceConfigException("warning.config.furniture.element.invalid_type", type.toString()); + } + return factory.create(arguments); + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitHitBox.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/AbstractHitBox.java similarity index 54% rename from bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitHitBox.java rename to core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/AbstractHitBox.java index 8f725a94b..185fec9de 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitHitBox.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/AbstractHitBox.java @@ -1,40 +1,26 @@ -package net.momirealms.craftengine.bukkit.entity.furniture; +package net.momirealms.craftengine.core.entity.furniture.hitbox; -import net.momirealms.craftengine.bukkit.entity.seat.BukkitSeat; import net.momirealms.craftengine.core.entity.furniture.Furniture; -import net.momirealms.craftengine.core.entity.furniture.HitBox; -import net.momirealms.craftengine.core.entity.furniture.HitBoxConfig; -import net.momirealms.craftengine.core.entity.furniture.HitBoxPart; import net.momirealms.craftengine.core.entity.seat.Seat; -import net.momirealms.craftengine.core.entity.seat.SeatConfig; import net.momirealms.craftengine.core.world.EntityHitResult; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.sparrow.nbt.CompoundTag; import java.util.Optional; -public class BukkitHitBox implements HitBox { +public abstract class AbstractHitBox implements HitBox { private final Furniture furniture; private final HitBoxConfig config; private final HitBoxPart[] parts; - private final Seat[] seats; + private Seat[] seats; - public BukkitHitBox(Furniture furniture, HitBoxConfig config, HitBoxPart[] parts) { + public AbstractHitBox(Furniture furniture, HitBoxConfig config, HitBoxPart[] parts) { this.parts = parts; this.config = config; this.furniture = furniture; - this.seats = createSeats(config); } - @SuppressWarnings("unchecked") - private Seat[] createSeats(HitBoxConfig config) { - SeatConfig[] seatConfigs = config.seats(); - Seat[] seats = new Seat[seatConfigs.length]; - for (int i = 0; i < seatConfigs.length; i++) { - seats[i] = new BukkitSeat<>(this, seatConfigs[i]); - } - return seats; - } + protected abstract void createSeats(HitBoxConfig config); @Override public HitBoxPart[] parts() { @@ -65,6 +51,6 @@ public class BukkitHitBox implements HitBox { @Override public void saveCustomData(CompoundTag data) { data.putString("type", "furniture"); - data.putInt("entity_id", this.furniture.baseEntityId()); + data.putInt("entity_id", this.furniture.entityId()); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractHitBoxConfig.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/AbstractHitBoxConfig.java similarity index 86% rename from core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractHitBoxConfig.java rename to core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/AbstractHitBoxConfig.java index d7f8e3021..d9a5755f0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/AbstractHitBoxConfig.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/AbstractHitBoxConfig.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.entity.furniture; +package net.momirealms.craftengine.core.entity.furniture.hitbox; import net.momirealms.craftengine.core.entity.seat.SeatConfig; import org.joml.Vector3f; @@ -30,16 +30,16 @@ public abstract class AbstractHitBoxConfig implements HitBoxConfig { @Override public boolean blocksBuilding() { - return blocksBuilding; + return this.blocksBuilding; } @Override public boolean canBeHitByProjectile() { - return canBeHitByProjectile; + return this.canBeHitByProjectile; } @Override public boolean canUseItemOn() { - return canUseItemOn; + return this.canUseItemOn; } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBox.java similarity index 87% rename from core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java rename to core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBox.java index 961ea7420..32d31c3e1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBox.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBox.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.entity.furniture; +package net.momirealms.craftengine.core.entity.furniture.hitbox; import net.momirealms.craftengine.core.entity.seat.Seat; import net.momirealms.craftengine.core.entity.seat.SeatOwner; diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxConfig.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxConfig.java new file mode 100644 index 000000000..f14f7a064 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxConfig.java @@ -0,0 +1,20 @@ +package net.momirealms.craftengine.core.entity.furniture.hitbox; + +import net.momirealms.craftengine.core.entity.seat.SeatConfig; +import net.momirealms.craftengine.core.util.Key; +import org.joml.Vector3f; + +public interface HitBoxConfig { + + Key type(); + + SeatConfig[] seats(); + + Vector3f position(); + + boolean blocksBuilding(); + + boolean canBeHitByProjectile(); + + boolean canUseItemOn(); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxConfigFactory.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxConfigFactory.java similarity index 65% rename from core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxConfigFactory.java rename to core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxConfigFactory.java index 32fb5f355..df9a2b101 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxConfigFactory.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxConfigFactory.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.entity.furniture; +package net.momirealms.craftengine.core.entity.furniture.hitbox; import java.util.Map; diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxPart.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxPart.java similarity index 73% rename from core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxPart.java rename to core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxPart.java index cfa336889..fe5619281 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxPart.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxPart.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.entity.furniture; +package net.momirealms.craftengine.core.entity.furniture.hitbox; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.collision.AABB; diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxTypes.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxTypes.java similarity index 91% rename from core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxTypes.java rename to core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxTypes.java index c005ee619..853fa8318 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/HitBoxTypes.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/hitbox/HitBoxTypes.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.entity.furniture; +package net.momirealms.craftengine.core.entity.furniture.hitbox; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; import net.momirealms.craftengine.core.registry.BuiltInRegistries; @@ -14,6 +14,7 @@ public class HitBoxTypes { public static final Key INTERACTION = Key.of("minecraft:interaction"); public static final Key SHULKER = Key.of("minecraft:shulker"); public static final Key HAPPY_GHAST = Key.of("minecraft:happy_ghast"); + public static final Key VIRTUAL = Key.of("minecraft:virtual"); public static final Key CUSTOM = Key.of("minecraft:custom"); public static void register(Key key, HitBoxConfigFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/tick/FurnitureTicker.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/tick/FurnitureTicker.java new file mode 100644 index 000000000..1f034cbd9 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/tick/FurnitureTicker.java @@ -0,0 +1,8 @@ +package net.momirealms.craftengine.core.entity.furniture.tick; + +import net.momirealms.craftengine.core.entity.furniture.Furniture; + +public interface FurnitureTicker { + + void tick(T furniture); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/ItemEntity.java b/core/src/main/java/net/momirealms/craftengine/core/entity/item/ItemEntity.java similarity index 67% rename from core/src/main/java/net/momirealms/craftengine/core/entity/ItemEntity.java rename to core/src/main/java/net/momirealms/craftengine/core/entity/item/ItemEntity.java index 77483b9c1..120c168f2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/ItemEntity.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/item/ItemEntity.java @@ -1,4 +1,4 @@ -package net.momirealms.craftengine.core.entity; +package net.momirealms.craftengine.core.entity.item; import net.momirealms.craftengine.core.item.Item; diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/projectile/ProjectileMeta.java b/core/src/main/java/net/momirealms/craftengine/core/entity/projectile/ProjectileMeta.java index 7801b8f9d..ca0c73679 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/projectile/ProjectileMeta.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/projectile/ProjectileMeta.java @@ -1,7 +1,7 @@ package net.momirealms.craftengine.core.entity.projectile; -import net.momirealms.craftengine.core.entity.Billboard; -import net.momirealms.craftengine.core.entity.ItemDisplayContext; +import net.momirealms.craftengine.core.entity.display.Billboard; +import net.momirealms.craftengine.core.entity.display.ItemDisplayContext; import net.momirealms.craftengine.core.util.Key; import org.joml.Quaternionf; import org.joml.Vector3f; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/Item.java b/core/src/main/java/net/momirealms/craftengine/core/item/Item.java index 5b7c2f563..f48a6bf39 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/Item.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/Item.java @@ -28,7 +28,7 @@ import java.util.Optional; * This interface provides methods for managing item properties such as custom model data, * damage, display name, lore, enchantments, and tags. * - * @param the type of the item implementation + * @param the id of the item implementation */ public interface Item { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java index 186588e32..0c125097d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java @@ -1,7 +1,7 @@ package net.momirealms.craftengine.core.item; -import net.momirealms.craftengine.core.entity.Billboard; -import net.momirealms.craftengine.core.entity.ItemDisplayContext; +import net.momirealms.craftengine.core.entity.display.Billboard; +import net.momirealms.craftengine.core.entity.display.ItemDisplayContext; import net.momirealms.craftengine.core.entity.projectile.ProjectileMeta; import net.momirealms.craftengine.core.item.equipment.ComponentBasedEquipment; import net.momirealms.craftengine.core.item.equipment.Equipment; @@ -134,6 +134,12 @@ public class ItemSettings { this.customData.clear(); } + @Nullable + @SuppressWarnings("unchecked") + public T removeCustomData(CustomDataType type) { + return (T) this.customData.remove(type); + } + public void addCustomData(CustomDataType key, T value) { this.customData.put(key, value); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java index 190ee8004..206655f05 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java @@ -190,7 +190,7 @@ public class CustomSmithingTransformRecipe extends AbstractedFixedResultRecip @Override public CustomSmithingTransformRecipe readMap(Key id, Map arguments) { List base = MiscUtils.getAsStringList(arguments.get("base")); - List template = MiscUtils.getAsStringList(arguments.get("template-type")); + List template = MiscUtils.getAsStringList(arguments.get("template-id")); List addition = MiscUtils.getAsStringList(arguments.get("addition")); boolean mergeComponents = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("merge-components", true), "merge-components"); boolean mergeEnchantments = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("merge-enchantments", false), "merge-enchantments"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTrimRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTrimRecipe.java index 7119a5f48..c3a749435 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTrimRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTrimRecipe.java @@ -141,7 +141,7 @@ public class CustomSmithingTrimRecipe extends AbstractRecipe @Override public CustomSmithingTrimRecipe readMap(Key id, Map arguments) { List base = MiscUtils.getAsStringList(arguments.get("base")); - List template = MiscUtils.getAsStringList(arguments.get("template-type")); + List template = MiscUtils.getAsStringList(arguments.get("template-id")); List addition = MiscUtils.getAsStringList(arguments.get("addition")); Key pattern = VersionHelper.isOrAbove1_21_5() ? Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("pattern"), "warning.config.recipe.smithing_trim.missing_pattern")) : null; return new CustomSmithingTrimRecipe<>(id, diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyBonusCountFunction.java b/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyBonusCountFunction.java index c0475500d..b5d118862 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyBonusCountFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/function/ApplyBonusCountFunction.java @@ -87,12 +87,12 @@ public class ApplyBonusCountFunction extends AbstractLootConditionalFunction< public static Formula fromMap(Map map) { String type = (String) map.get("type"); if (type == null) { - throw new NullPointerException("number type cannot be null"); + throw new NullPointerException("number id cannot be null"); } Key key = Key.withDefaultNamespace(type, Key.DEFAULT_NAMESPACE); FormulaFactory factory = BuiltInRegistries.FORMULA_FACTORY.getValue(key); if (factory == null) { - throw new IllegalArgumentException("Unknown formula type: " + type); + throw new IllegalArgumentException("Unknown formula id: " + type); } return factory.create(map); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/ItemModels.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/ItemModels.java index e6d151250..c79c52a8a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/ItemModels.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/ItemModels.java @@ -75,7 +75,7 @@ public class ItemModels { Key key = Key.withDefaultNamespace(type, "minecraft"); ItemModelReader reader = BuiltInRegistries.ITEM_MODEL_READER.getValue(key); if (reader == null) { - throw new IllegalArgumentException("Invalid item model type: " + key); + throw new IllegalArgumentException("Invalid item model id: " + key); } return reader.read(json); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/condition/ConditionProperties.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/condition/ConditionProperties.java index f2d5022fa..ce19f4e75 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/condition/ConditionProperties.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/condition/ConditionProperties.java @@ -80,7 +80,7 @@ public class ConditionProperties { Key key = Key.withDefaultNamespace(type, "minecraft"); ConditionPropertyReader reader = BuiltInRegistries.CONDITION_PROPERTY_READER.getValue(key); if (reader == null) { - throw new IllegalArgumentException("Invalid condition property type: " + key); + throw new IllegalArgumentException("Invalid condition property id: " + key); } return reader.read(json); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/rangedisptach/RangeDispatchProperties.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/rangedisptach/RangeDispatchProperties.java index a8f09bcc0..0d98ca88b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/rangedisptach/RangeDispatchProperties.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/rangedisptach/RangeDispatchProperties.java @@ -71,7 +71,7 @@ public class RangeDispatchProperties { Key key = Key.withDefaultNamespace(type, "minecraft"); RangeDispatchPropertyReader reader = BuiltInRegistries.RANGE_DISPATCH_PROPERTY_READER.getValue(key); if (reader == null) { - throw new IllegalArgumentException("Invalid range dispatch property type: " + key); + throw new IllegalArgumentException("Invalid range dispatch property id: " + key); } return reader.read(json); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/select/SelectProperties.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/select/SelectProperties.java index e6f5b46e0..464c79fc3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/select/SelectProperties.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/select/SelectProperties.java @@ -71,7 +71,7 @@ public class SelectProperties { Key key = Key.withDefaultNamespace(type, "minecraft"); SelectPropertyReader reader = BuiltInRegistries.SELECT_PROPERTY_READER.getValue(key); if (reader == null) { - throw new IllegalArgumentException("Invalid select property type: " + key); + throw new IllegalArgumentException("Invalid select property id: " + key); } return reader.read(json); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/special/SignSpecialModel.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/special/SignSpecialModel.java index b6a83032c..cdfffd3bb 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/special/SignSpecialModel.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/special/SignSpecialModel.java @@ -45,7 +45,7 @@ public class SignSpecialModel implements SpecialModel { @Override public SpecialModel create(Map arguments) { Key type = Key.of(arguments.get("type").toString()); - String woodType = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("wood-type"), "warning.config.item.model.special.sign.missing_wood_type"); + String woodType = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("wood-id"), "warning.config.item.model.special.sign.missing_wood_type"); String texture = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("texture"), "warning.config.item.model.special.sign.missing_texture"); return new SignSpecialModel(type, woodType, texture); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/special/SpecialModels.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/special/SpecialModels.java index c27c4bba3..8b222da2b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/special/SpecialModels.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/special/SpecialModels.java @@ -80,7 +80,7 @@ public class SpecialModels { Key key = Key.withDefaultNamespace(type, "minecraft"); SpecialModelReader reader = BuiltInRegistries.SPECIAL_MODEL_READER.getValue(key); if (reader == null) { - throw new IllegalArgumentException("Invalid special model type: " + key); + throw new IllegalArgumentException("Invalid special model id: " + key); } return reader.read(json); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/tint/Tints.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/tint/Tints.java index d44d3102d..8148873b5 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/tint/Tints.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/tint/Tints.java @@ -65,7 +65,7 @@ public class Tints { Key key = Key.withDefaultNamespace(type, "minecraft"); TintReader reader = BuiltInRegistries.TINT_READER.getValue(key); if (reader == null) { - throw new IllegalArgumentException("Invalid tint type: " + type); + throw new IllegalArgumentException("Invalid tint id: " + type); } return reader.read(json); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/obfuscation/ObfA.java b/core/src/main/java/net/momirealms/craftengine/core/pack/obfuscation/ObfA.java index 9d545f67d..7833ea8fc 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/obfuscation/ObfA.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/obfuscation/ObfA.java @@ -36,7 +36,7 @@ public enum ObfA { return type; } } - throw new IllegalArgumentException("Unknown resource type: " + xclf); + throw new IllegalArgumentException("Unknown resource id: " + xclf); } public static final byte[] VALUES = new byte[] { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/command/sender/AbstractSender.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/command/sender/AbstractSender.java index ff1e71fa1..96a87ede0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/command/sender/AbstractSender.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/command/sender/AbstractSender.java @@ -9,7 +9,7 @@ import java.util.UUID; /** * Simple implementation of {@link Sender} using a {@link SenderFactory} * - * @param the command sender type + * @param the command sender id */ public final class AbstractSender implements Sender { private final Plugin plugin; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java index df09a8b08..2ec08dbdf 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java @@ -448,10 +448,10 @@ public class Config { // furniture furniture$hide_base_entity = config.getBoolean("furniture.hide-base-entity", true); - furniture$collision_entity_type = ColliderType.valueOf(config.getString("furniture.collision-entity-type", "interaction").toUpperCase(Locale.ENGLISH)); + furniture$collision_entity_type = ColliderType.valueOf(config.getString("furniture.collision-entity-id", "interaction").toUpperCase(Locale.ENGLISH)); // equipment - equipment$sacrificed_vanilla_armor$type = config.getString("equipment.sacrificed-vanilla-armor.type", "chainmail").toLowerCase(Locale.ENGLISH); + equipment$sacrificed_vanilla_armor$type = config.getString("equipment.sacrificed-vanilla-armor.id", "chainmail").toLowerCase(Locale.ENGLISH); if (!AbstractPackManager.ALLOWED_VANILLA_EQUIPMENT.contains(equipment$sacrificed_vanilla_armor$type)) { TranslationManager.instance().log("warning.config.equipment.invalid_sacrificed_armor", equipment$sacrificed_vanilla_armor$type); equipment$sacrificed_vanilla_armor$type = "chainmail"; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/StringKeyConstructor.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/StringKeyConstructor.java index 10f7f8bea..4c3ea46fc 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/StringKeyConstructor.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/StringKeyConstructor.java @@ -259,7 +259,7 @@ public class StringKeyConstructor extends SafeConstructor { if (value instanceof Number number) { return number.byteValue(); } - throw new RuntimeException("Unexpected type: " + value.getClass().getName()); + throw new RuntimeException("Unexpected id: " + value.getClass().getName()); } } @@ -271,7 +271,7 @@ public class StringKeyConstructor extends SafeConstructor { if (value instanceof Number number) { return number.shortValue(); } - throw new RuntimeException("Unexpected type: " + value.getClass().getName()); + throw new RuntimeException("Unexpected id: " + value.getClass().getName()); } } @@ -283,7 +283,7 @@ public class StringKeyConstructor extends SafeConstructor { if (value instanceof Number number) { return number.longValue(); } - throw new RuntimeException("Unexpected type: " + value.getClass().getName()); + throw new RuntimeException("Unexpected id: " + value.getClass().getName()); } } @@ -295,7 +295,7 @@ public class StringKeyConstructor extends SafeConstructor { if (value instanceof Number number) { return number.floatValue(); } - throw new RuntimeException("Unexpected type: " + value.getClass().getName()); + throw new RuntimeException("Unexpected id: " + value.getClass().getName()); } } @@ -307,7 +307,7 @@ public class StringKeyConstructor extends SafeConstructor { if (value instanceof Number number) { return number.doubleValue(); } - throw new RuntimeException("Unexpected type: " + value.getClass().getName()); + throw new RuntimeException("Unexpected id: " + value.getClass().getName()); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/argument/ExpressionTemplateArgument.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/argument/ExpressionTemplateArgument.java index cf02eeb46..790641d5d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/argument/ExpressionTemplateArgument.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/argument/ExpressionTemplateArgument.java @@ -61,7 +61,7 @@ public class ExpressionTemplateArgument implements TemplateArgument { public TemplateArgument create(Map arguments) { return new ExpressionTemplateArgument( arguments.getOrDefault("expression", "").toString(), - ValueType.valueOf(arguments.getOrDefault("value-type", "double").toString().toUpperCase(Locale.ROOT)) + ValueType.valueOf(arguments.getOrDefault("value-id", "double").toString().toUpperCase(Locale.ROOT)) ); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/argument/TemplateArguments.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/argument/TemplateArguments.java index 9b1a8ef91..4c0e9baa7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/argument/TemplateArguments.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/template/argument/TemplateArguments.java @@ -58,7 +58,7 @@ public class TemplateArguments { Key key = Key.withDefaultNamespace(type0, Key.DEFAULT_NAMESPACE); TemplateArgumentFactory factory = BuiltInRegistries.TEMPLATE_ARGUMENT_FACTORY.getValue(key); if (factory == null) { - throw new IllegalArgumentException("Unknown argument type: " + type); + throw new IllegalArgumentException("Unknown argument id: " + type); } return factory.create(map); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DamageFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DamageFunction.java index 97e197b55..fa33c8b7f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DamageFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/DamageFunction.java @@ -43,7 +43,7 @@ public class DamageFunction extends AbstractConditionalFunc @Override public Function create(Map arguments) { PlayerSelector selector = PlayerSelectors.fromObject(arguments.getOrDefault("target", "self"), conditionFactory()); - Key damageType = Key.of(ResourceConfigUtils.getAsStringOrNull(arguments.getOrDefault("damage-type", "generic"))); + Key damageType = Key.of(ResourceConfigUtils.getAsStringOrNull(arguments.getOrDefault("damage-id", "generic"))); NumberProvider amount = NumberProviders.fromObject(arguments.getOrDefault("amount", 1f)); return new DamageFunction<>(selector, damageType, amount, getPredicates(arguments)); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java index bbe2fe3d0..1d1b17e4e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/OpenWindowFunction.java @@ -65,7 +65,7 @@ public class OpenWindowFunction extends AbstractConditional @Override public Function create(Map arguments) { String title = Optional.ofNullable(arguments.get("title")).map(String::valueOf).orElse(null); - String rawType = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("gui-type"), "warning.config.function.open_window.missing_gui_type"); + String rawType = ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("gui-id"), "warning.config.function.open_window.missing_gui_type"); try { GuiType type = GuiType.valueOf(rawType.toUpperCase(Locale.ENGLISH)); return new OpenWindowFunction<>(getPredicates(arguments), PlayerSelectors.fromObject(arguments.get("target"), conditionFactory()), type, title); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RemoveFurnitureFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RemoveFurnitureFunction.java index 88a2eb2ff..796358ef3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RemoveFurnitureFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/RemoveFurnitureFunction.java @@ -46,7 +46,7 @@ public class RemoveFurnitureFunction extends AbstractCondit ContextHolder.Builder builder = ContextHolder.builder() .withParameter(DirectContextParameters.POSITION, position) .withParameter(DirectContextParameters.FURNITURE, furniture) - .withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, furniture.extraData().item().orElse(null)); + .withOptionalParameter(DirectContextParameters.FURNITURE_ITEM, furniture.dataAccessor().item().orElse(null)); Optional optionalPlayer = ctx.getOptionalParameter(DirectContextParameters.PLAYER); Player player = optionalPlayer.orElse(null); if (player != null) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ReplaceFurnitureFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ReplaceFurnitureFunction.java index 520863010..154c66687 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ReplaceFurnitureFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ReplaceFurnitureFunction.java @@ -94,7 +94,7 @@ public class ReplaceFurnitureFunction extends AbstractCondi NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); NumberProvider pitch = NumberProviders.fromObject(arguments.getOrDefault("pitch", "")); NumberProvider yaw = NumberProviders.fromObject(arguments.getOrDefault("yaw", "")); - AnchorType anchorType = ResourceConfigUtils.getAsEnum(arguments.get("anchor-type"), AnchorType.class, null); + AnchorType anchorType = ResourceConfigUtils.getAsEnum(arguments.get("anchor-id"), AnchorType.class, null); boolean dropLoot = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("drop-loot", true), "drop-loot"); boolean playSound = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("play-sound", true), "play-sound"); return new ReplaceFurnitureFunction<>(furnitureId, x, y, z, pitch, yaw, anchorType, dropLoot, playSound, getPredicates(arguments)); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SpawnFurnitureFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SpawnFurnitureFunction.java index 39a879c3e..1db66e416 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SpawnFurnitureFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/SpawnFurnitureFunction.java @@ -1,8 +1,5 @@ package net.momirealms.craftengine.core.plugin.context.function; -import net.momirealms.craftengine.core.entity.furniture.AnchorType; -import net.momirealms.craftengine.core.entity.furniture.FurnitureExtraData; -import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.Condition; import net.momirealms.craftengine.core.plugin.context.Context; import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; @@ -15,7 +12,6 @@ import net.momirealms.craftengine.core.world.WorldPosition; import java.util.List; import java.util.Map; -import java.util.Optional; public class SpawnFurnitureFunction extends AbstractConditionalFunction { private final Key furnitureId; @@ -24,7 +20,7 @@ public class SpawnFurnitureFunction extends AbstractConditi private final NumberProvider z; private final NumberProvider pitch; private final NumberProvider yaw; - private final AnchorType anchorType; + private final String variant; private final boolean playSound; public SpawnFurnitureFunction( @@ -34,7 +30,7 @@ public class SpawnFurnitureFunction extends AbstractConditi NumberProvider z, NumberProvider pitch, NumberProvider yaw, - AnchorType anchorType, + String variant, boolean playSound, List> predicates ) { @@ -45,7 +41,7 @@ public class SpawnFurnitureFunction extends AbstractConditi this.z = z; this.pitch = pitch; this.yaw = yaw; - this.anchorType = anchorType; + this.variant = variant; this.playSound = playSound; } @@ -59,17 +55,18 @@ public class SpawnFurnitureFunction extends AbstractConditi float pitchValue = this.pitch.getFloat(ctx); float yawValue = this.yaw.getFloat(ctx); WorldPosition position = new WorldPosition(world, xPos, yPos, zPos, pitchValue, yawValue); - spawnFurniture(this.furnitureId, position, this.anchorType, this.playSound); + // fixme api +// spawnFurniture(this.furnitureId, position, this.anchorType, this.playSound); }); } - public static void spawnFurniture(Key furnitureId, WorldPosition position, AnchorType anchorType, boolean playSound) { - CraftEngine.instance().furnitureManager().furnitureById(furnitureId).ifPresent(furniture -> { - AnchorType anchor = Optional.ofNullable(anchorType).orElse(furniture.getAnyAnchorType()); - FurnitureExtraData extraData = FurnitureExtraData.builder().anchorType(anchor).build(); - CraftEngine.instance().furnitureManager().place(position, furniture, extraData, playSound); - }); - } +// public static void spawnFurniture(Key furnitureId, WorldPosition position, AnchorType anchorType, boolean playSound) { +// CraftEngine.instance().furnitureManager().furnitureById(furnitureId).ifPresent(furniture -> { +// AnchorType anchor = Optional.ofNullable(anchorType).orElse(furniture.getAnyAnchorType()); +// FurnitureDataAccessor extraData = FurnitureDataAccessor.builder().anchorType(anchor).build(); +// CraftEngine.instance().furnitureManager().place(position, furniture, extraData, playSound); +// }); +// } @Override public Key type() { @@ -90,9 +87,9 @@ public class SpawnFurnitureFunction extends AbstractConditi NumberProvider z = NumberProviders.fromObject(arguments.getOrDefault("z", "")); NumberProvider pitch = NumberProviders.fromObject(arguments.getOrDefault("pitch", "")); NumberProvider yaw = NumberProviders.fromObject(arguments.getOrDefault("yaw", "")); - AnchorType anchorType = ResourceConfigUtils.getAsEnum(arguments.get("anchor-type"), AnchorType.class, null); + String variant = ResourceConfigUtils.getAsStringOrNull(ResourceConfigUtils.get(arguments, "variant", "anchor-id")); boolean playSound = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("play-sound", true), "play-sound"); - return new SpawnFurnitureFunction<>(furnitureId, x, y, z, pitch, yaw, anchorType, playSound, getPredicates(arguments)); + return new SpawnFurnitureFunction<>(furnitureId, x, y, z, pitch, yaw, variant, playSound, getPredicates(arguments)); } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ToastFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ToastFunction.java index 853cc7c28..ec63aa261 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ToastFunction.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ToastFunction.java @@ -63,7 +63,7 @@ public class ToastFunction extends AbstractConditionalFunct @Override public Function create(Map arguments) { AdvancementType advancementType; - String advancementName = arguments.getOrDefault("advancement-type", "goal").toString(); + String advancementName = arguments.getOrDefault("advancement-id", "goal").toString(); try { advancementType = AdvancementType.valueOf(advancementName.toUpperCase(Locale.ROOT)); } catch (IllegalArgumentException e) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java index 0fd065ee2..273e16b2b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/EntityParameterProvider.java @@ -1,7 +1,7 @@ package net.momirealms.craftengine.core.plugin.context.parameter; import net.momirealms.craftengine.core.entity.Entity; -import net.momirealms.craftengine.core.entity.ItemEntity; +import net.momirealms.craftengine.core.entity.item.ItemEntity; import net.momirealms.craftengine.core.plugin.context.ChainParameterProvider; import net.momirealms.craftengine.core.plugin.context.ContextKey; import net.momirealms.craftengine.core.util.MiscUtils; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/LangData.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/LangData.java index b677d18a5..b0f6d19dd 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/LangData.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/locale/LangData.java @@ -53,7 +53,7 @@ public class LangData { temp.put(result, entry.getValue()); } }, - () -> CraftEngine.instance().logger().warn("Unknown lang type: " + key) + () -> CraftEngine.instance().logger().warn("Unknown lang id: " + key) ); } else { temp.put(key, entry.getValue()); diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java b/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java index f09e3a159..8cab5409b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/BuiltInRegistries.java @@ -5,7 +5,9 @@ import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.entity.BlockEntityType; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory; import net.momirealms.craftengine.core.block.properties.PropertyFactory; -import net.momirealms.craftengine.core.entity.furniture.HitBoxConfigFactory; +import net.momirealms.craftengine.core.entity.CustomEntityType; +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigFactory; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfigFactory; import net.momirealms.craftengine.core.item.ItemDataModifierFactory; import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; import net.momirealms.craftengine.core.item.equipment.EquipmentFactory; @@ -88,9 +90,11 @@ public class BuiltInRegistries { public static final Registry> RECIPE_POST_PROCESSOR_TYPE = createConstantBoundRegistry(Registries.RECIPE_POST_PROCESSOR_TYPE, 16); public static final Registry> ITEM_UPDATER_TYPE = createConstantBoundRegistry(Registries.ITEM_UPDATER_TYPE, 16); public static final Registry> MOD_PACKET = createConstantBoundRegistry(Registries.MOD_PACKET, 16); - public static final Registry> BLOCK_ENTITY_TYPE = createConstantBoundRegistry(Registries.BLOCK_ENTITY_TYPE, 128); + public static final Registry> BLOCK_ENTITY_TYPE = createConstantBoundRegistry(Registries.BLOCK_ENTITY_TYPE, 64); public static final Registry BLOCK_ENTITY_ELEMENT_TYPE = createConstantBoundRegistry(Registries.BLOCK_ENTITY_ELEMENT_TYPE, 16); public static final Registry CRAFT_REMAINDER_FACTORY = createConstantBoundRegistry(Registries.CRAFT_REMAINDER_FACTORY, 16); + public static final Registry> ENTITY_TYPE = createConstantBoundRegistry(Registries.ENTITY_TYPE, 32); + public static final Registry FURNITURE_ELEMENT_TYPE = createConstantBoundRegistry(Registries.FURNITURE_ELEMENT_TYPE, 16); private static Registry createConstantBoundRegistry(ResourceKey> key, int expectedSize) { return new ConstantBoundRegistry<>(key, expectedSize); diff --git a/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java b/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java index 33a34a9d9..5258d2e4b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java +++ b/core/src/main/java/net/momirealms/craftengine/core/registry/Registries.java @@ -5,7 +5,9 @@ import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.entity.BlockEntityType; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfigFactory; import net.momirealms.craftengine.core.block.properties.PropertyFactory; -import net.momirealms.craftengine.core.entity.furniture.HitBoxConfigFactory; +import net.momirealms.craftengine.core.entity.CustomEntityType; +import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigFactory; +import net.momirealms.craftengine.core.entity.furniture.hitbox.HitBoxConfigFactory; import net.momirealms.craftengine.core.item.ItemDataModifierFactory; import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; import net.momirealms.craftengine.core.item.equipment.EquipmentFactory; @@ -93,4 +95,6 @@ public class Registries { public static final ResourceKey>> BLOCK_ENTITY_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("block_entity_type")); public static final ResourceKey> BLOCK_ENTITY_ELEMENT_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("block_entity_element_type")); public static final ResourceKey> CRAFT_REMAINDER_FACTORY = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("craft_remainder_factory")); + public static final ResourceKey>> ENTITY_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("entity_type")); + public static final ResourceKey> FURNITURE_ELEMENT_TYPE = ResourceKey.create(ROOT_REGISTRY, Key.withDefaultNamespace("furniture_element_type")); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/sound/SoundData.java b/core/src/main/java/net/momirealms/craftengine/core/sound/SoundData.java index af0356c6e..cc7919e9c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/sound/SoundData.java +++ b/core/src/main/java/net/momirealms/craftengine/core/sound/SoundData.java @@ -22,7 +22,7 @@ public record SoundData(Key id, SoundValue volume, SoundValue pitch) { SoundValue pitchValue = Optional.ofNullable(SoundValue.of(map.get("pitch"))).orElse(volume); return new SoundData(id, volumeValue, pitchValue); } else { - throw new IllegalArgumentException("Illegal object type for sound data: " + obj.getClass()); + throw new IllegalArgumentException("Illegal object id for sound data: " + obj.getClass()); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/Pair.java b/core/src/main/java/net/momirealms/craftengine/core/util/Pair.java index de9774f5c..7d5e95ce6 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/Pair.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/Pair.java @@ -6,8 +6,8 @@ import java.util.Objects; * A generic class representing a pair of values. * This class provides methods to create and access pairs of values. * - * @param the type of the left value - * @param the type of the right value + * @param the id of the left value + * @param the id of the right value */ public record Pair(L left, R right) { @@ -16,8 +16,8 @@ public record Pair(L left, R right) { * * @param left the left value * @param right the right value - * @param the type of the left value - * @param the type of the right value + * @param the id of the left value + * @param the id of the right value * @return a new {@link Pair} with the specified values */ public static Pair of(final L left, final R right) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java index 703571af4..30472678c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/ReflectionUtils.java @@ -439,7 +439,7 @@ public class ReflectionUtils { public static List getMethods(@NotNull Class clazz, @NotNull Class returnType, @NotNull Class... parameterTypes) { List list = new ArrayList<>(); for (Method method : clazz.getMethods()) { - if (!returnType.isAssignableFrom(method.getReturnType()) // check type + if (!returnType.isAssignableFrom(method.getReturnType()) // check id || method.getParameterCount() != parameterTypes.length // check length ) continue; Class[] types = method.getParameterTypes(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java index 1a98323d1..4461e5d93 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/ResourceConfigUtils.java @@ -137,13 +137,13 @@ public final class ResourceConfigUtils { try { return Integer.parseInt(s.replace("_", "")); } catch (NumberFormatException e) { - throw new LocalizedResourceConfigException("warning.config.type.int", e, s, option); + throw new LocalizedResourceConfigException("warning.config.id.int", e, s, option); } } case Boolean b -> { return b ? 1 : 0; } - default -> throw new LocalizedResourceConfigException("warning.config.type.int", o.toString(), option); + default -> throw new LocalizedResourceConfigException("warning.config.id.int", o.toString(), option); } } @@ -162,11 +162,11 @@ public final class ResourceConfigUtils { try { return Double.parseDouble(s); } catch (NumberFormatException e) { - throw new LocalizedResourceConfigException("warning.config.type.double", e, s, option); + throw new LocalizedResourceConfigException("warning.config.id.double", e, s, option); } } default -> { - throw new LocalizedResourceConfigException("warning.config.type.double", o.toString(), option); + throw new LocalizedResourceConfigException("warning.config.id.double", o.toString(), option); } } } @@ -183,14 +183,14 @@ public final class ResourceConfigUtils { try { return Float.parseFloat(s); } catch (NumberFormatException e) { - throw new LocalizedResourceConfigException("warning.config.type.float", e, s, option); + throw new LocalizedResourceConfigException("warning.config.id.float", e, s, option); } } case Number number -> { return number.floatValue(); } default -> { - throw new LocalizedResourceConfigException("warning.config.type.float", o.toString(), option); + throw new LocalizedResourceConfigException("warning.config.id.float", o.toString(), option); } } } @@ -206,15 +206,15 @@ public final class ResourceConfigUtils { case Number n -> { if (n.byteValue() == 0) return false; if (n.byteValue() == 1) return true; - throw new LocalizedResourceConfigException("warning.config.type.boolean", String.valueOf(n), option); + throw new LocalizedResourceConfigException("warning.config.id.boolean", String.valueOf(n), option); } case String s -> { if (s.equalsIgnoreCase("true")) return true; if (s.equalsIgnoreCase("false")) return false; - throw new LocalizedResourceConfigException("warning.config.type.boolean", s, option); + throw new LocalizedResourceConfigException("warning.config.id.boolean", s, option); } default -> { - throw new LocalizedResourceConfigException("warning.config.type.boolean", o.toString(), option); + throw new LocalizedResourceConfigException("warning.config.id.boolean", o.toString(), option); } } } @@ -234,11 +234,11 @@ public final class ResourceConfigUtils { try { return Long.parseLong(s.replace("_", "")); } catch (NumberFormatException e) { - throw new LocalizedResourceConfigException("warning.config.type.long", e, s, option); + throw new LocalizedResourceConfigException("warning.config.id.long", e, s, option); } } default -> { - throw new LocalizedResourceConfigException("warning.config.type.long", o.toString(), option); + throw new LocalizedResourceConfigException("warning.config.id.long", o.toString(), option); } } } @@ -248,7 +248,7 @@ public final class ResourceConfigUtils { if (obj instanceof Map map) { return (Map) map; } - throw new LocalizedResourceConfigException("warning.config.type.map", String.valueOf(obj), option); + throw new LocalizedResourceConfigException("warning.config.id.map", String.valueOf(obj), option); } @SuppressWarnings("unchecked") @@ -259,7 +259,7 @@ public final class ResourceConfigUtils { if (obj instanceof Map map) { return (Map) map; } - throw new LocalizedResourceConfigException("warning.config.type.map", String.valueOf(obj), option); + throw new LocalizedResourceConfigException("warning.config.id.map", String.valueOf(obj), option); } public static Vector3f getAsVector3f(Object o, String option) { @@ -274,7 +274,7 @@ public final class ResourceConfigUtils { } else if (split.length == 1) { return new Vector3f(Float.parseFloat(split[0])); } else { - throw new LocalizedResourceConfigException("warning.config.type.vector3f", stringFormat, option); + throw new LocalizedResourceConfigException("warning.config.id.vector3f", stringFormat, option); } } } @@ -293,7 +293,7 @@ public final class ResourceConfigUtils { } else if (split.length == 1) { return QuaternionUtils.toQuaternionf(0, (float) -Math.toRadians(Float.parseFloat(split[0])), 0); } else { - throw new LocalizedResourceConfigException("warning.config.type.quaternionf", stringFormat, option); + throw new LocalizedResourceConfigException("warning.config.id.quaternionf", stringFormat, option); } } } @@ -311,7 +311,7 @@ public final class ResourceConfigUtils { double d = Double.parseDouble(split[0]); return new Vec3d(d, d, d); } else { - throw new LocalizedResourceConfigException("warning.config.type.vec3d", stringFormat, option); + throw new LocalizedResourceConfigException("warning.config.id.vec3d", stringFormat, option); } } } @@ -344,50 +344,54 @@ public final class ResourceConfigUtils { } public static AABB getAsAABB(Object o, String option) { - if (o == null) { - throw new LocalizedResourceConfigException("warning.config.type.aabb", "null", option); - } - if (o instanceof Number number) { - double min = -(number.doubleValue() / 2); - double max = number.doubleValue() / 2; - return new AABB(min, min, min, max, max, max); - } else { - double[] args; - if (o instanceof List list) { - args = new double[list.size()]; - for (int i = 0; i < args.length; i++) { - if (list.get(i) instanceof Number number) { - args[i] = number.doubleValue(); - } else { + switch (o) { + case null -> throw new LocalizedResourceConfigException("warning.config.id.aabb", "null", option); + case AABB aabb -> { + return aabb; + } + case Number number -> { + double min = -(number.doubleValue() / 2); + double max = number.doubleValue() / 2; + return new AABB(min, min, min, max, max, max); + } + default -> { + double[] args; + if (o instanceof List list) { + args = new double[list.size()]; + for (int i = 0; i < args.length; i++) { + if (list.get(i) instanceof Number number) { + args[i] = number.doubleValue(); + } else { + try { + args[i] = Double.parseDouble(list.get(i).toString()); + } catch (NumberFormatException e) { + throw new LocalizedResourceConfigException("warning.config.id.aabb", o.toString(), option); + } + } + } + } else { + String[] split = o.toString().split(","); + args = new double[split.length]; + for (int i = 0; i < args.length; i++) { try { - args[i] = Double.parseDouble(list.get(i).toString()); + args[i] = Double.parseDouble(split[i]); } catch (NumberFormatException e) { - throw new LocalizedResourceConfigException("warning.config.type.aabb", o.toString(), option); + throw new LocalizedResourceConfigException("warning.config.id.aabb", o.toString(), option); } } } - } else { - String[] split = o.toString().split(","); - args = new double[split.length]; - for (int i = 0; i < args.length; i++) { - try { - args[i] = Double.parseDouble(split[i]); - } catch (NumberFormatException e) { - throw new LocalizedResourceConfigException("warning.config.type.aabb", o.toString(), option); - } + if (args.length == 1) { + return new AABB(-args[0] / 2, -args[0] / 2, -args[0] / 2, args[0] / 2, args[0] / 2, args[0] / 2); + } else if (args.length == 2) { + return new AABB(-args[0] / 2, -args[1] / 2, -args[0] / 2, args[0] / 2, args[1] / 2, args[0] / 2); + } else if (args.length == 3) { + return new AABB(-args[0] / 2, -args[1] / 2, -args[2] / 2, args[0] / 2, args[1] / 2, args[2] / 2); + } else if (args.length == 6) { + return new AABB(args[0], args[1], args[2], args[3], args[4], args[5]); + } else { + throw new LocalizedResourceConfigException("warning.config.id.aabb", o.toString(), option); } } - if (args.length == 1) { - return new AABB(-args[0]/2, -args[0]/2, -args[0]/2, args[0]/2, args[0]/2, args[0]/2); - } else if (args.length == 2) { - return new AABB(-args[0]/2, -args[1]/2, -args[0]/2, args[0]/2, args[1]/2, args[0]/2); - } else if (args.length == 3) { - return new AABB(-args[0]/2, -args[1]/2, -args[2]/2, args[0]/2, args[1]/2, args[2]/2); - } else if (args.length == 6) { - return new AABB(args[0], args[1], args[2], args[3], args[4], args[5]); - } else { - throw new LocalizedResourceConfigException("warning.config.type.aabb", o.toString(), option); - } } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/SNBTReader.java b/core/src/main/java/net/momirealms/craftengine/core/util/SNBTReader.java index 0be81388d..27fd39740 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/SNBTReader.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/SNBTReader.java @@ -156,7 +156,7 @@ public final class SNBTReader extends DefaultStringReader { // 1.21.6的SNBT原版是支持 {key:[B;1,2b,0xFF]} 这种奇葩写法的, 越界部分会被自动舍弃, 如0xff的byte值为-1. // 如果需要和原版对齐, 那么只需要判断是否是数字就行了. // if (!(element instanceof Number number)) - // throw new IllegalArgumentException("Error element type at pos " + getCursor()); + // throw new IllegalArgumentException("Error element id at pos " + getCursor()); if (!(element instanceof Number number)) throw new IllegalArgumentException("Error parsing number at pos " + getCursor()); diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/Tuple.java b/core/src/main/java/net/momirealms/craftengine/core/util/Tuple.java index e4cf6baf5..d91a2afaf 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/Tuple.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/Tuple.java @@ -6,9 +6,9 @@ import java.util.Objects; * A generic class representing a tuple with three values. * This class provides methods for creating and accessing tuples with three values. * - * @param the type of the left value - * @param the type of the middle value - * @param the type of the right value + * @param the id of the left value + * @param the id of the middle value + * @param the id of the right value */ public record Tuple(L left, M mid, R right) { @@ -18,9 +18,9 @@ public record Tuple(L left, M mid, R right) { * @param left the left value * @param mid the middle value * @param right the right value - * @param the type of the left value - * @param the type of the middle value - * @param the type of the right value + * @param the id of the left value + * @param the id of the middle value + * @param the id of the right value * @return a new {@link Tuple} with the specified values */ public static Tuple of(final L left, final M mid, final R right) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/TypeUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/TypeUtils.java index 8e3b3dc1a..02687838f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/TypeUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/TypeUtils.java @@ -8,18 +8,18 @@ public class TypeUtils { private TypeUtils() {} /** - * Checks if the provided object is of the specified type. + * Checks if the provided object is of the specified id. * If not, throws an IllegalArgumentException with a detailed message. * * @param object The object to check. - * @param expectedType The expected class type. - * @param The type parameter for expectedType. - * @return The object cast to the expected type if it matches. - * @throws IllegalArgumentException if the object's type does not match the expected type. + * @param expectedType The expected class id. + * @param The id parameter for expectedType. + * @return The object cast to the expected id if it matches. + * @throws IllegalArgumentException if the object's id does not match the expected id. */ public static T checkType(Object object, Class expectedType) { if (!expectedType.isInstance(object)) { - throw new IllegalArgumentException("Expected type: " + expectedType.getName() + + throw new IllegalArgumentException("Expected id: " + expectedType.getName() + ", but got: " + (object == null ? "null" : object.getClass().getName())); } return expectedType.cast(object); @@ -48,7 +48,7 @@ public class TypeUtils { } yield bytes; } - default -> throw new IllegalStateException("Unsupported type: " + type.toLowerCase(Locale.ENGLISH)); + default -> throw new IllegalStateException("Unsupported id: " + type.toLowerCase(Locale.ENGLISH)); }; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java index 50eda3140..0aee4a4a1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/CEChunk.java @@ -10,6 +10,7 @@ import net.momirealms.craftengine.core.block.entity.render.DynamicBlockEntityRen import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElement; import net.momirealms.craftengine.core.block.entity.render.element.BlockEntityElementConfig; import net.momirealms.craftengine.core.block.entity.tick.*; +import net.momirealms.craftengine.core.entity.CustomEntity; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.entityculling.CullingData; @@ -18,6 +19,7 @@ import net.momirealms.craftengine.core.world.*; import net.momirealms.craftengine.core.world.chunk.client.VirtualCullableObject; import net.momirealms.craftengine.core.world.chunk.serialization.DefaultBlockEntityRendererSerializer; import net.momirealms.craftengine.core.world.chunk.serialization.DefaultBlockEntitySerializer; +import net.momirealms.craftengine.core.world.chunk.serialization.DefaultEntitySerializer; import net.momirealms.sparrow.nbt.ListTag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -30,11 +32,12 @@ public class CEChunk { public final ChunkPos chunkPos; public final CESection[] sections; public final WorldHeight worldHeightAccessor; - public final Map blockEntities; // 从区域线程上访问,安全 - public final Map tickingSyncBlockEntitiesByPos; // 从区域线程上访问,安全 - public final Map tickingAsyncBlockEntitiesByPos; // 从区域线程上访问,安全 - public final Map constantBlockEntityRenderers; // 会从区域线程上读写,netty线程上读取 - public final Map dynamicBlockEntityRenderers; // 会从区域线程上读写,netty线程上读取 + private final Map entities; // 从区域线程上访问,安全 + private final Map blockEntities; // 从区域线程上访问,安全 + private final Map tickingSyncBlockEntitiesByPos; // 从区域线程上访问,安全 + private final Map tickingAsyncBlockEntitiesByPos; // 从区域线程上访问,安全 + private final Map constantBlockEntityRenderers; // 会从区域线程上读写,netty线程上读取 + private final Map dynamicBlockEntityRenderers; // 会从区域线程上读写,netty线程上读取 private final ReentrantReadWriteLock renderLock = new ReentrantReadWriteLock(); private volatile boolean dirty; private volatile boolean loaded; @@ -50,10 +53,11 @@ public class CEChunk { this.dynamicBlockEntityRenderers = new Object2ObjectOpenHashMap<>(10, 0.5f); this.tickingSyncBlockEntitiesByPos = new Object2ObjectOpenHashMap<>(10, 0.5f); this.tickingAsyncBlockEntitiesByPos = new Object2ObjectOpenHashMap<>(10, 0.5f); + this.entities = new Object2ObjectOpenHashMap<>(10, 0.5f); this.fillEmptySection(); } - public CEChunk(CEWorld world, ChunkPos chunkPos, CESection[] sections, @Nullable ListTag blockEntitiesTag, @Nullable ListTag itemDisplayBlockRenders) { + public CEChunk(CEWorld world, ChunkPos chunkPos, CESection[] sections, @Nullable ListTag blockEntitiesTag, @Nullable ListTag blockEntityRenders, @Nullable ListTag entities) { this.world = world; this.chunkPos = chunkPos; this.worldHeightAccessor = world.worldHeight(); @@ -80,15 +84,27 @@ public class CEChunk { } else { this.blockEntities = new Object2ObjectOpenHashMap<>(10, 0.5f); } - if (itemDisplayBlockRenders != null) { - this.constantBlockEntityRenderers = new Object2ObjectOpenHashMap<>(Math.max(itemDisplayBlockRenders.size(), 10), 0.5f); - List blockEntityRendererPoses = DefaultBlockEntityRendererSerializer.deserialize(this.chunkPos, itemDisplayBlockRenders); + if (blockEntityRenders != null) { + this.constantBlockEntityRenderers = new Object2ObjectOpenHashMap<>(Math.max(blockEntityRenders.size(), 10), 0.5f); + List blockEntityRendererPoses = DefaultBlockEntityRendererSerializer.deserialize(this.chunkPos, blockEntityRenders); for (BlockPos pos : blockEntityRendererPoses) { this.addConstantBlockEntityRenderer(pos); } } else { this.constantBlockEntityRenderers = new Object2ObjectOpenHashMap<>(10, 0.5f); } + if (entities != null) { + this.entities = new Object2ObjectOpenHashMap<>(Math.max(entities.size(), 10), 0.5f); + for (CustomEntity entity : DefaultEntitySerializer.deserialize(world, entities)) { + this.entities.put(entity.uuid(), entity); + } + } else { + this.entities = new Object2ObjectOpenHashMap<>(10, 0.5f); + } + } + + public Map entities() { + return Collections.unmodifiableMap(this.entities); } public void spawnBlockEntities(Player player) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultBlockEntitySerializer.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultBlockEntitySerializer.java index 3c331d193..46d340b54 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultBlockEntitySerializer.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultBlockEntitySerializer.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior; import net.momirealms.craftengine.core.block.entity.BlockEntity; import net.momirealms.craftengine.core.block.entity.BlockEntityType; +import net.momirealms.craftengine.core.block.entity.InactiveBlockEntity; import net.momirealms.craftengine.core.plugin.logger.Debugger; import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.util.Key; @@ -37,11 +38,13 @@ public final class DefaultBlockEntitySerializer { CompoundTag data = tag.getCompound(i); Key id = Key.of(data.getString("id")); BlockEntityType type = BuiltInRegistries.BLOCK_ENTITY_TYPE.getValue(id); + BlockPos pos = BlockEntity.readPosAndVerify(data, chunk.chunkPos()); + ImmutableBlockState blockState = chunk.getBlockState(pos); if (type == null) { Debugger.BLOCK.debug(() -> "Unknown block entity type: " + id); + BlockEntity blockEntity = new InactiveBlockEntity(pos, blockState, data); + blockEntities.add(blockEntity); } else { - BlockPos pos = BlockEntity.readPosAndVerify(data, chunk.chunkPos()); - ImmutableBlockState blockState = chunk.getBlockState(pos); if (blockState.blockEntityType() == type) { Optional entityBlockBehavior = blockState.behavior().getAs(EntityBlockBehavior.class); if (entityBlockBehavior.isPresent()) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultChunkSerializer.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultChunkSerializer.java index 2f851fe49..e98376e7e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultChunkSerializer.java +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultChunkSerializer.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.core.world.chunk.serialization; +import net.momirealms.craftengine.core.entity.CustomEntity; import net.momirealms.craftengine.core.world.CEWorld; import net.momirealms.craftengine.core.world.ChunkPos; import net.momirealms.craftengine.core.world.chunk.CEChunk; @@ -9,6 +10,9 @@ import net.momirealms.sparrow.nbt.ListTag; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Map; +import java.util.UUID; + public final class DefaultChunkSerializer { private DefaultChunkSerializer() {} @@ -36,6 +40,10 @@ public final class DefaultChunkSerializer { if (!blockEntityRenders.isEmpty()) { chunkNbt.put("block_entity_renderers", blockEntityRenders); } + ListTag listTag = new ListTag(); + Map entities = chunk.entities(); + + return chunkNbt; } @@ -54,7 +62,8 @@ public final class DefaultChunkSerializer { } } ListTag blockEntities = chunkNbt.getList("block_entities"); - ListTag itemDisplayBlockRenders = chunkNbt.getList("block_entity_renderers"); - return new CEChunk(world, pos, sectionArray, blockEntities, itemDisplayBlockRenders); + ListTag blockEntityRenders = chunkNbt.getList("block_entity_renderers"); + ListTag entities = chunkNbt.getList("entities"); + return new CEChunk(world, pos, sectionArray, blockEntities, blockEntityRenders, entities); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultEntitySerializer.java b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultEntitySerializer.java new file mode 100644 index 000000000..df24bb530 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/world/chunk/serialization/DefaultEntitySerializer.java @@ -0,0 +1,55 @@ +package net.momirealms.craftengine.core.world.chunk.serialization; + +import net.momirealms.craftengine.core.entity.CustomEntity; +import net.momirealms.craftengine.core.entity.CustomEntityType; +import net.momirealms.craftengine.core.entity.InactiveCustomEntity; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.world.CEWorld; +import net.momirealms.craftengine.core.world.WorldPosition; +import net.momirealms.sparrow.nbt.CompoundTag; +import net.momirealms.sparrow.nbt.ListTag; +import net.momirealms.sparrow.nbt.Tag; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.UUID; + +public class DefaultEntitySerializer { + + public static ListTag serialize(@NotNull Collection entity) { + ListTag entities = new ListTag(); + for (CustomEntity customEntity : entity) { + if (customEntity.isValid()) { + entities.add(customEntity.saveAsTag()); + } + } + return entities; + } + + public static List deserialize(CEWorld world, ListTag entitiesTag) { + List entities = new ArrayList<>(entitiesTag.size()); + for (Tag tag : entitiesTag) { + if (tag instanceof CompoundTag entityTag) { + WorldPosition worldPosition = CustomEntity.readPos(world, entityTag); + UUID uuid = CustomEntity.readUUID(entityTag); + Key type = Key.of(entityTag.getString("type")); + CustomEntityType entityType = BuiltInRegistries.ENTITY_TYPE.getValue(type); + if (entityType == null) { + InactiveCustomEntity entity = new InactiveCustomEntity(uuid, worldPosition, entityTag); + entities.add(entity); + } else { + CustomEntity entity = entityType.factory().create(uuid, worldPosition); + entity.loadCustomData(entityTag); + // 加载时无效则直接放弃 + if (entity.isValid()) { + entities.add(entity); + } + } + } + } + return entities; + } +}