9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 15:09:15 +00:00

添加家具发光和物品发光

This commit is contained in:
XiaoMoMi
2025-12-06 02:32:32 +08:00
parent bd02b9d46e
commit 054444b658
15 changed files with 275 additions and 62 deletions

View File

@@ -4,10 +4,12 @@ import it.unimi.dsi.fastutil.ints.IntArrayList;
import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.nms.FastNMS;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MEntityTypes; 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.Furniture;
import net.momirealms.craftengine.core.entity.furniture.FurnitureColorSource; import net.momirealms.craftengine.core.entity.furniture.FurnitureColorSource;
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement; import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElement;
import net.momirealms.craftengine.core.entity.player.Player; 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.Vec3d;
import net.momirealms.craftengine.core.world.WorldPosition; import net.momirealms.craftengine.core.world.WorldPosition;
@@ -21,6 +23,7 @@ public class ItemDisplayFurnitureElement implements FurnitureElement {
private final int entityId; private final int entityId;
private final Object despawnPacket; private final Object despawnPacket;
private final FurnitureColorSource colorSource; private final FurnitureColorSource colorSource;
private final LegacyChatFormatter glowColor;
public ItemDisplayFurnitureElement(Furniture furniture, ItemDisplayFurnitureElementConfig config) { public ItemDisplayFurnitureElement(Furniture furniture, ItemDisplayFurnitureElementConfig config) {
this.config = 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.position = new WorldPosition(furniturePos.world, position.x, position.y, position.z, furniturePos.xRot, furniturePos.yRot);
this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(entityId); }}); this.despawnPacket = FastNMS.INSTANCE.constructor$ClientboundRemoveEntitiesPacket(new IntArrayList() {{ add(entityId); }});
this.colorSource = furniture.dataAccessor.getColorSource(); this.colorSource = furniture.dataAccessor.getColorSource();
this.glowColor = config.glowColor;
} }
@Override @Override
public void show(Player player) { public void show(Player player) {
UUID uuid = UUID.randomUUID();
player.sendPacket(FastNMS.INSTANCE.constructor$ClientboundBundlePacket(List.of( player.sendPacket(FastNMS.INSTANCE.constructor$ClientboundBundlePacket(List.of(
FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket( FastNMS.INSTANCE.constructor$ClientboundAddEntityPacket(
this.entityId, UUID.randomUUID(), this.entityId, uuid,
this.position.x, this.position.y, this.position.z, 0, this.position.yRot, this.position.x, this.position.y, this.position.z, 0, this.position.yRot,
MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0 MEntityTypes.ITEM_DISPLAY, 0, CoreReflections.instance$Vec3$Zero, 0
), ),
FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadata.apply(player, this.colorSource)) FastNMS.INSTANCE.constructor$ClientboundSetEntityDataPacket(this.entityId, this.config.metadata.apply(player, this.colorSource))
)), false); )), 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 @Override

View File

@@ -1,8 +1,10 @@
package net.momirealms.craftengine.bukkit.entity.furniture.element; package net.momirealms.craftengine.bukkit.entity.furniture.element;
import it.unimi.dsi.fastutil.ints.IntArrayList; 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.entity.data.ItemDisplayEntityData;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager; 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.Billboard;
import net.momirealms.craftengine.core.entity.display.ItemDisplayContext; import net.momirealms.craftengine.core.entity.display.ItemDisplayContext;
import net.momirealms.craftengine.core.entity.furniture.Furniture; 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.ItemKeys;
import net.momirealms.craftengine.core.item.data.FireworkExplosion; import net.momirealms.craftengine.core.item.data.FireworkExplosion;
import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.LegacyChatFormatter;
import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.util.ResourceConfigUtils;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3f; import org.joml.Vector3f;
@@ -26,7 +30,7 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.BiFunction; import java.util.function.BiFunction;
public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig<ItemDisplayFurnitureElement> { public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig<ItemDisplayFurnitureElement>, Glowing {
public static final Factory FACTORY = new Factory(); public static final Factory FACTORY = new Factory();
public final BiFunction<Player, FurnitureColorSource, List<Object>> metadata; public final BiFunction<Player, FurnitureColorSource, List<Object>> metadata;
public final Key itemId; public final Key itemId;
@@ -41,6 +45,7 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig
public final float shadowRadius; public final float shadowRadius;
public final float shadowStrength; public final float shadowStrength;
public final boolean applyDyedColor; public final boolean applyDyedColor;
public final LegacyChatFormatter glowColor;
public ItemDisplayFurnitureElementConfig(Key itemId, public ItemDisplayFurnitureElementConfig(Key itemId,
Vector3f scale, Vector3f scale,
@@ -53,7 +58,8 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig
Billboard billboard, Billboard billboard,
float shadowRadius, float shadowRadius,
float shadowStrength, float shadowStrength,
boolean applyDyedColor) { boolean applyDyedColor,
@Nullable LegacyChatFormatter glowColor) {
this.scale = scale; this.scale = scale;
this.position = position; this.position = position;
this.translation = translation; this.translation = translation;
@@ -66,6 +72,7 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig
this.shadowStrength = shadowStrength; this.shadowStrength = shadowStrength;
this.applyDyedColor = applyDyedColor; this.applyDyedColor = applyDyedColor;
this.itemId = itemId; this.itemId = itemId;
this.glowColor = glowColor;
BiFunction<Player, FurnitureColorSource, Item<?>> itemFunction = (player, colorSource) -> { BiFunction<Player, FurnitureColorSource, Item<?>> itemFunction = (player, colorSource) -> {
Item<ItemStack> wrappedItem = BukkitItemManager.instance().createWrappedItem(itemId, player); Item<ItemStack> wrappedItem = BukkitItemManager.instance().createWrappedItem(itemId, player);
if (applyDyedColor && colorSource != null && wrappedItem != null) { if (applyDyedColor && colorSource != null && wrappedItem != null) {
@@ -82,6 +89,9 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig
}; };
this.metadata = (player, source) -> { this.metadata = (player, source) -> {
List<Object> dataValues = new ArrayList<>(); List<Object> dataValues = new ArrayList<>();
if (glowColor != null) {
BaseEntityData.SharedFlags.addEntityData((byte) 0x40, dataValues);
}
ItemDisplayEntityData.DisplayedItem.addEntityData(itemFunction.apply(player, source).getLiteralObject(), dataValues); ItemDisplayEntityData.DisplayedItem.addEntityData(itemFunction.apply(player, source).getLiteralObject(), dataValues);
ItemDisplayEntityData.Scale.addEntityData(this.scale, dataValues); ItemDisplayEntityData.Scale.addEntityData(this.scale, dataValues);
ItemDisplayEntityData.RotationLeft.addEntityData(this.rotation, dataValues); ItemDisplayEntityData.RotationLeft.addEntityData(this.rotation, dataValues);
@@ -142,6 +152,12 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig
return this.itemId; return this.itemId;
} }
@Nullable
@Override
public LegacyChatFormatter glowColor() {
return this.glowColor;
}
@Override @Override
public ItemDisplayFurnitureElement create(@NotNull Furniture furniture) { public ItemDisplayFurnitureElement create(@NotNull Furniture furniture) {
return new ItemDisplayFurnitureElement(furniture, this); return new ItemDisplayFurnitureElement(furniture, this);
@@ -165,7 +181,8 @@ public class ItemDisplayFurnitureElementConfig implements FurnitureElementConfig
ResourceConfigUtils.getAsEnum(arguments.get("billboard"), Billboard.class, Billboard.FIXED), ResourceConfigUtils.getAsEnum(arguments.get("billboard"), Billboard.class, Billboard.FIXED),
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-radius", 0f), "shadow-radius"), ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-radius", 0f), "shadow-radius"),
ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-strength", 1f), "shadow-strength"), ResourceConfigUtils.getAsFloat(arguments.getOrDefault("shadow-strength", 1f), "shadow-strength"),
applyDyedColor applyDyedColor,
ResourceConfigUtils.getAsEnum(arguments.get("glow-color"), LegacyChatFormatter.class, null)
); );
} }
} }

View File

@@ -27,6 +27,7 @@ import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.sound.BukkitSoundManager; import net.momirealms.craftengine.bukkit.sound.BukkitSoundManager;
import net.momirealms.craftengine.bukkit.util.EventUtils; import net.momirealms.craftengine.bukkit.util.EventUtils;
import net.momirealms.craftengine.bukkit.world.BukkitWorldManager; 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.item.ItemManager;
import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.classpath.ClassPathAppender; import net.momirealms.craftengine.core.plugin.classpath.ClassPathAppender;
@@ -192,6 +193,8 @@ public class BukkitCraftEngine extends CraftEngine {
super.seatManager = new BukkitSeatManager(this); super.seatManager = new BukkitSeatManager(this);
// 初始化家具管理器 // 初始化家具管理器
super.furnitureManager = new BukkitFurnitureManager(this); super.furnitureManager = new BukkitFurnitureManager(this);
// 初始化队伍管理器
super.teamManager = new BukkitTeamManager(this);
// 注册默认的parser // 注册默认的parser
this.registerDefaultParsers(); this.registerDefaultParsers();
// 完成加载 // 完成加载

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.bukkit.plugin.network.handler; package net.momirealms.craftengine.bukkit.plugin.network.handler;
import net.kyori.adventure.text.Component; 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.entity.data.ItemEntityData;
import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
import net.momirealms.craftengine.bukkit.nms.FastNMS; 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.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.bukkit.util.ComponentUtils; import net.momirealms.craftengine.bukkit.util.ComponentUtils;
import net.momirealms.craftengine.bukkit.util.EntityDataUtils; 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.entity.player.Player;
import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.CustomItem;
import net.momirealms.craftengine.core.item.Item; 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.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.context.ContextHolder; 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.context.parameter.DirectContextParameters;
import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent; import net.momirealms.craftengine.core.plugin.network.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler; 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.plugin.text.minimessage.CustomTagResolver;
import net.momirealms.craftengine.core.util.AdventureHelper; import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.ArrayUtils; import net.momirealms.craftengine.core.util.ArrayUtils;
import net.momirealms.craftengine.core.util.FriendlyByteBuf; import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import net.momirealms.craftengine.core.util.LegacyChatFormatter;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
public class CommonItemPacketHandler implements EntityPacketHandler { public class CommonItemPacketHandler implements EntityPacketHandler {
@@ -42,71 +44,97 @@ public class CommonItemPacketHandler implements EntityPacketHandler {
boolean changed = false; boolean changed = false;
List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf); List<Object> packedItems = FastNMS.INSTANCE.method$ClientboundSetEntityDataPacket$unpack(buf);
Component nameToShow = null; Component nameToShow = null;
LegacyChatFormatter glowColor = null;
for (int i = 0; i < packedItems.size(); i++) { for (int i = 0; i < packedItems.size(); i++) {
Object packedItem = packedItems.get(i); Object packedItem = packedItems.get(i);
int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem); int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
if (entityDataId != EntityDataUtils.UNSAFE_ITEM_DATA_ID) continue; if (entityDataId == EntityDataUtils.UNSAFE_ITEM_DATA_ID) {
Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem); Object nmsItemStack = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
// 可能是其他插件导致的问题 // 可能是其他插件导致的问题
if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) { if (!CoreReflections.clazz$ItemStack.isInstance(nmsItemStack)) {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
if (time - lastWarningTime > 5000) { if (time - lastWarningTime > 5000) {
BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user; BukkitServerPlayer serverPlayer = (BukkitServerPlayer) user;
CraftEngine.instance().logger().severe("An issue was detected while applying item-related entity data for '" + serverPlayer.name() + 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."); "'. Please execute the command '/ce debug entity-id " + serverPlayer.world().name() + " " + id + "' and provide a screenshot for further investigation.");
lastWarningTime = time; lastWarningTime = time;
}
continue;
}
ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsItemStack);
// 转换为客户端侧物品
Optional<ItemStack> 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<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
Optional<CustomItem<ItemStack>> 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<Component> 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); if (glowColor != null) {
Object teamByColor = BukkitTeamManager.instance().getTeamByColor(glowColor);
// 转换为客户端侧物品 if (teamByColor != null) {
Optional<ItemStack> optional = BukkitItemManager.instance().s2c(itemStack, user);
if (optional.isPresent()) {
changed = true; changed = true;
itemStack = optional.get(); outer: {
Object serializer = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$serializer(packedItem); for (int i = 0; i < packedItems.size(); i++) {
packedItems.set(i, FastNMS.INSTANCE.constructor$SynchedEntityData$DataValue(entityDataId, serializer, FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack))); Object packedItem = packedItems.get(i);
} int entityDataId = FastNMS.INSTANCE.field$SynchedEntityData$DataValue$id(packedItem);
if (entityDataId == BaseEntityData.SharedFlags.id()) {
// 处理 drop-display 物品设置 byte flags = (Byte) FastNMS.INSTANCE.field$SynchedEntityData$DataValue$value(packedItem);
// 一定要处理经历过客户端侧组件修改的物品 flags |= (byte) 0x40;
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack); packedItems.set(i, BaseEntityData.SharedFlags.createEntityData(flags));
Optional<CustomItem<ItemStack>> optionalCustomItem = wrappedItem.getCustomItem(); break outer;
String showName = null; }
if (optionalCustomItem.isPresent()) { }
showName = optionalCustomItem.get().settings().dropDisplay(); packedItems.add(BaseEntityData.SharedFlags.createEntityData((byte) 0x40));
} else if (Config.enableDefaultDropDisplay()) {
showName = Config.defaultDropDisplayFormat();
}
// 如果设定了自定义展示名
if (showName != null) {
PlayerOptionalContext context = NetworkTextReplaceContext.of(user, ContextHolder.builder()
.withParameter(DirectContextParameters.COUNT, itemStack.getAmount()));
Optional<Component> optionalHoverComponent = wrappedItem.hoverNameComponent();
Component hoverComponent;
if (optionalHoverComponent.isPresent()) {
hoverComponent = optionalHoverComponent.get();
} else {
hoverComponent = Component.translatable(itemStack.translationKey());
} }
// 展示名称为空则显示其hover name Object entityLookup = FastNMS.INSTANCE.method$ServerLevel$getEntityLookup(user.clientSideWorld().serverWorld());
if (showName.isEmpty()) { Object entity = FastNMS.INSTANCE.method$EntityLookup$get(entityLookup, id);
nameToShow = hoverComponent; if (entity != null) {
} user.sendPacket(FastNMS.INSTANCE.method$ClientboundSetPlayerTeamPacket$createMultiplePlayerPacket(teamByColor, List.of(FastNMS.INSTANCE.method$Entity$getUUID(entity).toString()), true), false);
// 显示自定义格式的名字
else {
nameToShow = AdventureHelper.miniMessage().deserialize(
showName,
ArrayUtils.appendElementToArrayTail(context.tagResolvers(), new CustomTagResolver("name", hoverComponent))
);
} }
} }
break;
} }
// 添加自定义显示名 // 添加自定义显示名
if (nameToShow != null) { if (nameToShow != null) {

View File

@@ -392,4 +392,12 @@ public final class CraftBukkitReflections {
public static final Field field$MinecraftMerchant$title = requireNonNull( public static final Field field$MinecraftMerchant$title = requireNonNull(
ReflectionUtils.getDeclaredField(clazz$CraftMerchantCustom$MinecraftMerchant, CoreReflections.clazz$Component, 0) 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)
);
} }

View File

@@ -4638,4 +4638,11 @@ public final class CoreReflections {
public static final Field field$EntityDimensions$fixed = requireNonNull( public static final Field field$EntityDimensions$fixed = requireNonNull(
ReflectionUtils.getDeclaredField(clazz$EntityDimensions, boolean.class, 0) ReflectionUtils.getDeclaredField(clazz$EntityDimensions, boolean.class, 0)
); );
public static final Class<?> clazz$PlayerTeam = requireNonNull(
BukkitReflectionUtils.findReobfOrMojmapClass(
"world.scores.ScoreboardTeam",
"world.scores.PlayerTeam"
)
);
} }

View File

@@ -10,6 +10,7 @@ public final class EntityDataUtils {
private static final int LEFT_ALIGNMENT = 0x08; // 8 private static final int LEFT_ALIGNMENT = 0x08; // 8
private static final int RIGHT_ALIGNMENT = 0x10; // 16 private static final int RIGHT_ALIGNMENT = 0x10; // 16
public static final int UNSAFE_ITEM_DATA_ID = 8; // 正常来说应该通过定义 Data 获取 id 这样的做法未经验证可能不安全 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) { public static byte encodeTextDisplayMask(boolean hasShadow, boolean isSeeThrough, boolean useDefaultBackground, int alignment) {
int bitMask = 0; int bitMask = 0;

View File

@@ -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<LegacyChatFormatter> colorsInUse = new HashSet<>();
private final Map<LegacyChatFormatter, Object> 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();
}
}
}
}
}

