diff --git a/bukkit/loader/src/main/resources/resources/default/configuration/furniture.yml b/bukkit/loader/src/main/resources/resources/default/configuration/furniture.yml index e8eb30a91..2816c5458 100644 --- a/bukkit/loader/src/main/resources/resources/default/configuration/furniture.yml +++ b/bukkit/loader/src/main/resources/resources/default/configuration/furniture.yml @@ -41,7 +41,7 @@ items: - 0,0,-0.1 0 - 1,0,-0.1 0 loot: - template: "default:loot_table/basic" + template: "default:loot_table/furniture" arguments: item: default:bench default:table_lamp: @@ -92,7 +92,7 @@ items: height: 0.4 interactive: true loot: - template: "default:loot_table/basic" + template: "default:loot_table/furniture" arguments: item: default:table_lamp default:wooden_chair: @@ -132,6 +132,6 @@ items: seats: - 0,0,-0.1 0 loot: - template: "default:loot_table/basic" + template: "default:loot_table/furniture" arguments: item: default:wooden_chair \ No newline at end of file diff --git a/bukkit/loader/src/main/resources/resources/default/configuration/templates.yml b/bukkit/loader/src/main/resources/resources/default/configuration/templates.yml index b2f321624..a281f7e41 100644 --- a/bukkit/loader/src/main/resources/resources/default/configuration/templates.yml +++ b/bukkit/loader/src/main/resources/resources/default/configuration/templates.yml @@ -968,6 +968,18 @@ templates#loot_tables: - type: item item: "{item}" + # drop the original furniture item or a fallback item + + # template: default:loot_table/furniture + # arguments: + # item: the fallback item + default:loot_table/furniture: + pools: + - rolls: 1 + entries: + - type: furniture_item + item: "{item}" + # drop with silk touch # template: default:loot_table/silk_touch 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 d611eec59..51fb36cd4 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 @@ -9,6 +9,7 @@ import net.momirealms.craftengine.bukkit.util.LocationUtils; 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.FurnitureExtraData; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.loot.LootTable; import net.momirealms.craftengine.core.plugin.context.ContextHolder; @@ -41,7 +42,7 @@ public final class CraftEngineFurniture { } /** - * Places furniture at the certain location + * Places furniture at certain location * * @param location location * @param furnitureId furniture to place @@ -55,7 +56,7 @@ public final class CraftEngineFurniture { } /** - * Places furniture at the certain location + * Places furniture at certain location * * @param location location * @param furnitureId furniture to place @@ -66,11 +67,11 @@ public final class CraftEngineFurniture { public static LoadedFurniture place(Location location, Key furnitureId, AnchorType anchorType) { CustomFurniture furniture = byId(furnitureId); if (furniture == null) return null; - return BukkitFurnitureManager.instance().place(furniture, location, anchorType, true); + return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true); } /** - * Places furniture at the certain location + * Places furniture at certain location * * @param location location * @param furniture furniture to place @@ -79,11 +80,11 @@ public final class CraftEngineFurniture { */ @NotNull public static LoadedFurniture place(Location location, CustomFurniture furniture, AnchorType anchorType) { - return BukkitFurnitureManager.instance().place(furniture, location, anchorType, true); + return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), true); } /** - * Places furniture at the certain location + * Places furniture at certain location * * @param location location * @param furnitureId furniture to place @@ -95,11 +96,11 @@ public final class CraftEngineFurniture { public static LoadedFurniture place(Location location, Key furnitureId, AnchorType anchorType, boolean playSound) { CustomFurniture furniture = byId(furnitureId); if (furniture == null) return null; - return BukkitFurnitureManager.instance().place(furniture, location, anchorType, playSound); + return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound); } /** - * Places furniture at the certain location + * Places furniture at certain location * * @param location location * @param furniture furniture to place @@ -109,7 +110,7 @@ public final class CraftEngineFurniture { */ @NotNull public static LoadedFurniture place(Location location, CustomFurniture furniture, AnchorType anchorType, boolean playSound) { - return BukkitFurnitureManager.instance().place(furniture, location, anchorType, playSound); + return BukkitFurnitureManager.instance().place(location, furniture, FurnitureExtraData.builder().anchorType(anchorType).build(), playSound); } /** @@ -222,7 +223,7 @@ public final class CraftEngineFurniture { } /** - * Removes furniture by providing a plugin furniture instance + * Removes furniture by providing furniture instance * * @param loadedFurniture loaded furniture * @param dropLoot whether to drop loots @@ -235,7 +236,7 @@ public final class CraftEngineFurniture { } /** - * Removes furniture by providing a plugin furniture instance + * Removes furniture by providing furniture instance * * @param loadedFurniture loaded furniture * @param player the player who removes the furniture @@ -251,7 +252,7 @@ public final class CraftEngineFurniture { } /** - * Removes furniture by providing a plugin furniture instance + * Removes furniture by providing furniture instance * * @param loadedFurniture loaded furniture * @param player the player who removes the furniture @@ -272,6 +273,7 @@ public final class CraftEngineFurniture { ContextHolder.Builder builder = ContextHolder.builder(); builder.withParameter(CommonParameters.LOCATION, vec3d); builder.withParameter(CommonParameters.WORLD, world); + builder.withOptionalParameter(CommonParameters.FURNITURE_ITEM, loadedFurniture.extraData().item().orElse(null)); if (player != null) { builder.withParameter(CommonParameters.PLAYER, player); //mark item builder.withOptionalParameter(CommonParameters.MAIN_HAND_ITEM, player.getItemInHand(InteractionHand.MAIN_HAND)); 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 ca76fb096..e94f4eaef 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 @@ -6,6 +6,7 @@ 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.util.EntityUtils; +import net.momirealms.craftengine.bukkit.util.LocationUtils; import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.entity.Billboard; import net.momirealms.craftengine.core.entity.ItemDisplayContext; @@ -20,7 +21,7 @@ import net.momirealms.craftengine.core.sound.SoundData; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.VersionHelper; -import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.WorldPosition; import org.bukkit.*; import org.bukkit.entity.*; import org.bukkit.event.HandlerList; @@ -31,13 +32,16 @@ import org.jetbrains.annotations.NotNull; import org.joml.Vector3f; import javax.annotation.Nullable; +import java.io.IOException; import java.nio.file.Path; import java.util.*; import java.util.concurrent.ConcurrentHashMap; public class BukkitFurnitureManager extends AbstractFurnitureManager { public static final NamespacedKey FURNITURE_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:furniture_id")); - public static final NamespacedKey FURNITURE_ANCHOR_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:anchor_type")); + // DEPRECATED + // public static final NamespacedKey FURNITURE_ANCHOR_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:anchor_type")); + public static final NamespacedKey FURNITURE_EXTRA_DATA_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:furniture_extra_data")); public static final NamespacedKey FURNITURE_SEAT_BASE_ENTITY_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_to_base_entity")); public static final NamespacedKey FURNITURE_SEAT_VECTOR_3F_KEY = Objects.requireNonNull(NamespacedKey.fromString("craftengine:seat_vector")); public static final NamespacedKey FURNITURE_COLLISION = Objects.requireNonNull(NamespacedKey.fromString("craftengine:collision")); @@ -66,19 +70,23 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { } @Override - public Furniture place(CustomFurniture furniture, Vec3d vec3d, net.momirealms.craftengine.core.world.World world, AnchorType anchorType, boolean playSound) { - return this.place(furniture, new Location((World) world.platformWorld(), vec3d.x(), vec3d.y(), vec3d.z()), anchorType, playSound); + public Furniture place(WorldPosition position, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) { + return this.place(LocationUtils.toLocation(position), furniture, extraData, playSound); } - public LoadedFurniture place(CustomFurniture furniture, Location location, AnchorType anchorType, boolean playSound) { - if (furniture.isAllowedPlacement(anchorType)) { - anchorType = furniture.getAnyPlacement(); + public LoadedFurniture place(Location location, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound) { + Optional optionalAnchorType = extraData.anchorType(); + if (optionalAnchorType.isEmpty() || !furniture.isAllowedPlacement(optionalAnchorType.get())) { + extraData.anchorType(furniture.getAnyPlacement()); } - AnchorType finalAnchorType = anchorType; 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()); - display.getPersistentDataContainer().set(BukkitFurnitureManager.FURNITURE_ANCHOR_KEY, PersistentDataType.STRING, finalAnchorType.name()); + 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) { @@ -224,9 +232,6 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { handleCollisionEntityLoadOnEntitiesLoad(interaction); } else if (entity instanceof Boat boat) { handleCollisionEntityLoadOnEntitiesLoad(boat); - } else if (entity instanceof Shulker shulker) { - // TODO 移除这一行,预计过一个月 - handleCollisionEntityLoadOnEntitiesLoad(shulker); } } } @@ -301,7 +306,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { boolean preventChange = FastNMS.INSTANCE.isPreventingStatusUpdates(location.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); if (above1_20_1) { if (!preventChange) { - LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(display, customFurniture)); + LoadedFurniture furniture = addNewFurniture(display, customFurniture); furniture.initializeColliders(); for (Player player : display.getTrackedPlayers()) { this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds())); @@ -309,7 +314,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { } } } else { - LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(display, customFurniture)); + LoadedFurniture furniture = addNewFurniture(display, customFurniture); for (Player player : display.getTrackedPlayers()) { this.plugin.adapt(player).entityPacketHandlers().computeIfAbsent(furniture.baseEntityId(), k -> new FurniturePacketHandler(furniture.fakeEntityIds())); this.plugin.networkManager().sendPacket(player, furniture.spawnPacket(player)); @@ -373,7 +378,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { CustomFurniture customFurniture = optionalFurniture.get(); LoadedFurniture previous = this.furnitureByRealEntityId.get(display.getEntityId()); if (previous != null) return; - LoadedFurniture furniture = addNewFurniture(display, customFurniture, getAnchorType(display, customFurniture)); + LoadedFurniture furniture = addNewFurniture(display, customFurniture); furniture.initializeColliders(); // safely do it here } } @@ -394,24 +399,37 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { collisionEntity.remove(); } - private AnchorType getAnchorType(Entity baseEntity, CustomFurniture furniture) { - String anchorType = baseEntity.getPersistentDataContainer().get(FURNITURE_ANCHOR_KEY, PersistentDataType.STRING); - if (anchorType != null) { - try { - AnchorType unverified = AnchorType.valueOf(anchorType); - if (furniture.isAllowedPlacement(unverified)) { - return unverified; - } - } catch (IllegalArgumentException ignored) { - } - } - AnchorType anchorTypeEnum = furniture.getAnyPlacement(); - baseEntity.getPersistentDataContainer().set(FURNITURE_ANCHOR_KEY, PersistentDataType.STRING, anchorTypeEnum.name()); - return anchorTypeEnum; + 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 LoadedFurniture addNewFurniture(ItemDisplay display, CustomFurniture furniture, AnchorType anchorType) { - LoadedFurniture loadedFurniture = new LoadedFurniture(display, furniture, anchorType); +// private AnchorType getAnchorType(Entity baseEntity, CustomFurniture furniture) { +// String anchorType = baseEntity.getPersistentDataContainer().get(FURNITURE_ANCHOR_KEY, PersistentDataType.STRING); +// if (anchorType != null) { +// try { +// AnchorType unverified = AnchorType.valueOf(anchorType); +// if (furniture.isAllowedPlacement(unverified)) { +// return unverified; +// } +// } catch (IllegalArgumentException ignored) { +// } +// } +// AnchorType anchorTypeEnum = furniture.getAnyPlacement(); +// baseEntity.getPersistentDataContainer().set(FURNITURE_ANCHOR_KEY, PersistentDataType.STRING, anchorTypeEnum.name()); +// return anchorTypeEnum; +// } + + private synchronized LoadedFurniture 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); + } + LoadedFurniture loadedFurniture = new LoadedFurniture(display, furniture, extraData); this.furnitureByRealEntityId.put(loadedFurniture.baseEntityId(), loadedFurniture); for (int entityId : loadedFurniture.entityIds()) { this.furnitureByEntityId.put(entityId, loadedFurniture); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java index ac8ba908a..21d79d9ab 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/LoadedFurniture.java @@ -31,6 +31,7 @@ public class LoadedFurniture implements Furniture { private final Key id; private final CustomFurniture furniture; private final AnchorType anchorType; + private final FurnitureExtraData extraData; // location private final Location location; // base entity @@ -54,10 +55,11 @@ public class LoadedFurniture implements Furniture { public LoadedFurniture(Entity baseEntity, CustomFurniture furniture, - AnchorType anchorType) { + FurnitureExtraData extraData) { this.id = furniture.id(); + this.extraData = extraData; this.baseEntityId = baseEntity.getEntityId(); - this.anchorType = anchorType; + this.anchorType = extraData.anchorType().orElse(furniture.getAnyPlacement()); this.location = baseEntity.getLocation(); this.baseEntity = new WeakReference<>(baseEntity); this.furniture = furniture; @@ -305,6 +307,11 @@ public class LoadedFurniture implements Furniture { spawnSeatEntityForPlayer((Player) player.platformPlayer(), seat); } + @Override + public FurnitureExtraData extraData() { + return this.extraData; + } + public void spawnSeatEntityForPlayer(org.bukkit.entity.Player player, Seat seat) { Location location = this.calculateSeatLocation(seat); Entity seatEntity = seat.limitPlayerRotation() ? diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index fe46abf8e..6433d7fd0 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.bukkit.item; +import com.saicone.rtag.item.ItemTagStream; import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior; import net.momirealms.craftengine.bukkit.item.behavior.BoneMealItemBehavior; import net.momirealms.craftengine.bukkit.item.behavior.BucketItemBehavior; @@ -163,6 +164,11 @@ public class BukkitItemManager extends AbstractItemManager { HandlerList.unregisterAll(this.debugStickListener); } + @Override + public Item fromByteArray(byte[] bytes) { + return this.factory.wrap(ItemTagStream.INSTANCE.fromBytes(bytes)); + } + @Override public ConfigParser parser() { return this.itemParser; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java index 75f692f57..7a6e7c0a3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentItemWrapper.java @@ -71,7 +71,7 @@ public class ComponentItemWrapper implements ItemWrapper { @Override public ItemWrapper copyWithCount(int count) { - ItemStack copied = item.clone(); + ItemStack copied = this.item.clone(); copied.setAmount(count); return new ComponentItemWrapper(copied); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentTypes.java index 904cac448..d755ab11b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentTypes.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ComponentTypes.java @@ -25,6 +25,7 @@ public class ComponentTypes { public static final Object REPAIR_COST = getComponentType(ComponentKeys.REPAIR_COST); public static final Object CUSTOM_DATA = getComponentType(ComponentKeys.CUSTOM_DATA); public static final Object PROFILE = getComponentType(ComponentKeys.PROFILE); + public static final Object DYED_COLOR = getComponentType(ComponentKeys.DYED_COLOR); private ComponentTypes() {} 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 ff062ebec..d4d8c2b0b 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 @@ -10,6 +10,7 @@ import net.momirealms.craftengine.bukkit.util.DirectionUtils; import net.momirealms.craftengine.bukkit.util.EventUtils; 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.HitBox; import net.momirealms.craftengine.core.entity.player.InteractionResult; import net.momirealms.craftengine.core.entity.player.Player; @@ -126,7 +127,15 @@ public class FurnitureItemBehavior extends ItemBehavior { return InteractionResult.FAIL; } - LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().place(customFurniture, furnitureLocation.clone(), anchorType, false); + Item item = context.getItem(); + + LoadedFurniture loadedFurniture = BukkitFurnitureManager.instance().place( + furnitureLocation.clone(), customFurniture, + FurnitureExtraData.builder() + .item(item.copyWithCount(1)) + .anchorType(anchorType) + .dyedColor(item.dyedColor().orElse(-1)) + .build(), false); FurniturePlaceEvent placeEvent = new FurniturePlaceEvent(bukkitPlayer, loadedFurniture, furnitureLocation, context.getHand()); if (EventUtils.fireAndCheckCancel(placeEvent)) { @@ -135,7 +144,6 @@ public class FurnitureItemBehavior extends ItemBehavior { } if (!player.isCreativeMode()) { - Item item = context.getItem(); item.count(item.count() - 1); item.load(); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java index 853271e93..0dd515534 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.bukkit.item.factory; import com.google.gson.JsonElement; +import com.saicone.rtag.item.ItemTagStream; import net.momirealms.craftengine.bukkit.util.ItemTags; import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.item.EquipmentData; @@ -46,6 +47,11 @@ public abstract class BukkitItemFactory> extend } } + @Override + protected byte[] toByteArray(W item) { + return ItemTagStream.INSTANCE.toBytes(item.getItem()); + } + @Override protected boolean isBlockItem(W item) { return item.getItem().getType().isBlock(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java index f7b5e76ff..2cf775754 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java @@ -244,6 +244,26 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory dyedColor(ComponentItemWrapper item) { + if (!item.hasComponent(ComponentTypes.DYED_COLOR)) return Optional.empty(); + return Optional.ofNullable( + (Integer) ComponentType.encodeJava( + ComponentTypes.DYED_COLOR, + item.getComponent(ComponentTypes.DYED_COLOR) + ).orElse(null) + ); + } + + @Override + protected void dyedColor(ComponentItemWrapper item, Integer color) { + if (color == null) { + item.resetComponent(ComponentTypes.DYED_COLOR); + } else { + item.setJavaComponent(ComponentTypes.DYED_COLOR, color); + } + } + @Override protected Optional maxDamage(ComponentItemWrapper item) { if (!item.hasComponent(ComponentTypes.MAX_DAMAGE)) return Optional.of((int) item.getItem().getType().getMaxDurability()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java index 3dd72fe51..dbf97a69d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java @@ -152,6 +152,21 @@ public class UniversalItemFactory extends BukkitItemFactory { item.set(damage, "Damage"); } + @Override + protected Optional dyedColor(LegacyItemWrapper item) { + if (!item.hasTag("display", "color")) return Optional.empty(); + return Optional.of(item.get("display", "color")); + } + + @Override + protected void dyedColor(LegacyItemWrapper item, Integer color) { + if (color == null) { + item.remove("display", "color"); + } else { + item.set(color, "display", "color"); + } + } + @Override protected Optional maxDamage(LegacyItemWrapper item) { return Optional.of((int) item.getItem().getType().getMaxDurability()); 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 df390ccf2..70914aa49 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 @@ -1,5 +1,6 @@ package net.momirealms.craftengine.bukkit.plugin.command.feature; +import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.BukkitFurnitureManager; import net.momirealms.craftengine.bukkit.plugin.command.BukkitCommandFeature; import net.momirealms.craftengine.bukkit.util.KeyUtils; @@ -55,7 +56,7 @@ public class DebugSpawnFurnitureCommand extends BukkitCommandFeature { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LocationUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LocationUtils.java index 01c719118..1dbfa8d8c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LocationUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/LocationUtils.java @@ -3,13 +3,19 @@ package net.momirealms.craftengine.bukkit.util; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.WorldPosition; import org.bukkit.Location; +import org.bukkit.World; import org.jetbrains.annotations.NotNull; public class LocationUtils { private LocationUtils() {} + public static Location toLocation(WorldPosition position) { + return new Location((World) position.world().platformWorld(), position.position().x(), position.position().y(), position.position().z()); + } + public static Vec3d toVec3d(Location loc) { return new Vec3d(loc.getX(), loc.getY(), loc.getZ()); } 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 42998e48b..249a5872d 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 @@ -46,4 +46,6 @@ public interface Furniture { boolean hasExternalModel(); void spawnSeatEntityForPlayer(Player player, Seat seat); + + FurnitureExtraData extraData(); } 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/FurnitureExtraData.java new file mode 100644 index 000000000..7da9d6c4e --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureExtraData.java @@ -0,0 +1,86 @@ +package net.momirealms.craftengine.core.entity.furniture; + +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.sparrow.nbt.CompoundTag; +import net.momirealms.sparrow.nbt.NBT; + +import java.io.IOException; +import java.util.Optional; + +public class FurnitureExtraData { + public static final String ITEM = "item"; + public static final String DYED_COLOR = "dyed_color"; + public static final String ANCHOR_TYPE = "anchor_type"; + + private final CompoundTag data; + + public FurnitureExtraData(CompoundTag data) { + this.data = data; + } + + public Optional> item() { + byte[] data = this.data.getByteArray(ITEM); + if (data == null) return Optional.empty(); + return Optional.of(CraftEngine.instance().itemManager().fromByteArray(data)); + } + + public Optional dyedColor() { + if (this.data.containsKey(DYED_COLOR)) return Optional.of(this.data.getInt(DYED_COLOR)); + return Optional.empty(); + } + + 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) { + this.data.putInt(ANCHOR_TYPE, type.getId()); + return this; + } + + public static Builder builder() { + return new Builder(); + } + + public static FurnitureExtraData fromBytes(final byte[] data) throws IOException { + return new FurnitureExtraData(NBT.fromBytes(data)); + } + + public static byte[] toBytes(final FurnitureExtraData 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(int color) { + if (color < 0) return this; + this.data.putInt(DYED_COLOR, color); + 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/FurnitureManager.java b/core/src/main/java/net/momirealms/craftengine/core/entity/furniture/FurnitureManager.java index 7dd60f33b..50d4787c1 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 @@ -4,8 +4,7 @@ import net.momirealms.craftengine.core.entity.AbstractEntity; import net.momirealms.craftengine.core.plugin.Manageable; import net.momirealms.craftengine.core.plugin.config.ConfigParser; import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.world.Vec3d; -import net.momirealms.craftengine.core.world.World; +import net.momirealms.craftengine.core.world.WorldPosition; import org.incendo.cloud.suggestion.Suggestion; import javax.annotation.Nullable; @@ -21,7 +20,7 @@ public interface FurnitureManager extends Manageable { Collection cachedSuggestions(); - Furniture place(CustomFurniture furniture, Vec3d vec3d, World world, AnchorType anchorType, boolean playSound); + Furniture place(WorldPosition position, CustomFurniture furniture, FurnitureExtraData extraData, boolean playSound); Optional furnitureById(Key id); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java index cd8991160..70fbf6d8f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java @@ -93,6 +93,17 @@ public class AbstractItem, I> implements Item { return this.factory.maxDamage(this.item); } + @Override + public Item dyedColor(Integer data) { + this.factory.dyedColor(this.item, data); + return this; + } + + @Override + public Optional dyedColor() { + return this.factory.dyedColor(this.item); + } + @SuppressWarnings("unchecked") @Override public Optional> getCustomItem() { @@ -358,4 +369,9 @@ public class AbstractItem, I> implements Item { public void merge(Item another) { this.factory.merge(this.item, (W) ((AbstractItem) another).item); } + + @Override + public byte[] toByteArray() { + return this.factory.toByteArray(this.item); + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ComponentKeys.java b/core/src/main/java/net/momirealms/craftengine/core/item/ComponentKeys.java index 30e2be9ce..597639121 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ComponentKeys.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ComponentKeys.java @@ -22,4 +22,5 @@ public class ComponentKeys { public static final Key REPAIR_COST = Key.of("minecraft", "repair_cost"); public static final Key CUSTOM_DATA = Key.of("minecraft", "custom_data"); public static final Key PROFILE = Key.of("minecraft", "profile"); + public static final Key DYED_COLOR = Key.of("minecraft", "dyed_color"); } 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 1d12dc775..50786ace9 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 @@ -56,6 +56,10 @@ public interface Item { Optional maxDamage(); + Item dyedColor(Integer data); + + Optional dyedColor(); + Item customName(String displayName); Optional customName(); @@ -145,4 +149,6 @@ public interface Item { Item mergeCopy(Item another); void merge(Item another); + + byte[] toByteArray(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java index c747a5131..eb3c9fada 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java @@ -83,6 +83,10 @@ public abstract class ItemFactory, I> { protected abstract void damage(W item, Integer damage); + protected abstract Optional dyedColor(W item); + + protected abstract void dyedColor(W item, Integer color); + protected abstract Optional maxDamage(W item); protected abstract void maxDamage(W item, Integer damage); @@ -138,4 +142,7 @@ public abstract class ItemFactory, I> { protected abstract void equippable(W item, EquipmentData data); protected abstract Optional equippable(W item); + + protected abstract byte[] toByteArray(W item); + } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java index c02f1aa54..a5320e710 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java @@ -41,6 +41,8 @@ public interface ItemManager extends Manageable, ModelGenerator { Item wrap(T itemStack); + Item fromByteArray(byte[] bytes); + Collection items(); Key itemId(T itemStack); diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/entry/FurnitureItemLootEntryContainer.java b/core/src/main/java/net/momirealms/craftengine/core/loot/entry/FurnitureItemLootEntryContainer.java new file mode 100644 index 000000000..b16ed84f8 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/entry/FurnitureItemLootEntryContainer.java @@ -0,0 +1,58 @@ +package net.momirealms.craftengine.core.loot.entry; + +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.loot.LootConditions; +import net.momirealms.craftengine.core.loot.LootContext; +import net.momirealms.craftengine.core.loot.function.LootFunction; +import net.momirealms.craftengine.core.loot.function.LootFunctions; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.parameter.CommonParameters; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.function.Consumer; + +public class FurnitureItemLootEntryContainer extends SingleItemLootEntryContainer { + public static final Factory FACTORY = new Factory<>(); + private final boolean hasFallback; + + protected FurnitureItemLootEntryContainer(@Nullable Key item, List> conditions, List> lootFunctions, int weight, int quality) { + super(item, conditions, lootFunctions, weight, quality); + this.hasFallback = item != null; + } + + @Override + public Key type() { + return LootEntryContainers.FURNITURE_ITEM; + } + + @SuppressWarnings("unchecked") + @Override + protected void createItem(Consumer> lootConsumer, LootContext context) { + Optional> optionalItem = context.getOptionalParameter(CommonParameters.FURNITURE_ITEM); + if (optionalItem.isPresent()) { + lootConsumer.accept((Item) optionalItem.get()); + } else if (this.hasFallback) { + super.createItem(lootConsumer, context); + } + } + + public static class Factory implements LootEntryContainerFactory { + @SuppressWarnings("unchecked") + @Override + public LootEntryContainer create(Map arguments) { + Key item = Optional.ofNullable(arguments.get("item")).map(String::valueOf).map(Key::of).orElse(null); + int weight = ResourceConfigUtils.getAsInt(arguments.getOrDefault("weight", 1), "weight"); + int quality = ResourceConfigUtils.getAsInt(arguments.getOrDefault("quality", 0), "quality"); + List> conditions = Optional.ofNullable(arguments.get("conditions")) + .map(it -> LootConditions.fromMapList((List>) it)) + .orElse(Collections.emptyList()); + List> functions = Optional.ofNullable(arguments.get("functions")) + .map(it -> (List>) new ArrayList>(LootFunctions.fromMapList((List>) it))) + .orElse(Collections.emptyList()); + return new FurnitureItemLootEntryContainer<>(item, conditions, functions, weight, quality); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/loot/entry/LootEntryContainers.java b/core/src/main/java/net/momirealms/craftengine/core/loot/entry/LootEntryContainers.java index 5d44629dc..2d27fb6f1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/loot/entry/LootEntryContainers.java +++ b/core/src/main/java/net/momirealms/craftengine/core/loot/entry/LootEntryContainers.java @@ -16,12 +16,14 @@ import java.util.Map; public class LootEntryContainers { public static final Key ALTERNATIVES = Key.from("craftengine:alternatives"); public static final Key ITEM = Key.from("craftengine:item"); + public static final Key FURNITURE_ITEM = Key.from("craftengine:furniture_item"); public static final Key EXP = Key.from("craftengine:exp"); static { register(ALTERNATIVES, AlternativesLootEntryContainer.FACTORY); register(ITEM, SingleItemLootEntryContainer.FACTORY); register(EXP, ExpLootEntryContainer.FACTORY); + register(FURNITURE_ITEM, FurnitureItemLootEntryContainer.FACTORY); } public static void register(Key key, LootEntryContainerFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/CommonParameters.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/CommonParameters.java index e84c45315..615aa93bb 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/CommonParameters.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/parameter/CommonParameters.java @@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.plugin.context.parameter; import net.momirealms.craftengine.core.block.ImmutableBlockState; import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.context.ContextKey; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.World; @@ -13,6 +14,7 @@ public final class CommonParameters { public static final ContextKey LAST_RANDOM = ContextKey.of("last_random"); public static final ContextKey LOCATION = ContextKey.of("location"); public static final ContextKey WORLD = ContextKey.of("world"); + public static final ContextKey> FURNITURE_ITEM = ContextKey.of("furniture_item"); public static final ContextKey FALLING_BLOCK = ContextKey.of("falling_block"); public static final ContextKey EXPLOSION_RADIUS = ContextKey.of("explosion_radius"); public static final ContextKey PLAYER = ContextKey.of("player"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/WorldPosition.java b/core/src/main/java/net/momirealms/craftengine/core/world/WorldPosition.java new file mode 100644 index 000000000..b2dc01529 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/world/WorldPosition.java @@ -0,0 +1,19 @@ +package net.momirealms.craftengine.core.world; + +public class WorldPosition { + private final World world; + private final Position position; + + public WorldPosition(Position position, World world) { + this.position = position; + this.world = world; + } + + public Position position() { + return position; + } + + public World world() { + return world; + } +} diff --git a/gradle.properties b/gradle.properties index 22e20eb06..313e0850e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,7 @@ asm_version=9.8 asm_commons_version=9.8 jar_relocator_version=1.7 adventure_bundle_version=4.21.0 -adventure_platform_version=4.3.4 +adventure_platform_version=4.4.0 cloud_core_version=2.0.0 cloud_services_version=2.0.0 cloud_brigadier_version=2.0.0-beta.10