From 054444b6588a18ed17e08b2e79031e4844725728 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sat, 6 Dec 2025 02:32:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=B6=E5=85=B7=E5=8F=91?= =?UTF-8?q?=E5=85=89=E5=92=8C=E7=89=A9=E5=93=81=E5=8F=91=E5=85=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../element/ItemDisplayFurnitureElement.java | 13 +- .../ItemDisplayFurnitureElementConfig.java | 23 ++- .../bukkit/plugin/BukkitCraftEngine.java | 3 + .../handler/CommonItemPacketHandler.java | 142 +++++++++++------- .../bukkit/CraftBukkitReflections.java | 8 + .../reflection/minecraft/CoreReflections.java | 7 + .../bukkit/util/EntityDataUtils.java | 1 + .../bukkit/world/score/BukkitTeamManager.java | 76 ++++++++++ .../craftengine/core/entity/Glowing.java | 10 ++ .../furniture/AbstractFurnitureManager.java | 10 ++ .../core/item/AbstractItemManager.java | 3 + .../craftengine/core/plugin/CraftEngine.java | 20 +++ .../craftengine/core/plugin/Plugin.java | 9 ++ .../core/world/score/TeamManager.java | 10 ++ gradle.properties | 2 +- 15 files changed, 275 insertions(+), 62 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/score/BukkitTeamManager.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/entity/Glowing.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/world/score/TeamManager.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElement.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElement.java index ae884d0c7..cbd6a4c05 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElement.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElement.java @@ -4,10 +4,12 @@ import it.unimi.dsi.fastutil.ints.IntArrayList; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; +import net.momirealms.craftengine.bukkit.world.score.BukkitTeamManager; import net.momirealms.craftengine.core.entity.furniture.Furniture; import net.momirealms.craftengine.core.entity.furniture.FurnitureColorSource; import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement; import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.util.LegacyChatFormatter; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.WorldPosition; @@ -21,6 +23,7 @@ public class ItemDisplayFurnitureElement implements FurnitureElement { private final int entityId; private final Object despawnPacket; private final FurnitureColorSource colorSource; + private final LegacyChatFormatter glowColor; public ItemDisplayFurnitureElement(Furniture furniture, ItemDisplayFurnitureElementConfig config) { this.config = config; @@ -30,18 +33,26 @@ public class ItemDisplayFurnitureElement implements FurnitureElement { this.position = new WorldPosition(furniturePos.world, position.x, position.y, position.z, furniturePos.xRot, furniturePos.yRot); this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(entityId); }}); this.colorSource = furniture.dataAccessor.getColorSource(); + this.glowColor = config.glowColor; } @Override public void show(Player player) { + UUID uuid = UUID.randomUUID(); player.sendPacket(FastNMS.INSTANCE.constructor$ClientboundBundlePacket(List.of( FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( - this.entityId, UUID.randomUUID(), + this.entityId, uuid, this.position.x, this.position.y, this.position.z, 0, this.position.yRot, MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0 ), FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadata.apply(player, this.colorSource)) )), false); + if (this.glowColor != null) { + Object team = BukkitTeamManager.instance().getTeamByColor(this.glowColor); + if (team != null) { + FastNMS.INSTANCE.method$ClientboundSetPlayerTeamPacket$createMultiplePlayerPacket(team, List.of(uuid.toString()), true); + } + } } @Override diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java index caa972e9b..8e6a16aae 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/element/ItemDisplayFurnitureElementConfig.java @@ -1,8 +1,10 @@ package net.momirealms.craftengine.bukkit.entity.furniture.element; import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData; import net.momirealms.craftengine.bukkit.entity.data.ItemDisplayEntityData; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.core.entity.Glowing; import net.momirealms.craftengine.core.entity.display.Billboard; import net.momirealms.craftengine.core.entity.display.ItemDisplayContext; import net.momirealms.craftengine.core.entity.furniture.Furniture; @@ -14,9 +16,11 @@ 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.LegacyChatFormatter; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.joml.Quaternionf; import org.joml.Vector3f; @@ -26,7 +30,7 @@ import java.util.Map; import java.util.Optional; import java.util.function.BiFunction; -public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig { +public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig, Glowing { public static final Factory FACTORY = new Factory(); public final BiFunction> metadata; public final Key itemId; @@ -41,6 +45,7 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig public final float shadowRadius; public final float shadowStrength; public final boolean applyDyedColor; + public final LegacyChatFormatter glowColor; public ItemDisplayFurnitureElementConfig(Key itemId, Vector3f scale, @@ -53,7 +58,8 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig Billboard billboard, float shadowRadius, float shadowStrength, - boolean applyDyedColor) { + boolean applyDyedColor, + @Nullable LegacyChatFormatter glowColor) { this.scale = scale; this.position = position; this.translation = translation; @@ -66,6 +72,7 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig this.shadowStrength = shadowStrength; this.applyDyedColor = applyDyedColor; this.itemId = itemId; + this.glowColor = glowColor; BiFunction> itemFunction = (player, colorSource) -> { Item wrappedItem = BukkitItemManager.instance().createWrappedItem(itemId, player); if (applyDyedColor && colorSource != null && wrappedItem != null) { @@ -82,6 +89,9 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig }; this.metadata = (player, source) -> { List dataValues = new ArrayList<>(); + if (glowColor != null) { + BaseEntityData.SharedFlags.addEntityData((byte) 0x40, dataValues); + } ItemDisplayEntityData.DisplayedItem.addEntityData(itemFunction.apply(player, source).getLiteralObject(), dataValues); ItemDisplayEntityData.Scale.addEntityData(this.scale, dataValues); ItemDisplayEntityData.RotationLeft.addEntityData(this.rotation, dataValues); @@ -142,6 +152,12 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig return this.itemId; } + @Nullable + @Override + public LegacyChatFormatter glowColor() { + return this.glowColor; + } + @Override public ItemDisplayFurnitureElement create(@NotNull Furniture furniture) { return new ItemDisplayFurnitureElement(furniture, this); @@ -165,7 +181,8 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig ResourceConfigUtils.getAsEnum(arguments.get("billboard"), Billboard.class, Billboard.FIXED), ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-radius", 0f), "shadow-radius"), ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-strength", 1f), "shadow-strength"), - applyDyedColor + applyDyedColor, + ResourceConfigUtils.getAsEnum(arguments.get("glow-color"), LegacyChatFormatter.class, null) ); } } 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 e141aa000..df1f0b1d5 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 @@ -27,6 +27,7 @@ import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.sound.BukkitSoundManager; import net.momirealms.craftengine.bukkit.util.EventUtils; import net.momirealms.craftengine.bukkit.world.BukkitWorldManager; +import net.momirealms.craftengine.bukkit.world.score.BukkitTeamManager; import net.momirealms.craftengine.core.item.ItemManager; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.classpath.ClassPathAppender; @@ -192,6 +193,8 @@ public class BukkitCraftEngine extends CraftEngine { super.seatManager = new BukkitSeatManager(this); // 初始化家具管理器 super.furnitureManager = new BukkitFurnitureManager(this); + // 初始化队伍管理器 + super.teamManager = new BukkitTeamManager(this); // 注册默认的parser this.registerDefaultParsers(); // 完成加载 diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/CommonItemPacketHandler.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/CommonItemPacketHandler.java index 3df058747..b835c2c8f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/CommonItemPacketHandler.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/handler/CommonItemPacketHandler.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.bukkit.plugin.network.handler; import net.kyori.adventure.text.Component; +import net.momirealms.craftengine.bukkit.entity.data.BaseEntityData; import net.momirealms.craftengine.bukkit.entity.data.ItemEntityData; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; @@ -8,9 +9,11 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.util.ComponentUtils; import net.momirealms.craftengine.bukkit.util.EntityDataUtils; +import net.momirealms.craftengine.bukkit.world.score.BukkitTeamManager; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemSettings; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.context.ContextHolder; @@ -19,15 +22,14 @@ import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent; import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler; -import net.momirealms.craftengine.core.plugin.text.component.ComponentProvider; import net.momirealms.craftengine.core.plugin.text.minimessage.CustomTagResolver; import net.momirealms.craftengine.core.util.AdventureHelper; import net.momirealms.craftengine.core.util.ArrayUtils; import net.momirealms.craftengine.core.util.FriendlyByteBuf; +import net.momirealms.craftengine.core.util.LegacyChatFormatter; import org.bukkit.inventory.ItemStack; import java.util.List; -import java.util.Map; import java.util.Optional; public class CommonItemPacketHandler implements EntityPacketHandler { @@ -42,71 +44,97 @@ public class CommonItemPacketHandler implements EntityPacketHandler { boolean changed = false; List packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf); Component nameToShow = null; + LegacyChatFormatter glowColor = null; for (int i = 0; i < packedItems.size(); i++) { Object packedItem = packedItems.get(i); int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); - if (entityDataId != EntityDataUtils.UNSAFE_ITEM_DATA_ID) continue; - Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); + if (entityDataId == EntityDataUtils.UNSAFE_ITEM_DATA_ID) { + Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); - // 可能是其他插件导致的问题 - if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) { - long time = System.currentTimeMillis(); - if (time - lastWarningTime > 5000) { - BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user; - CraftEngine.instance().logger().severe("An issue was detected while applying item-related entity data for '" + serverPlayer.name() + - "'. Please execute the command '/ce debug entity-id " + serverPlayer.world().name() + " " + id + "' and provide a screenshot for further investigation."); - lastWarningTime = time; + // 可能是其他插件导致的问题 + if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) { + long time = System.currentTimeMillis(); + if (time - lastWarningTime > 5000) { + BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user; + CraftEngine.instance().logger().severe("An issue was detected while applying item-related entity data for '" + serverPlayer.name() + + "'. Please execute the command '/ce debug entity-id " + serverPlayer.world().name() + " " + id + "' and provide a screenshot for further investigation."); + lastWarningTime = time; + } + continue; + } + + ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack); + + // 转换为客户端侧物品 + Optional optional = BukkitItemManager.instance().s2c(itemStack, user); + if (optional.isPresent()) { + changed = true; + itemStack = optional.get(); + Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); + packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack))); + } + + // 处理 drop-display 物品设置 + // 一定要处理经历过客户端侧组件修改的物品 + Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); + Optional> optionalCustomItem = wrappedItem.getCustomItem(); + String showName = null; + if (optionalCustomItem.isPresent()) { + ItemSettings settings = optionalCustomItem.get().settings(); + showName = settings.dropDisplay(); + glowColor = settings.glowColor(); + } else if (Config.enableDefaultDropDisplay()) { + showName = Config.defaultDropDisplayFormat(); + } + + // 如果设定了自定义展示名 + if (showName != null) { + PlayerOptionalContext context = NetworkTextReplaceContext.of(user, ContextHolder.builder() + .withParameter(DirectContextParameters.COUNT, itemStack.getAmount())); + Optional optionalHoverComponent = wrappedItem.hoverNameComponent(); + Component hoverComponent; + if (optionalHoverComponent.isPresent()) { + hoverComponent = optionalHoverComponent.get(); + } else { + hoverComponent = Component.translatable(itemStack.translationKey()); + } + // 展示名称为空,则显示其hover name + if (showName.isEmpty()) { + nameToShow = hoverComponent; + } + // 显示自定义格式的名字 + else { + nameToShow = AdventureHelper.miniMessage().deserialize( + showName, + ArrayUtils.appendElementToArrayTail(context.tagResolvers(), new CustomTagResolver("name", hoverComponent)) + ); + } } - continue; } - - ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack); - - // 转换为客户端侧物品 - Optional optional = BukkitItemManager.instance().s2c(itemStack, user); - if (optional.isPresent()) { + } + if (glowColor != null) { + Object teamByColor = BukkitTeamManager.instance().getTeamByColor(glowColor); + if (teamByColor != null) { changed = true; - itemStack = optional.get(); - Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); - packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack))); - } - - // 处理 drop-display 物品设置 - // 一定要处理经历过客户端侧组件修改的物品 - Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); - Optional> optionalCustomItem = wrappedItem.getCustomItem(); - String showName = null; - if (optionalCustomItem.isPresent()) { - showName = optionalCustomItem.get().settings().dropDisplay(); - } else if (Config.enableDefaultDropDisplay()) { - showName = Config.defaultDropDisplayFormat(); - } - - // 如果设定了自定义展示名 - if (showName != null) { - PlayerOptionalContext context = NetworkTextReplaceContext.of(user, ContextHolder.builder() - .withParameter(DirectContextParameters.COUNT, itemStack.getAmount())); - Optional optionalHoverComponent = wrappedItem.hoverNameComponent(); - Component hoverComponent; - if (optionalHoverComponent.isPresent()) { - hoverComponent = optionalHoverComponent.get(); - } else { - hoverComponent = Component.translatable(itemStack.translationKey()); + outer: { + for (int i = 0; i < packedItems.size(); i++) { + Object packedItem = packedItems.get(i); + int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); + if (entityDataId == BaseEntityData.SharedFlags.id()) { + byte flags = (Byte) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); + flags |= (byte) 0x40; + packedItems.set(i, BaseEntityData.SharedFlags.createEntityData(flags)); + break outer; + } + } + packedItems.add(BaseEntityData.SharedFlags.createEntityData((byte) 0x40)); } - // 展示名称为空,则显示其hover name - if (showName.isEmpty()) { - nameToShow = hoverComponent; - } - // 显示自定义格式的名字 - else { - nameToShow = AdventureHelper.miniMessage().deserialize( - showName, - ArrayUtils.appendElementToArrayTail(context.tagResolvers(), new CustomTagResolver("name", hoverComponent)) - ); + Object entityLookup = FastNMS.INSTANCE.method$ServerLevel$getEntityLookup(user.clientSideWorld().serverWorld()); + Object entity = FastNMS.INSTANCE.method$EntityLookup$get(entityLookup, id); + if (entity != null) { + user.sendPacket(FastNMS.INSTANCE.method$ClientboundSetPlayerTeamPacket$createMultiplePlayerPacket(teamByColor, List.of(FastNMS.INSTANCE.method$Entity$getUUID(entity).toString()), true), false); } } - - break; } // 添加自定义显示名 if (nameToShow != null) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/bukkit/CraftBukkitReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/bukkit/CraftBukkitReflections.java index 06546717e..e330f24ab 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/bukkit/CraftBukkitReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/bukkit/CraftBukkitReflections.java @@ -392,4 +392,12 @@ public final class CraftBukkitReflections { public static final Field field$MinecraftMerchant$title = requireNonNull( ReflectionUtils.getDeclaredField(clazz$CraftMerchantCustom$MinecraftMerchant, CoreReflections.clazz$Component, 0) ); + + public static final Class clazz$CraftTeam = requireNonNull( + ReflectionUtils.getClazz(BukkitReflectionUtils.assembleCBClass("scoreboard.CraftTeam")) + ); + + public static final Field field$CraftTeam$team = requireNonNull( + ReflectionUtils.getDeclaredField(clazz$CraftTeam, CoreReflections.clazz$PlayerTeam, 0) + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java index 5d4d7286b..661b445e0 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java @@ -4638,4 +4638,11 @@ public final class CoreReflections { public static final Field field$EntityDimensions$fixed = requireNonNull( ReflectionUtils.getDeclaredField(clazz$EntityDimensions, boolean.class, 0) ); + + public static final Class clazz$PlayerTeam = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "world.scores.ScoreboardTeam", + "world.scores.PlayerTeam" + ) + ); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityDataUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityDataUtils.java index 1f03ba9ed..30a913296 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityDataUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityDataUtils.java @@ -10,6 +10,7 @@ public final class EntityDataUtils { private static final int LEFT_ALIGNMENT = 0x08; // 8 private static final int RIGHT_ALIGNMENT = 0x10; // 16 public static final int UNSAFE_ITEM_DATA_ID = 8; // 正常来说应该通过定义 Data 获取 id 这样的做法未经验证可能不安全 + public static final int SHARED_FLAGS_ID = 0; // 正常来说应该通过定义 Data 获取 id 这样的做法未经验证可能不安全 public static byte encodeTextDisplayMask(boolean hasShadow, boolean isSeeThrough, boolean useDefaultBackground, int alignment) { int bitMask = 0; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/score/BukkitTeamManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/score/BukkitTeamManager.java new file mode 100644 index 000000000..49fb993ad --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/world/score/BukkitTeamManager.java @@ -0,0 +1,76 @@ +package net.momirealms.craftengine.bukkit.world.score; + +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections; +import net.momirealms.craftengine.core.util.LegacyChatFormatter; +import net.momirealms.craftengine.core.world.score.TeamManager; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class BukkitTeamManager implements TeamManager { + private static BukkitTeamManager instance; + private final BukkitCraftEngine plugin; + protected Set colorsInUse = new HashSet<>(); + private final Map teamByColor = new EnumMap<>(LegacyChatFormatter.class); + private boolean changed = false; + + public BukkitTeamManager(BukkitCraftEngine plugin) { + this.plugin = plugin; + instance = this; + } + + public static BukkitTeamManager instance() { + return instance; + } + + @Override + public void setColorInUse(LegacyChatFormatter color) { + this.colorsInUse.add(color); + this.changed = true; + } + + @Override + public void unload() { + this.changed = !this.colorsInUse.isEmpty(); + this.colorsInUse.clear(); + this.teamByColor.clear(); + } + + @Nullable + public Object getTeamByColor(LegacyChatFormatter color) { + return this.teamByColor.get(color); + } + + @SuppressWarnings("deprecation") + @Override + public void runDelayedSyncTasks() { + if (!this.changed) { + return; + } + Scoreboard scoreboard = Bukkit.getScoreboardManager().getMainScoreboard(); + for (LegacyChatFormatter color : LegacyChatFormatter.values()) { + Team team = scoreboard.getTeam(TEAM_PREFIX + color.name().toLowerCase(Locale.ROOT)); + if (this.colorsInUse.contains(color)) { + if (team == null) { + team = scoreboard.registerNewTeam(TEAM_PREFIX + color.name().toLowerCase(Locale.ROOT)); + team.setColor(ChatColor.valueOf(color.name())); + } + try { + Object nmsTeam = CraftBukkitReflections.field$CraftTeam$team.get(team); + this.teamByColor.put(color, nmsTeam); + } catch (ReflectiveOperationException e) { + this.plugin.logger().warn("Could not get nms team", e); + } + } else { + if (team != null) { + team.unregister(); + } + } + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/Glowing.java b/core/src/main/java/net/momirealms/craftengine/core/entity/Glowing.java new file mode 100644 index 000000000..71877e393 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/Glowing.java @@ -0,0 +1,10 @@ +package net.momirealms.craftengine.core.entity; + +import net.momirealms.craftengine.core.util.LegacyChatFormatter; +import org.jetbrains.annotations.Nullable; + +public interface Glowing { + + @Nullable + LegacyChatFormatter glowColor(); +} 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 b4460723c..364281ce7 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,6 +1,7 @@ package net.momirealms.craftengine.core.entity.furniture; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.momirealms.craftengine.core.entity.Glowing; import net.momirealms.craftengine.core.entity.furniture.behavior.FurnitureBehaviorTypes; import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig; import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfigs; @@ -219,6 +220,14 @@ public abstract class AbstractFurnitureManager implements FurnitureManager { 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); + // 收集发光颜色类型 + for (FurnitureElementConfig element : elements) { + if (element instanceof Glowing glowing) { + Optional.ofNullable(glowing.glowColor()).ifPresent(color -> AbstractFurnitureManager.this.plugin.teamManager().setColorInUse(color)); + } + } + + // 外部模型 Optional externalModel; if (variantArguments.containsKey("model-engine")) { externalModel = Optional.of(plugin.compatibilityManager().createModel("ModelEngine", variantArguments.get("model-engine").toString())); @@ -228,6 +237,7 @@ public abstract class AbstractFurnitureManager implements FurnitureManager { externalModel = Optional.empty(); } + // 碰撞箱配置 List> hitboxes = ResourceConfigUtils.parseConfigAsList(variantArguments.get("hitboxes"), FurnitureHitBoxTypes::fromMap); if (hitboxes.isEmpty() && externalModel.isEmpty()) { hitboxes = List.of(defaultHitBox()); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java index a119bcf42..6eacd6503 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java @@ -234,6 +234,9 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl if (settings.destroyOnDeathChance != 0) { this.featureFlag$destroyOnDeathChance = true; } + if (settings.glowColor != null) { + this.plugin.teamManager().setColorInUse(settings.glowColor); + } } return true; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java index 3075ea81e..68fea801d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java @@ -41,6 +41,7 @@ import net.momirealms.craftengine.core.plugin.scheduler.SchedulerAdapter; import net.momirealms.craftengine.core.sound.SoundManager; import net.momirealms.craftengine.core.util.CompletableFutures; import net.momirealms.craftengine.core.world.WorldManager; +import net.momirealms.craftengine.core.world.score.TeamManager; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Logger; import org.jetbrains.annotations.ApiStatus; @@ -82,6 +83,7 @@ public abstract class CraftEngine implements Plugin { protected ProjectileManager projectileManager; protected SeatManager seatManager; protected EntityCullingManager entityCullingManager; + protected TeamManager teamManager; private final PluginTaskRegistry beforeEnableTaskRegistry = new PluginTaskRegistry(); private final PluginTaskRegistry afterEnableTaskRegistry = new PluginTaskRegistry(); @@ -164,6 +166,7 @@ public abstract class CraftEngine implements Plugin { this.projectileManager.reload(); this.seatManager.reload(); this.entityCullingManager.reload(); + this.teamManager.reload(); } private void runDelayTasks(boolean reloadRecipe) { @@ -236,6 +239,8 @@ public abstract class CraftEngine implements Plugin { if (reloadRecipe) { this.recipeManager.runDelayedSyncTasks(); } + // 同步修改队伍 + this.teamManager.runDelayedSyncTasks(); long time4 = System.currentTimeMillis(); long syncTime = time4 - time3; this.reloadEventDispatcher.accept(this); @@ -569,6 +574,21 @@ public abstract class CraftEngine implements Plugin { return projectileManager; } + @Override + public EntityCullingManager entityCullingManager() { + return entityCullingManager; + } + + @Override + public TeamManager teamManager() { + return teamManager; + } + + @Override + public SeatManager seatManager() { + return seatManager; + } + @Override public Platform platform() { return platform; diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/Plugin.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/Plugin.java index 1813c2bd8..d4aae96e9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/Plugin.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/Plugin.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.advancement.AdvancementManager; import net.momirealms.craftengine.core.block.BlockManager; import net.momirealms.craftengine.core.entity.furniture.FurnitureManager; import net.momirealms.craftengine.core.entity.projectile.ProjectileManager; +import net.momirealms.craftengine.core.entity.seat.SeatManager; import net.momirealms.craftengine.core.font.FontManager; import net.momirealms.craftengine.core.item.ItemManager; import net.momirealms.craftengine.core.item.recipe.RecipeManager; @@ -16,6 +17,7 @@ import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.config.template.TemplateManager; import net.momirealms.craftengine.core.plugin.context.GlobalVariableManager; import net.momirealms.craftengine.core.plugin.dependency.DependencyManager; +import net.momirealms.craftengine.core.plugin.entityculling.EntityCullingManager; import net.momirealms.craftengine.core.plugin.gui.GuiManager; import net.momirealms.craftengine.core.plugin.gui.category.ItemBrowserManager; import net.momirealms.craftengine.core.plugin.locale.TranslationManager; @@ -24,6 +26,7 @@ import net.momirealms.craftengine.core.plugin.network.NetworkManager; import net.momirealms.craftengine.core.plugin.scheduler.SchedulerAdapter; import net.momirealms.craftengine.core.sound.SoundManager; import net.momirealms.craftengine.core.world.WorldManager; +import net.momirealms.craftengine.core.world.score.TeamManager; import java.io.File; import java.io.InputStream; @@ -97,5 +100,11 @@ public interface Plugin { ProjectileManager projectileManager(); + EntityCullingManager entityCullingManager(); + + TeamManager teamManager(); + + SeatManager seatManager(); + Platform platform(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/world/score/TeamManager.java b/core/src/main/java/net/momirealms/craftengine/core/world/score/TeamManager.java new file mode 100644 index 000000000..af772e294 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/world/score/TeamManager.java @@ -0,0 +1,10 @@ +package net.momirealms.craftengine.core.world.score; + +import net.momirealms.craftengine.core.plugin.Manageable; +import net.momirealms.craftengine.core.util.LegacyChatFormatter; + +public interface TeamManager extends Manageable { + String TEAM_PREFIX = "ce_"; + + void setColorInUse(LegacyChatFormatter color); +} diff --git a/gradle.properties b/gradle.properties index bf950c905..b510a3cca 100644 --- a/gradle.properties +++ b/gradle.properties @@ -48,7 +48,7 @@ byte_buddy_version=1.18.1 ahocorasick_version=0.6.3 snake_yaml_version=2.5 anti_grief_version=1.0.5 -nms_helper_version=1.0.142 +nms_helper_version=1.0.145 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.38.7