View File

@@ -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();
}

View File

@@ -1,6 +1,7 @@
package net.momirealms.craftengine.core.entity.furniture; package net.momirealms.craftengine.core.entity.furniture;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; 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.behavior.FurnitureBehaviorTypes;
import net.momirealms.craftengine.core.entity.furniture.element.FurnitureElementConfig; 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.element.FurnitureElementConfigs;
@@ -219,6 +220,14 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
Optional<Vector3f> optionalLootSpawnOffset = Optional.ofNullable(variantArguments.get("loot-spawn-offset")).map(it -> ResourceConfigUtils.getAsVector3f(it, "loot-spawn-offset")); Optional<Vector3f> optionalLootSpawnOffset = Optional.ofNullable(variantArguments.get("loot-spawn-offset")).map(it -> ResourceConfigUtils.getAsVector3f(it, "loot-spawn-offset"));
List<FurnitureElementConfig<?>> elements = ResourceConfigUtils.parseConfigAsList(variantArguments.get("elements"), FurnitureElementConfigs::fromMap); List<FurnitureElementConfig<?>> 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> externalModel; Optional<ExternalModel> externalModel;
if (variantArguments.containsKey("model-engine")) { if (variantArguments.containsKey("model-engine")) {
externalModel = Optional.of(plugin.compatibilityManager().createModel("ModelEngine", variantArguments.get("model-engine").toString())); 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(); externalModel = Optional.empty();
} }
// 碰撞箱配置
List<FurnitureHitBoxConfig<?>> hitboxes = ResourceConfigUtils.parseConfigAsList(variantArguments.get("hitboxes"), FurnitureHitBoxTypes::fromMap); List<FurnitureHitBoxConfig<?>> hitboxes = ResourceConfigUtils.parseConfigAsList(variantArguments.get("hitboxes"), FurnitureHitBoxTypes::fromMap);
if (hitboxes.isEmpty() && externalModel.isEmpty()) { if (hitboxes.isEmpty() && externalModel.isEmpty()) {
hitboxes = List.of(defaultHitBox()); hitboxes = List.of(defaultHitBox());

View File

@@ -234,6 +234,9 @@ public abstract class AbstractItemManager<I> extends AbstractModelGenerator impl
if (settings.destroyOnDeathChance != 0) { if (settings.destroyOnDeathChance != 0) {
this.featureFlag$destroyOnDeathChance = true; this.featureFlag$destroyOnDeathChance = true;
} }
if (settings.glowColor != null) {
this.plugin.teamManager().setColorInUse(settings.glowColor);
}
} }
return true; return true;
} }

