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

盔甲重构part1

This commit is contained in:
XiaoMoMi
2025-07-03 05:55:57 +08:00
parent a27f1678fd
commit d9bf33ce11
30 changed files with 931 additions and 362 deletions

View File

@@ -15,10 +15,7 @@ import net.momirealms.craftengine.core.util.VersionHelper;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.ThrowableProjectile;
import org.bukkit.entity.*;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
@@ -32,6 +29,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
public class BukkitProjectileManager implements Listener, ProjectileManager {
private static BukkitProjectileManager instance;
@@ -47,11 +45,22 @@ public class BukkitProjectileManager implements Listener, ProjectileManager {
@Override
public void delayedInit() {
Bukkit.getPluginManager().registerEvents(this, this.plugin.javaPlugin());
for (World world : Bukkit.getWorlds()) {
List<Entity> entities = world.getEntities();
for (Entity entity : entities) {
if (entity instanceof Projectile projectile) {
handleProjectileLoad(projectile);
if (VersionHelper.isFolia()) {
for (World world : Bukkit.getWorlds()) {
List<Entity> entities = world.getEntities();
for (Entity entity : entities) {
if (entity instanceof Projectile projectile) {
projectile.getScheduler().run(this.plugin.javaPlugin(), (t) -> handleProjectileLoad(projectile), () -> {});
}
}
}
} else {
for (World world : Bukkit.getWorlds()) {
List<Entity> entities = world.getEntities();
for (Entity entity : entities) {
if (entity instanceof Projectile projectile) {
handleProjectileLoad(projectile);
}
}
}
}

View File

@@ -149,6 +149,7 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
@Override
public CustomItem<ItemStack> build() {
this.modifiers.addAll(this.settings.modifiers());
this.clientBoundModifiers.addAll(this.settings.clientBoundModifiers());
return new BukkitCustomItem(this.id, this.item, this.clientBoundItem, this.itemKey, this.clientBoundItemKey, List.copyOf(this.behaviors),
List.copyOf(this.modifiers), List.copyOf(this.clientBoundModifiers), this.settings, this.events);
}

View File

@@ -11,11 +11,14 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
import net.momirealms.craftengine.bukkit.util.ItemUtils;
import net.momirealms.craftengine.bukkit.util.KeyUtils;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.*;
import net.momirealms.craftengine.core.item.equipment.TrimBasedEquipment;
import net.momirealms.craftengine.core.item.modifier.IdModifier;
import net.momirealms.craftengine.core.pack.AbstractPackManager;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
@@ -33,9 +36,7 @@ import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Optional;
import java.util.Set;
import java.util.*;
public class BukkitItemManager extends AbstractItemManager<ItemStack> {
static {
@@ -50,6 +51,8 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
private final DebugStickListener debugStickListener;
private final ArmorEventListener armorEventListener;
private final NetworkItemHandler<ItemStack> networkItemHandler;
private final Object bedrockItemHolder;
private boolean registeredTrimMaterial;
public BukkitItemManager(BukkitCraftEngine plugin) {
super(plugin);
@@ -61,6 +64,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
this.armorEventListener = new ArmorEventListener();
this.networkItemHandler = VersionHelper.isOrAbove1_20_5() ? new ModernNetworkItemHandler() : new LegacyNetworkItemHandler();
this.registerAllVanillaItems();
this.bedrockItemHolder = FastNMS.INSTANCE.method$Registry$getHolderByResourceKey(MBuiltInRegistries.ITEM, FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.ITEM, KeyUtils.toResourceLocation(Key.of("minecraft:bedrock")))).get();;
}
@Override
@@ -134,6 +138,78 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
HandlerList.unregisterAll(this.armorEventListener);
}
@Override
protected void registerArmorTrimPattern(Collection<TrimBasedEquipment> equipments) {
if (equipments.isEmpty()) return;
this.registerCustomTrimMaterial();
Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.TRIM_PATTERN);
try {
CoreReflections.field$MappedRegistry$frozen.set(registry, false);
for (TrimBasedEquipment equipment : equipments) {
Object resourceLocation = KeyUtils.toResourceLocation(equipment.assetId());
Object previous = FastNMS.INSTANCE.method$Registry$getValue(registry, resourceLocation);
if (previous == null) {
Object trimPattern = createTrimPattern(equipment.assetId());
Object holder = CoreReflections.method$Registry$registerForHolder.invoke(null, registry, resourceLocation, trimPattern);
CoreReflections.method$Holder$Reference$bindValue.invoke(holder, trimPattern);
CoreReflections.field$Holder$Reference$tags.set(holder, Set.of());
}
}
} catch (Exception e) {
this.plugin.logger().warn("Failed to register armor trim pattern.", e);
} finally {
try {
CoreReflections.field$MappedRegistry$frozen.set(registry, true);
} catch (ReflectiveOperationException ignored) {
}
}
}
private void registerCustomTrimMaterial() {
if (this.registeredTrimMaterial) return;
Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.TRIM_MATERIAL);
Object resourceLocation = KeyUtils.toResourceLocation(Key.of("minecraft", AbstractPackManager.TRIM_MATERIAL));
Object previous = FastNMS.INSTANCE.method$Registry$getValue(registry, resourceLocation);
if (previous == null) {
try {
CoreReflections.field$MappedRegistry$frozen.set(registry, false);
Object trimMaterial = createTrimMaterial();
Object holder = CoreReflections.method$Registry$registerForHolder.invoke(null, registry, resourceLocation, trimMaterial);
CoreReflections.method$Holder$Reference$bindValue.invoke(holder, trimMaterial);
CoreReflections.field$Holder$Reference$tags.set(holder, Set.of());
} catch (Exception e) {
this.plugin.logger().warn("Failed to register trim material.", e);
} finally {
try {
CoreReflections.field$MappedRegistry$frozen.set(registry, true);
} catch (ReflectiveOperationException ignored) {
}
}
}
this.registeredTrimMaterial = true;
}
private Object createTrimPattern(Key key) throws ReflectiveOperationException {
if (VersionHelper.isOrAbove1_21_5()) {
return CoreReflections.constructor$TrimPattern.newInstance(KeyUtils.toResourceLocation(key), CoreReflections.instance$Component$empty, false);
} else if (VersionHelper.isOrAbove1_20_2()) {
return CoreReflections.constructor$TrimPattern.newInstance(KeyUtils.toResourceLocation(key), this.bedrockItemHolder, CoreReflections.instance$Component$empty, false);
} else {
return CoreReflections.constructor$TrimPattern.newInstance(KeyUtils.toResourceLocation(key), this.bedrockItemHolder, CoreReflections.instance$Component$empty);
}
}
private Object createTrimMaterial() throws ReflectiveOperationException {
if (VersionHelper.isOrAbove1_21_5()) {
Object assetGroup = CoreReflections.method$MaterialAssetGroup$create.invoke(null, "custom");
return CoreReflections.constructor$TrimMaterial.newInstance(assetGroup, CoreReflections.instance$Component$empty);
} else if (VersionHelper.isOrAbove1_21_4()) {
return CoreReflections.constructor$TrimMaterial.newInstance("custom", this.bedrockItemHolder, Map.of(), CoreReflections.instance$Component$empty);
} else {
return CoreReflections.constructor$TrimMaterial.newInstance("custom", this.bedrockItemHolder, 1_000_000.0f, Map.of(), CoreReflections.instance$Component$empty);
}
}
@SuppressWarnings("deprecation")
@Override
public Item<ItemStack> fromByteArray(byte[] bytes) {

View File

@@ -2,9 +2,17 @@ package net.momirealms.craftengine.bukkit.item.factory;
import net.momirealms.craftengine.bukkit.item.ComponentItemWrapper;
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
import net.momirealms.craftengine.core.entity.EquipmentSlot;
import net.momirealms.craftengine.core.item.equipment.Equipments;
import net.momirealms.craftengine.core.item.setting.EquipmentData;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.sparrow.nbt.CompoundTag;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
public class ComponentItemFactory1_21_2 extends ComponentItemFactory1_21 {
@@ -52,6 +60,18 @@ public class ComponentItemFactory1_21_2 extends ComponentItemFactory1_21 {
@Override
protected Optional<EquipmentData> equippable(ComponentItemWrapper item) {
throw new UnsupportedOperationException("Not implemented yet.");
Optional<Object> optionalData = item.getJavaComponent(ComponentTypes.EQUIPPABLE);
if (optionalData.isEmpty()) return Optional.empty();
Map<String, Object> data = MiscUtils.castToMap(optionalData.get(), false);
String slot = data.get("slot").toString();
return Optional.of(new EquipmentData(
EquipmentSlot.valueOf(slot.toUpperCase(Locale.ENGLISH)),
data.containsKey("asset_id") ? Key.of((String) data.get("asset_id")) : null,
(boolean) data.getOrDefault("dispensable", true),
(boolean) data.getOrDefault("swappable", true),
(boolean) data.getOrDefault("damage_on_hurt", true),
(boolean) data.getOrDefault("equip_on_interact", false),
data.containsKey("camera_overlay") ? Key.of((String) data.get("camera_overlay")) : null
));
}
}

View File

@@ -3588,12 +3588,37 @@ public final class CoreReflections {
);
public static final Class<?> clazz$TrimPattern = requireNonNull(
VersionHelper.isOrAbove1_21_2() ?
BukkitReflectionUtils.findReobfOrMojmapClass(
"world.item.equipment.trim.TrimPattern",
"world.item.equipment.trim.TrimPattern"
) :
BukkitReflectionUtils.findReobfOrMojmapClass(
"world.item.armortrim.TrimPattern",
"world.item.armortrim.TrimPattern"
)
);
public static final Class<?> clazz$TrimMaterial = requireNonNull(
VersionHelper.isOrAbove1_21_2() ?
BukkitReflectionUtils.findReobfOrMojmapClass(
"world.item.equipment.trim.TrimMaterial",
"world.item.equipment.trim.TrimMaterial"
) :
BukkitReflectionUtils.findReobfOrMojmapClass(
"world.item.armortrim.TrimMaterial",
"world.item.armortrim.TrimMaterial"
)
);
public static final Class<?> clazz$MaterialAssetGroup = BukkitReflectionUtils.findReobfOrMojmapClass(
"world.item.equipment.trim.MaterialAssetGroup",
"world.item.equipment.trim.MaterialAssetGroup"
);
public static final Method method$MaterialAssetGroup$create = Optional.ofNullable(clazz$MaterialAssetGroup)
.map(it -> ReflectionUtils.getStaticMethod(it, it, String.class)).orElse(null);
public static final Constructor<?> constructor$TrimPattern = requireNonNull(
VersionHelper.isOrAbove1_21_5() ?
ReflectionUtils.getConstructor(clazz$TrimPattern, clazz$ResourceLocation, clazz$Component, boolean.class) :
@@ -3601,4 +3626,12 @@ public final class CoreReflections {
ReflectionUtils.getConstructor(clazz$TrimPattern, clazz$ResourceLocation, clazz$Holder, clazz$Component, boolean.class) :
ReflectionUtils.getConstructor(clazz$TrimPattern, clazz$ResourceLocation, clazz$Holder, clazz$Component)
);
public static final Constructor<?> constructor$TrimMaterial = requireNonNull(
VersionHelper.isOrAbove1_21_5() ?
ReflectionUtils.getConstructor(clazz$TrimMaterial, clazz$MaterialAssetGroup, clazz$Component) :
VersionHelper.isOrAbove1_21_4() ?
ReflectionUtils.getConstructor(clazz$TrimMaterial, String.class, clazz$Holder, Map.class, clazz$Component) :
ReflectionUtils.getConstructor(clazz$TrimMaterial, String.class, clazz$Holder, float.class, Map.class, clazz$Component)
);
}

View File

@@ -24,6 +24,7 @@ public final class MRegistries {
public static final Object CONFIGURED_FEATURE;
public static final Object PLACED_FEATURE;
public static final Object TRIM_PATTERN;
public static final Object TRIM_MATERIAL;
@Nullable // 1.21+
public static final Object JUKEBOX_SONG;
@Nullable // 1.21+
@@ -48,6 +49,7 @@ public final class MRegistries {
Object registries$JukeboxSong = null;
Object registries$Recipe = null;
Object registries$TrimPattern = null;
Object registries$TrimMaterial = null;
for (Field field : fields) {
Type fieldType = field.getGenericType();
if (fieldType instanceof ParameterizedType paramType) {
@@ -91,6 +93,8 @@ public final class MRegistries {
registries$PlacedFeature = field.get(null);
} else if (type == CoreReflections.clazz$TrimPattern) {
registries$TrimPattern = field.get(null);
} else if (type == CoreReflections.clazz$TrimMaterial) {
registries$TrimMaterial = field.get(null);
}
}
}
@@ -111,6 +115,7 @@ public final class MRegistries {
CONFIGURED_FEATURE = requireNonNull(registries$ConfiguredFeature);
PLACED_FEATURE = requireNonNull(registries$PlacedFeature);
TRIM_PATTERN = requireNonNull(registries$TrimPattern);
TRIM_MATERIAL = requireNonNull(registries$TrimMaterial);
JUKEBOX_SONG = registries$JukeboxSong;
RECIPE = registries$Recipe;
} catch (ReflectiveOperationException e) {

View File

@@ -30,10 +30,10 @@ public class BukkitSoundManager extends AbstractSoundManager {
@Override
protected void registerSongs(Map<Key, JukeboxSong> songs) {
if (songs.isEmpty()) return;
Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.JUKEBOX_SONG);
try {
// 获取 JUKEBOX_SONG 注册表
Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.JUKEBOX_SONG);
unfreezeRegistry(registry);
CoreReflections.field$MappedRegistry$frozen.set(registry, false);
for (Map.Entry<Key, JukeboxSong> entry : songs.entrySet()) {
Key id = entry.getKey();
JukeboxSong jukeboxSong = entry.getValue();
@@ -54,17 +54,12 @@ public class BukkitSoundManager extends AbstractSoundManager {
CoreReflections.field$Holder$Reference$tags.set(holder, Set.of());
}
}
freezeRegistry(registry);
} catch (Exception e) {
plugin.logger().warn("Failed to register jukebox songs.", e);
this.plugin.logger().warn("Failed to register jukebox songs.", e);
} finally {
try {
CoreReflections.field$MappedRegistry$frozen.set(registry, true);
} catch (ReflectiveOperationException ignored) {}
}
}
private void unfreezeRegistry(Object registry) throws IllegalAccessException {
CoreReflections.field$MappedRegistry$frozen.set(registry, false);
}
private void freezeRegistry(Object registry) throws IllegalAccessException {
CoreReflections.field$MappedRegistry$frozen.set(registry, true);
}
}