diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java index 188bfcdd6..dec3c6b62 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java @@ -33,7 +33,7 @@ public class LegacyItemWrapper implements ItemWrapper { public boolean setTag(Object value, Object... path) { if (value instanceof Tag tag) { try { - Object nmsTag = FastNMS.INSTANCE.method$NbtIo$fromBytes(NBT.toBytes(tag, !VersionHelper.isOrAbove1_20_3())); + Object nmsTag = FastNMS.INSTANCE.method$NbtIo$fromBytes(NBT.toBytes(tag, true)); return this.rtagItem.set(nmsTag, path); } catch (IOException e) { CraftEngine.instance().logger().warn("Failed to set NBT tag " + Arrays.toString(path), e); @@ -49,7 +49,7 @@ public class LegacyItemWrapper implements ItemWrapper { try { // Incompatible DFU version // return this.rtagItem.add(Reflections.instance$SPARROW_NBT_OPS.convertTo(Reflections.instance$NBT_OPS, tag), path); - Object nmsTag = FastNMS.INSTANCE.method$NbtIo$fromBytes(NBT.toBytes(tag, !VersionHelper.isOrAbove1_20_3())); + Object nmsTag = FastNMS.INSTANCE.method$NbtIo$fromBytes(NBT.toBytes(tag, true)); return this.rtagItem.add(nmsTag, path); } catch (IOException e) { CraftEngine.instance().logger().warn("Failed to add NBT tag " + Arrays.toString(path), e); @@ -66,6 +66,7 @@ public class LegacyItemWrapper implements ItemWrapper { public Tag getNBTTag(Object... path) { Object tag = getExactTag(path); + if (tag == null) return null; try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(FastNMS.INSTANCE.method$NbtIo$toBytes(tag)))) { return NBT.readUnnamedTag(dis, !VersionHelper.isOrAbove1_20_3()); } catch (IOException e) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyNetworkItemHandler.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyNetworkItemHandler.java index 37081736d..01e7a45cb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyNetworkItemHandler.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyNetworkItemHandler.java @@ -5,6 +5,7 @@ import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.craftengine.core.item.NetworkItemHandler; +import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.util.AdventureHelper; @@ -42,8 +43,30 @@ public class LegacyNetworkItemHandler implements NetworkItemHandler { if (optionalCustomItem.isEmpty()) { if (!Config.interceptItem()) return Optional.empty(); return new OtherItem(wrapped).process(); + } else { + CustomItem customItem = optionalCustomItem.get(); + if (!customItem.hasClientBoundDataModifier()) { + if (!Config.interceptItem()) return Optional.empty(); + return new OtherItem(wrapped).process(); + } else { + CompoundTag tag = new CompoundTag(); + for (ItemDataModifier modifier : customItem.clientBoundDataModifiers()) { + modifier.prepareNetworkItem(wrapped, context, tag); + modifier.apply(wrapped, context); + } + if (Config.interceptItem()) { + if (!tag.containsKey("display.Name")) { + processCustomName(wrapped, tag::put); + } + if (!tag.containsKey("display.Lore")) { + processLore(wrapped, tag::put); + } + } + if (tag.isEmpty()) return Optional.empty(); + wrapped.setTag(tag, NETWORK_ITEM_TAG); + return Optional.of(wrapped); + } } - return Optional.empty(); } public static boolean processCustomName(Item item, BiConsumer callback) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java index f3bd26abd..ace94cb32 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java @@ -810,7 +810,7 @@ public class BukkitInjector { if (!previous.isEmpty()) { holder.ceChunk().setDirty(true); if (Config.enableLightSystem()) { - updateLightIfChanged(holder, previous.vanillaBlockState().handle(), newState, y, z, x); + updateLightIfChanged(holder, previousState, newState, newState, x, y, z); } } } else { @@ -820,7 +820,7 @@ public class BukkitInjector { holder.ceChunk().setDirty(true); // 如果新方块的光照属性和客户端认为的不同 if (Config.enableLightSystem() && !immutableBlockState.isEmpty()) { - updateLightIfChanged(holder, immutableBlockState.vanillaBlockState().handle(), newState, y, z, x); + updateLightIfChanged(holder, previousState, immutableBlockState.vanillaBlockState().handle(), newState, x, y, z); } } } catch (Exception e) { @@ -828,9 +828,17 @@ public class BukkitInjector { } } - protected static void updateLightIfChanged(@This InjectedHolder thisObj, Object oldState, Object newState, int y, int z, int x) { + protected static void updateLightIfChanged(@This InjectedHolder thisObj, Object oldServerSideState, Object clientSideState, Object serverSideState, int x, int y, int z) { CEWorld world = thisObj.ceChunk().world(); - if (FastNMS.INSTANCE.method$LightEngine$hasDifferentLightProperties(oldState, newState, world.world().serverWorld(), LocationUtils.toBlockPos(x, y, z))) { + Object blockPos = LocationUtils.toBlockPos(x, y, z); + Object serverWorld = world.world().serverWorld(); + if (clientSideState != serverSideState && FastNMS.INSTANCE.method$LightEngine$hasDifferentLightProperties(clientSideState, serverSideState, serverWorld, blockPos)) { + SectionPos sectionPos = thisObj.cePos(); + List pos = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, 15); + world.sectionLightUpdated(pos); + return; + } + if (FastNMS.INSTANCE.method$LightEngine$hasDifferentLightProperties(oldServerSideState, serverSideState, serverWorld, blockPos)) { SectionPos sectionPos = thisObj.cePos(); List pos = SectionPosUtils.calculateAffectedRegions((sectionPos.x() << 4) + x, (sectionPos.y() << 4) + y, (sectionPos.z() << 4) + z, 15); world.sectionLightUpdated(pos); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index c103fe711..6587d5cac 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -2554,7 +2554,7 @@ public class Reflections { public static final Method method$BlockBehaviour$getCollisionShape = requireNonNull( ReflectionUtils.getDeclaredMethod( - clazz$BlockBehaviour, clazz$VoxelShape, new String[]{"getCollisionShape", "c"}, clazz$BlockState, clazz$BlockGetter, clazz$BlockPos, clazz$CollisionContext + clazz$BlockBehaviour, clazz$VoxelShape, new String[]{"getCollisionShape", VersionHelper.isOrAbove1_20_3() ? "b" : "c"}, clazz$BlockState, clazz$BlockGetter, clazz$BlockPos, clazz$CollisionContext ) ); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/NetworkItemHandler.java b/core/src/main/java/net/momirealms/craftengine/core/item/NetworkItemHandler.java index 263f74abf..09635b18d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/NetworkItemHandler.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/NetworkItemHandler.java @@ -13,7 +13,7 @@ import java.util.Optional; public interface NetworkItemHandler { Operation[] BY_INDEX = new Operation[] {Operation.ADD, Operation.REMOVE, Operation.RESET}; - String NETWORK_ITEM_TAG = "craftengine:network"; + String NETWORK_ITEM_TAG = "craftengine:network_modifiers"; String NETWORK_OPERATION = "type"; String NETWORK_VALUE = "value"; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomModelDataModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomModelDataModifier.java index 359b7b50d..fb6ec08d1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomModelDataModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomModelDataModifier.java @@ -34,6 +34,13 @@ public class CustomModelDataModifier implements ItemDataModifier { } else { networkData.put(ComponentKeys.CUSTOM_MODEL_DATA.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } + } else { + Tag previous = item.getNBTTag("CustomModelData"); + if (previous != null) { + networkData.put("CustomModelData", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put("CustomModelData", NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java index aca62cdcd..d16b5281b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java @@ -36,6 +36,13 @@ public class CustomNameModifier implements ItemDataModifier { } else { networkData.put(ComponentKeys.CUSTOM_NAME.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } + } else { + Tag previous = item.getNBTTag("display", "Name"); + if (previous != null) { + networkData.put("display.Name", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put("display.Name", NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentModifier.java index 54c5ad10f..88a06c183 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentModifier.java @@ -1,9 +1,9 @@ package net.momirealms.craftengine.core.item.modifier; -import net.momirealms.craftengine.core.item.Enchantment; -import net.momirealms.craftengine.core.item.Item; -import net.momirealms.craftengine.core.item.ItemBuildContext; -import net.momirealms.craftengine.core.item.ItemKeys; +import net.momirealms.craftengine.core.item.*; +import net.momirealms.craftengine.core.util.VersionHelper; +import net.momirealms.sparrow.nbt.CompoundTag; +import net.momirealms.sparrow.nbt.Tag; import java.util.List; @@ -27,4 +27,41 @@ public class EnchantmentModifier implements ItemDataModifier { item.setEnchantments(this.enchantments); } } + + @Override + public void prepareNetworkItem(Item item, ItemBuildContext context, CompoundTag networkData) { + if (item.vanillaId().equals(ItemKeys.ENCHANTED_BOOK)) { + if (VersionHelper.isOrAbove1_20_5()) { + Tag previous = item.getNBTComponent(ComponentKeys.STORED_ENCHANTMENTS); + if (previous != null) { + networkData.put(ComponentKeys.STORED_ENCHANTMENTS.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put(ComponentKeys.STORED_ENCHANTMENTS.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } + } else { + Tag previous = item.getNBTTag("StoredEnchantments"); + if (previous != null) { + networkData.put("StoredEnchantments", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put("StoredEnchantments", NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } + } + } else { + if (VersionHelper.isOrAbove1_20_5()) { + Tag previous = item.getNBTComponent(ComponentKeys.ENCHANTMENTS); + if (previous != null) { + networkData.put(ComponentKeys.ENCHANTMENTS.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put(ComponentKeys.ENCHANTMENTS.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } + } else { + Tag previous = item.getNBTTag("Enchantments"); + if (previous != null) { + networkData.put("Enchantments", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put("Enchantments", NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } + } + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java index 1655179e4..f59c44abb 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java @@ -36,6 +36,13 @@ public class ItemNameModifier implements ItemDataModifier { } else { networkData.put(ComponentKeys.ITEM_NAME.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } + } else { + Tag previous = item.getNBTTag("display", "Name"); + if (previous != null) { + networkData.put("display.Name", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put("display.Name", NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/LoreModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/LoreModifier.java index 0b2a8e412..6328fe5c8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/LoreModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/LoreModifier.java @@ -39,6 +39,13 @@ public class LoreModifier implements ItemDataModifier { } else { networkData.put(ComponentKeys.LORE.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } + } else { + Tag previous = item.getNBTTag("display", "Lore"); + if (previous != null) { + networkData.put("display.Lore", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put("display.Lore", NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TagsModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TagsModifier.java index c49ae4cbc..582fce937 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TagsModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TagsModifier.java @@ -2,8 +2,11 @@ package net.momirealms.craftengine.core.item.modifier; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemBuildContext; +import net.momirealms.craftengine.core.item.NetworkItemHandler; import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.util.TypeUtils; +import net.momirealms.sparrow.nbt.CompoundTag; +import net.momirealms.sparrow.nbt.Tag; import java.util.LinkedHashMap; import java.util.Map; @@ -26,13 +29,26 @@ public class TagsModifier implements ItemDataModifier { @Override public void apply(Item item, ItemBuildContext context) { - for (Map.Entry entry : arguments.entrySet()) { + for (Map.Entry entry : this.arguments.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); item.setTag(value, key); } } + // TODO NOT PERFECT + @Override + public void prepareNetworkItem(Item item, ItemBuildContext context, CompoundTag networkData) { + for (Map.Entry entry : this.arguments.entrySet()) { + Tag previous = item.getNBTTag(entry.getKey()); + if (previous != null) { + networkData.put(entry.getKey(), NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put(entry.getKey(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } + } + } + private static Map mapToMap(final Map source) { Map resultMap = new LinkedHashMap<>(); recursiveMapProcessing(source, resultMap); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java index e3a9e5cf1..4d8a4facd 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java @@ -1,8 +1,9 @@ package net.momirealms.craftengine.core.item.modifier; -import net.momirealms.craftengine.core.item.Item; -import net.momirealms.craftengine.core.item.ItemBuildContext; -import net.momirealms.craftengine.core.item.Trim; +import net.momirealms.craftengine.core.item.*; +import net.momirealms.craftengine.core.util.VersionHelper; +import net.momirealms.sparrow.nbt.CompoundTag; +import net.momirealms.sparrow.nbt.Tag; public class TrimModifier implements ItemDataModifier { private final String material; @@ -22,4 +23,23 @@ public class TrimModifier implements ItemDataModifier { public void apply(Item item, ItemBuildContext context) { item.trim(new Trim(this.material, this.pattern)); } + + @Override + public void prepareNetworkItem(Item item, ItemBuildContext context, CompoundTag networkData) { + if (VersionHelper.isOrAbove1_20_5()) { + Tag previous = item.getNBTComponent(ComponentKeys.TRIM); + if (previous != null) { + networkData.put(ComponentKeys.TRIM.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put(ComponentKeys.TRIM.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } + } else { + Tag previous = item.getNBTTag("Trim"); + if (previous != null) { + networkData.put("Trim", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put("Trim", NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java index 3e3f2b93c..34c58ed56 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java @@ -34,6 +34,13 @@ public class UnbreakableModifier implements ItemDataModifier { } else { networkData.put(ComponentKeys.UNBREAKABLE.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } + } else { + Tag previous = item.getNBTTag("Unbreakable"); + if (previous != null) { + networkData.put("Unbreakable", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); + } else { + networkData.put("Unbreakable", NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); + } } } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index d993b75d8..bad5c544c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -147,21 +147,26 @@ public abstract class AbstractPackManager implements PackManager { @Override public void load() { - List> list = Config.instance().settings().getMapList("resource-pack.delivery.hosting"); - if (list == null || list.isEmpty()) { - this.resourcePackHost = NoneHost.INSTANCE; + Object hostingObj = Config.instance().settings().get("resource-pack.delivery.hosting"); + Map arguments; + if (hostingObj instanceof Map) { + arguments = MiscUtils.castToMap(hostingObj, false); + } else if (hostingObj instanceof List list && !list.isEmpty()) { + arguments = MiscUtils.castToMap(list.get(0), false); } else { - try { - // we might add multiple host methods in future versions - this.resourcePackHost = ResourcePackHosts.fromMap(MiscUtils.castToMap(list.get(0), false)); - } catch (LocalizedException e) { - if (e instanceof LocalizedResourceConfigException exception) { - exception.setPath(plugin.dataFolderPath().resolve("config.yml")); - e.setArgument(1, "hosting"); - } - TranslationManager.instance().log(e.node(), e.arguments()); - this.resourcePackHost = NoneHost.INSTANCE; + this.resourcePackHost = NoneHost.INSTANCE; + return; + } + try { + // we might add multiple host methods in future versions + this.resourcePackHost = ResourcePackHosts.fromMap(arguments); + } catch (LocalizedException e) { + if (e instanceof LocalizedResourceConfigException exception) { + exception.setPath(plugin.dataFolderPath().resolve("config.yml")); + e.setArgument(1, "hosting"); } + TranslationManager.instance().log(e.node(), e.arguments()); + this.resourcePackHost = NoneHost.INSTANCE; } }