View File

@@ -41,6 +41,7 @@ import net.momirealms.craftengine.core.plugin.scheduler.SchedulerAdapter;
import net.momirealms.craftengine.core.sound.SoundManager; import net.momirealms.craftengine.core.sound.SoundManager;
import net.momirealms.craftengine.core.util.CompletableFutures; import net.momirealms.craftengine.core.util.CompletableFutures;
import net.momirealms.craftengine.core.world.WorldManager; 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.LogManager;
import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.core.Logger;
import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.ApiStatus;
@@ -82,6 +83,7 @@ public abstract class CraftEngine implements Plugin {
protected ProjectileManager projectileManager; protected ProjectileManager projectileManager;
protected SeatManager seatManager; protected SeatManager seatManager;
protected EntityCullingManager entityCullingManager; protected EntityCullingManager entityCullingManager;
protected TeamManager teamManager;
private final PluginTaskRegistry beforeEnableTaskRegistry = new PluginTaskRegistry(); private final PluginTaskRegistry beforeEnableTaskRegistry = new PluginTaskRegistry();
private final PluginTaskRegistry afterEnableTaskRegistry = new PluginTaskRegistry(); private final PluginTaskRegistry afterEnableTaskRegistry = new PluginTaskRegistry();
@@ -164,6 +166,7 @@ public abstract class CraftEngine implements Plugin {
this.projectileManager.reload(); this.projectileManager.reload();
this.seatManager.reload(); this.seatManager.reload();
this.entityCullingManager.reload(); this.entityCullingManager.reload();
this.teamManager.reload();
} }
private void runDelayTasks(boolean reloadRecipe) { private void runDelayTasks(boolean reloadRecipe) {
@@ -236,6 +239,8 @@ public abstract class CraftEngine implements Plugin {
if (reloadRecipe) { if (reloadRecipe) {
this.recipeManager.runDelayedSyncTasks(); this.recipeManager.runDelayedSyncTasks();
} }
// 同步修改队伍
this.teamManager.runDelayedSyncTasks();
long time4 = System.currentTimeMillis(); long time4 = System.currentTimeMillis();
long syncTime = time4 - time3; long syncTime = time4 - time3;
this.reloadEventDispatcher.accept(this); this.reloadEventDispatcher.accept(this);
@@ -569,6 +574,21 @@ public abstract class CraftEngine implements Plugin {
return projectileManager; return projectileManager;
} }
@Override
public EntityCullingManager entityCullingManager() {
return entityCullingManager;
}
@Override
public TeamManager teamManager() {
return teamManager;
}
@Override
public SeatManager seatManager() {
return seatManager;
}
@Override @Override
public Platform platform() { public Platform platform() {
return platform; return platform;

View File

@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.advancement.AdvancementManager;
import net.momirealms.craftengine.core.block.BlockManager; import net.momirealms.craftengine.core.block.BlockManager;
import net.momirealms.craftengine.core.entity.furniture.FurnitureManager; import net.momirealms.craftengine.core.entity.furniture.FurnitureManager;
import net.momirealms.craftengine.core.entity.projectile.ProjectileManager; 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.font.FontManager;
import net.momirealms.craftengine.core.item.ItemManager; import net.momirealms.craftengine.core.item.ItemManager;
import net.momirealms.craftengine.core.item.recipe.RecipeManager; 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.config.template.TemplateManager;
import net.momirealms.craftengine.core.plugin.context.GlobalVariableManager; import net.momirealms.craftengine.core.plugin.context.GlobalVariableManager;
import net.momirealms.craftengine.core.plugin.dependency.DependencyManager; 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.GuiManager;
import net.momirealms.craftengine.core.plugin.gui.category.ItemBrowserManager; import net.momirealms.craftengine.core.plugin.gui.category.ItemBrowserManager;
import net.momirealms.craftengine.core.plugin.locale.TranslationManager; 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.plugin.scheduler.SchedulerAdapter;
import net.momirealms.craftengine.core.sound.SoundManager; import net.momirealms.craftengine.core.sound.SoundManager;
import net.momirealms.craftengine.core.world.WorldManager; import net.momirealms.craftengine.core.world.WorldManager;
import net.momirealms.craftengine.core.world.score.TeamManager;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
@@ -97,5 +100,11 @@ public interface Plugin {
ProjectileManager projectileManager(); ProjectileManager projectileManager();
EntityCullingManager entityCullingManager();
TeamManager teamManager();
SeatManager seatManager();
Platform platform(); Platform platform();
} }

View File

@@ -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);
}

View File

@@ -48,7 +48,7 @@ byte_buddy_version=1.18.1
ahocorasick_version=0.6.3 ahocorasick_version=0.6.3
snake_yaml_version=2.5 snake_yaml_version=2.5
anti_grief_version=1.0.5 anti_grief_version=1.0.5
nms_helper_version=1.0.142 nms_helper_version=1.0.145
evalex_version=3.5.0 evalex_version=3.5.0
reactive_streams_version=1.0.4 reactive_streams_version=1.0.4
amazon_awssdk_version=2.38.7 amazon_awssdk_version=2.38.7