diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java index ccc9c42cc..5fafae5db 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurniture.java @@ -137,6 +137,7 @@ public class BukkitFurniture implements Furniture { @NotNull public Object spawnPacket(Player player) { // TODO hasPermission might be slow, can we use a faster way in the future? + // TODO Make it based on conditions. So we can dynamically control which furniture should be sent to the player if (!this.minimized || player.hasPermission(FurnitureManager.FURNITURE_ADMIN_NODE)) { return this.cachedSpawnPacket; } else { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index 2f72badf9..583162725 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -1,5 +1,9 @@ package net.momirealms.craftengine.bukkit.item; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior; import net.momirealms.craftengine.bukkit.item.behavior.FlintAndSteelItemBehavior; import net.momirealms.craftengine.bukkit.item.factory.BukkitItemFactory; @@ -23,6 +27,7 @@ import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigExce import net.momirealms.craftengine.core.registry.BuiltInRegistries; import net.momirealms.craftengine.core.registry.Holder; import net.momirealms.craftengine.core.registry.WritableRegistry; +import net.momirealms.craftengine.core.util.GsonHelper; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ResourceKey; import net.momirealms.craftengine.core.util.VersionHelper; @@ -34,6 +39,9 @@ import org.bukkit.event.HandlerList; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; public class BukkitItemManager extends AbstractItemManager { @@ -143,7 +151,9 @@ public class BukkitItemManager extends AbstractItemManager { protected void registerArmorTrimPattern(Collection equipments) { if (equipments.isEmpty()) return; this.lastRegisteredPatterns = new HashSet<>(equipments); - this.lastRegisteredPatterns.add(Config.sacrificedAssetId()); + // 可能还没加载 + if (Config.sacrificedAssetId() != null) + this.lastRegisteredPatterns.add(Config.sacrificedAssetId()); Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.TRIM_PATTERN); try { CoreReflections.field$MappedRegistry$frozen.set(registry, false); @@ -168,9 +178,50 @@ public class BukkitItemManager extends AbstractItemManager { } private void persistLastRegisteredPatterns() { + Path persistTrimPatternPath = this.plugin.dataFolderPath() + .resolve("cache") + .resolve("trim_patterns.json"); + try { + Files.createDirectories(persistTrimPatternPath.getParent()); + JsonObject json = new JsonObject(); + JsonArray jsonElements = new JsonArray(); + for (Key key : this.lastRegisteredPatterns) { + jsonElements.add(new JsonPrimitive(key.toString())); + } + json.add("patterns", jsonElements); + if (jsonElements.isEmpty()) { + if (Files.exists(persistTrimPatternPath)) { + Files.delete(persistTrimPatternPath); + } + } else { + GsonHelper.writeJsonFile(json, persistTrimPatternPath); + } + } catch (IOException e) { + this.plugin.logger().warn("Failed to persist registered trim patterns.", e); + } } + // 需要持久化存储上一次注册的新trim类型,如果注册晚了,加载世界可能导致一些物品损坏 private void loadLastRegisteredPatterns() { + Path persistTrimPatternPath = this.plugin.dataFolderPath() + .resolve("cache") + .resolve("trim_patterns.json"); + if (Files.exists(persistTrimPatternPath) && Files.isRegularFile(persistTrimPatternPath)) { + try { + JsonObject cache = GsonHelper.readJsonFile(persistTrimPatternPath).getAsJsonObject(); + JsonArray patterns = cache.getAsJsonArray("patterns"); + Set trims = new HashSet<>(); + for (JsonElement element : patterns) { + if (element instanceof JsonPrimitive primitive) { + trims.add(Key.of(primitive.getAsString())); + } + } + this.registerArmorTrimPattern(trims); + this.lastRegisteredPatterns = trims; + } catch (IOException e) { + this.plugin.logger().warn("Failed to load registered trim patterns.", e); + } + } } private void registerCustomTrimMaterial() { 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 871bbcb32..ecbcde058 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 @@ -27,7 +27,7 @@ import java.util.Optional; import java.util.function.BiConsumer; @SuppressWarnings("DuplicatedCode") -public class LegacyNetworkItemHandler implements NetworkItemHandler { +public final class LegacyNetworkItemHandler implements NetworkItemHandler { @Override public Optional> c2s(Item wrapped) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java index 3d3ab0837..35a822401 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java @@ -15,12 +15,14 @@ import net.momirealms.craftengine.bukkit.util.ComponentUtils; import net.momirealms.craftengine.bukkit.util.ItemUtils; import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils; import net.momirealms.craftengine.core.item.*; +import net.momirealms.craftengine.core.item.equipment.TrimBasedEquipment; import net.momirealms.craftengine.core.item.recipe.*; import net.momirealms.craftengine.core.item.recipe.Recipe; import net.momirealms.craftengine.core.item.recipe.input.CraftingInput; import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput; import net.momirealms.craftengine.core.item.recipe.input.SmithingInput; import net.momirealms.craftengine.core.item.setting.AnvilRepairItem; +import net.momirealms.craftengine.core.item.setting.ItemEquipment; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.registry.BuiltInRegistries; @@ -933,6 +935,24 @@ public class RecipeEventListener implements Listener { } } + @EventHandler(ignoreCancelled = true) + public void onSmithingTrim(PrepareSmithingEvent event) { + SmithingInventory inventory = event.getInventory(); + if (!(inventory.getRecipe() instanceof SmithingTrimRecipe)) return; + ItemStack equipment = inventory.getInputEquipment(); + if (equipment == null) return; + Item wrappedEquipment = this.itemManager.wrap(equipment); + Optional> optionalCustomItem = wrappedEquipment.getCustomItem(); + if (optionalCustomItem.isEmpty()) return; + CustomItem customItem = optionalCustomItem.get(); + ItemEquipment itemEquipmentSettings = customItem.settings().equipment(); + if (itemEquipmentSettings == null) return; + // 不允许trim类型的盔甲再次被使用trim + if (itemEquipmentSettings.equipment() instanceof TrimBasedEquipment) { + event.setResult(null); + } + } + @EventHandler(ignoreCancelled = true) public void onSmithingTransform(PrepareSmithingEvent event) { if (!Config.enableRecipeSystem()) return; 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 8518f6dcd..6cdb33ec7 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 @@ -138,6 +138,7 @@ public class BukkitCraftEngine extends CraftEngine { super.onPluginLoad(); super.blockManager.init(); super.networkManager = new BukkitNetworkManager(this); + super.itemManager = new BukkitItemManager(this); this.successfullyLoaded = true; super.compatibilityManager().onLoad(); } @@ -182,7 +183,6 @@ public class BukkitCraftEngine extends CraftEngine { PacketConsumers.initEntities(RegistryUtils.currentEntityTypeRegistrySize()); super.packManager = new BukkitPackManager(this); super.senderFactory = new BukkitSenderFactory(this); - super.itemManager = new BukkitItemManager(this); super.recipeManager = new BukkitRecipeManager(this); super.commandManager = new BukkitCommandManager(this); super.itemBrowserManager = new ItemBrowserManagerImpl(this); diff --git a/common-files/src/main/resources/config.yml b/common-files/src/main/resources/config.yml index 08879aeec..0f9f2fafa 100644 --- a/common-files/src/main/resources/config.yml +++ b/common-files/src/main/resources/config.yml @@ -76,9 +76,7 @@ resource-pack: # Send the resource pack on joining the server send-on-join: true kick-if-declined: true - prompt: | - To fully experience our server, - please accept our custom resource pack. + prompt: "To fully experience our server,please accept our custom resource pack." # If you are hosting the resource pack by yourself, replace `localhost` with your server ip otherwise it would only work on your local pc # If using BungeeCord or Velocity, consider using a proxy-side plugin to handle resource pack delivery. # Read this page for more host types: https://mo-mi.gitbook.io/xiaomomi-plugins/craftengine/plugin-wiki/craftengine/resource-pack/host @@ -140,7 +138,7 @@ resource-pack: item: # Make custom-model-data and item-model clientside by default - client-bound-model: false + client-bound-model: true equipment: # The sacrificed-vanilla-armor argument determines which vanilla armor gets completely removed (loses all its trims) diff --git a/common-files/src/main/resources/resources/default/configuration/items.yml b/common-files/src/main/resources/resources/default/configuration/items.yml index 5bd344e6e..d9a6eeda8 100644 --- a/common-files/src/main/resources/resources/default/configuration/items.yml +++ b/common-files/src/main/resources/resources/default/configuration/items.yml @@ -307,15 +307,21 @@ templates: - default:topaz_tools equipment: asset-id: default:topaz + $$>=1.21.2: + slot: ${slot} model: template: default:model/armor_trim equipments#topaz: - default:topaz: - type: - $$>=1.21.2: component - $$<1.21.2: trim - humanoid: minecraft:entity/equipment/humanoid/topaz - humanoid-leggings: minecraft:entity/equipment/humanoid_leggings/topaz + $$>=1.21.2: + default:topaz: + type: component + humanoid: minecraft:topaz + humanoid-leggings: minecraft:topaz + $$<1.21.2: + default:topaz: + type: trim + humanoid: minecraft:entity/equipment/humanoid/topaz + humanoid-leggings: minecraft:entity/equipment/humanoid_leggings/topaz recipes#topaz: default:topaz_shovel: type: shaped @@ -377,49 +383,48 @@ recipes#topaz: result: id: default:topaz_pickaxe count: 1 - $$>=1.21.2#armor: - default:topaz_helmet: - type: shaped - pattern: - - AAA - - A A - ingredients: - A: default:topaz - result: - id: default:topaz_helmet - count: 1 - default:topaz_chestplate: - type: shaped - pattern: - - A A - - AAA - - AAA - ingredients: - A: default:topaz - result: - id: default:topaz_chestplate - count: 1 - default:topaz_leggings: - type: shaped - pattern: - - AAA - - A A - - A A - ingredients: - A: default:topaz - result: - id: default:topaz_leggings - count: 1 - default:topaz_boots: - type: shaped - pattern: - - A A - - A A - ingredients: - A: default:topaz - result: - id: default:topaz_boots - count: 1 + default:topaz_helmet: + type: shaped + pattern: + - AAA + - A A + ingredients: + A: default:topaz + result: + id: default:topaz_helmet + count: 1 + default:topaz_chestplate: + type: shaped + pattern: + - A A + - AAA + - AAA + ingredients: + A: default:topaz + result: + id: default:topaz_chestplate + count: 1 + default:topaz_leggings: + type: shaped + pattern: + - AAA + - A A + - A A + ingredients: + A: default:topaz + result: + id: default:topaz_leggings + count: 1 + default:topaz_boots: + type: shaped + pattern: + - A A + - A A + ingredients: + A: default:topaz + result: + id: default:topaz_boots + count: 1 default:topaz_bow: type: smithing_transform base: minecraft:bow diff --git a/common-files/src/main/resources/resources/legacy_armor/pack.yml b/common-files/src/main/resources/resources/legacy_armor/pack.yml index d5addb0cb..f73b20dc9 100644 --- a/common-files/src/main/resources/resources/legacy_armor/pack.yml +++ b/common-files/src/main/resources/resources/legacy_armor/pack.yml @@ -1,6 +1,6 @@ author: XiaoMoMi version: 0.0.1 -description: +description: Fix broken vanilla armor namespace: minecraft enable: $$>=1.21.2: false diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index a9b53c713..40c7c0b65 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -390,6 +390,7 @@ warning.config.resource_pack.generation.missing_item_model: "Item 'Block state '' is missing model file: ''" warning.config.resource_pack.generation.missing_parent_model: "Model '' cannot find parent model: ''" warning.config.resource_pack.generation.malformatted_json: "Json file '' is malformatted." +warning.config.resource_pack.generation.missing_equipment_texture: "Equipment '' is missing texture ''" warning.config.resource_pack.invalid_overlay_format: "Issue found in config.yml at 'resource-pack.overlay-format' - Invalid overlay format ''. Overlay format must contain the placeholder '{version}'." warning.config.equipment.duplicate: "Issue found in file - Duplicated equipment ''. Please check if there is the same configuration in other files." warning.config.equipment.missing_type: "Issue found in file - The equipment '' is missing the required 'type' argument." diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index 5302a77f9..53a4041be 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -304,7 +304,7 @@ warning.config.loot_table.entry.item.missing_item: "在文件 warning.config.loot_table.condition.missing_type: "在文件 发现问题 - '' 的战利品表配置错误 某个条件缺少必需的 'type' 参数" warning.config.loot_table.condition.invalid_type: "在文件 发现问题 - '' 的战利品表配置错误 某个条件使用了无效的条件类型 ''" warning.config.host.missing_type: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 缺少必需的 'type' 参数" -warning.config.host.invalid_type: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 无效的托管类型 '' 请参考 https://mo-mi.gitbook.io/xiaomomi-plugins/craftengine/plugin-wiki/craftengine/resource-pack/host" +warning.config.host.invalid_type: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 无效的托管类型 '' 请参考 https://mo-mi.gitbook.io/xiaomomi-plugins/craftengine/plugin-wiki/craftengine/resource-pack/host" warning.config.host.external.missing_url: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - 外部托管缺少必需的 'url' 参数" warning.config.host.alist.missing_api_url: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - Alist 托管缺少必需的 'api-url' 参数" warning.config.host.alist.missing_username: "在 config.yml 的 'resource-pack.delivery.hosting' 处发现问题 - Alist 托管缺少必需的 'username' 参数或环境变量 'CE_ALIST_USERNAME'" @@ -390,8 +390,9 @@ warning.config.resource_pack.generation.missing_item_model: "物品'方块状态''缺少模型文件: ''" warning.config.resource_pack.generation.missing_parent_model: "模型''找不到父级模型文件: ''" warning.config.resource_pack.generation.malformatted_json: "Json文件 '' 格式错误." +warning.config.resource_pack.generation.missing_equipment_texture: "装备 '' 缺少纹理 ''" warning.config.resource_pack.invalid_overlay_format: "在 config.yml 的 'resource-pack.overlay-format' 处发现问题 - 无效的overlay格式 ''. Overlay格式必须包含占位符 '{version}'." -warning.config.equipment.duplicate: "Issue found in file - Duplicated equipment ''. Please check if there is the same configuration in other files." -warning.config.equipment.missing_type: "Issue found in file - The equipment '' is missing the required 'type' argument." -warning.config.equipment.invalid_type: "Issue found in file - The equipment '' is using an invalid 'type' argument." -warning.config.equipment.invalid_sacrificed_armor: "Issue found in config.yml at 'equipment.sacrificed-vanilla-armor' - Invalid vanilla armor type ''." \ No newline at end of file +warning.config.equipment.duplicate: "在文件 发现问题 - 重复的装备配置 ''。请检查其他文件中是否存在相同配置" +warning.config.equipment.missing_type: "在文件 发现问题 - 装备 '' 缺少必需的 'type' 参数" +warning.config.equipment.invalid_type: "在文件 发现问题 - 装备 '' 使用了无效的 'type' 参数" +warning.config.equipment.invalid_sacrificed_armor: "在 config.yml 的 'equipment.sacrificed-vanilla-armor' 处发现问题 - 无效的原版盔甲类型 ''" \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractCustomItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractCustomItem.java index 2b3ca7080..736f2c6a2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractCustomItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractCustomItem.java @@ -1,6 +1,5 @@ package net.momirealms.craftengine.core.item; -import com.google.common.collect.ImmutableMap; import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; import net.momirealms.craftengine.core.plugin.context.PlayerOptionalContext; @@ -20,9 +19,7 @@ public abstract class AbstractCustomItem implements CustomItem { protected final Key material; protected final Key clientBoundMaterial; protected final ItemDataModifier[] modifiers; - protected final Map> modifierMap; protected final ItemDataModifier[] clientBoundModifiers; - protected final Map> clientBoundModifierMap; protected final List behaviors; protected final ItemSettings settings; protected final Map>> events; @@ -44,13 +41,6 @@ public abstract class AbstractCustomItem implements CustomItem { this.clientBoundModifiers = clientBoundModifiers.toArray(new ItemDataModifier[0]); this.behaviors = List.copyOf(behaviors); this.settings = settings; - ImmutableMap.Builder> modifierMapBuilder = ImmutableMap.builder(); - for (ItemDataModifier modifier : modifiers) { - modifierMapBuilder.put(modifier.name(), modifier); - } - this.modifierMap = modifierMapBuilder.build(); - ImmutableMap.Builder> clientSideModifierMapBuilder = ImmutableMap.builder(); - this.clientBoundModifierMap = clientSideModifierMapBuilder.build(); } @Override @@ -85,11 +75,6 @@ public abstract class AbstractCustomItem implements CustomItem { return this.modifiers; } - @Override - public Map> dataModifierMap() { - return this.modifierMap; - } - @Override public boolean hasClientBoundDataModifier() { return this.clientBoundModifiers.length != 0; @@ -100,11 +85,6 @@ public abstract class AbstractCustomItem implements CustomItem { return this.clientBoundModifiers; } - @Override - public Map> clientBoundDataModifierMap() { - return this.clientBoundModifierMap; - } - @Override public ItemSettings settings() { return this.settings; 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 c6691d78b..5ee3e5a45 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 @@ -4,9 +4,7 @@ import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.behavior.ItemBehaviors; import net.momirealms.craftengine.core.item.data.Enchantment; import net.momirealms.craftengine.core.item.data.JukeboxPlayable; -import net.momirealms.craftengine.core.item.equipment.Equipment; -import net.momirealms.craftengine.core.item.equipment.Equipments; -import net.momirealms.craftengine.core.item.equipment.TrimBasedEquipment; +import net.momirealms.craftengine.core.item.equipment.*; import net.momirealms.craftengine.core.item.modifier.*; import net.momirealms.craftengine.core.item.setting.EquipmentData; import net.momirealms.craftengine.core.pack.LoadingSequence; @@ -289,6 +287,17 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl } } + public void addOrMergeEquipment(ComponentBasedEquipment equipment) { + Equipment previous = this.equipments.get(equipment.assetId()); + if (previous instanceof ComponentBasedEquipment another) { + for (Map.Entry> entry : equipment.layers().entrySet()) { + another.addLayer(entry.getKey(), entry.getValue()); + } + } else { + this.equipments.put(equipment.assetId(), equipment); + } + } + public class ItemParser implements ConfigParser { public static final String[] CONFIG_SECTION_NAME = new String[] {"items", "item"}; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java index f3dd338a7..1381c9a71 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java @@ -25,14 +25,10 @@ public interface CustomItem extends BuildableItem { ItemDataModifier[] dataModifiers(); - Map> dataModifierMap(); - boolean hasClientBoundDataModifier(); ItemDataModifier[] clientBoundDataModifiers(); - Map> clientBoundDataModifierMap(); - ItemSettings settings(); default boolean is(Key tag) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java index dba5abe21..e9199502e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java @@ -320,6 +320,7 @@ public class ItemSettings { Map args = MiscUtils.castToMap(value, false); EquipmentData data = EquipmentData.fromMap(args); ComponentBasedEquipment componentBasedEquipment = ComponentBasedEquipment.FACTORY.create(data.assetId(), args); + ((AbstractItemManager) CraftEngine.instance().itemManager()).addOrMergeEquipment(componentBasedEquipment); ItemEquipment itemEquipment = new ItemEquipment(Tristate.FALSE, data, componentBasedEquipment); return settings -> settings.equipment(itemEquipment); })); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/HideTooltipModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/HideTooltipModifier.java index 368862879..e3a3688d7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/HideTooltipModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/HideTooltipModifier.java @@ -11,7 +11,10 @@ import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.sparrow.nbt.CompoundTag; import net.momirealms.sparrow.nbt.Tag; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; 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 a4d5e8b6b..dbaad936f 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 @@ -1188,74 +1188,7 @@ public abstract class AbstractPackManager implements PackManager { for (Equipment equipment : this.plugin.itemManager().equipments().values()) { if (equipment instanceof ComponentBasedEquipment componentBasedEquipment) { // 现代的盔甲生成 - Key assetId = componentBasedEquipment.assetId(); - if (Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_4)) { - Path equipmentPath = generatedPackPath - .resolve("assets") - .resolve(assetId.namespace()) - .resolve("equipment") - .resolve(assetId.value() + ".json"); - - JsonObject equipmentJson = null; - if (Files.exists(equipmentPath)) { - try (BufferedReader reader = Files.newBufferedReader(equipmentPath)) { - equipmentJson = JsonParser.parseReader(reader).getAsJsonObject(); - } catch (IOException e) { - plugin.logger().warn("Failed to load existing sounds.json", e); - return; - } - } - if (equipmentJson != null) { - equipmentJson = GsonHelper.deepMerge(equipmentJson, componentBasedEquipment.get()); - } else { - equipmentJson = componentBasedEquipment.get(); - } - try { - Files.createDirectories(equipmentPath.getParent()); - } catch (IOException e) { - plugin.logger().severe("Error creating " + equipmentPath.toAbsolutePath()); - return; - } - try { - GsonHelper.writeJsonFile(equipmentJson, equipmentPath); - } catch (IOException e) { - this.plugin.logger().severe("Error writing equipment file", e); - } - } - if (Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_2) && Config.packMinVersion().isBelow(MinecraftVersions.V1_21_4)) { - Path equipmentPath = generatedPackPath - .resolve("assets") - .resolve(assetId.namespace()) - .resolve("models") - .resolve("equipment") - .resolve(assetId.value() + ".json"); - - JsonObject equipmentJson = null; - if (Files.exists(equipmentPath)) { - try (BufferedReader reader = Files.newBufferedReader(equipmentPath)) { - equipmentJson = JsonParser.parseReader(reader).getAsJsonObject(); - } catch (IOException e) { - plugin.logger().warn("Failed to load existing sounds.json", e); - return; - } - } - if (equipmentJson != null) { - equipmentJson = GsonHelper.deepMerge(equipmentJson, componentBasedEquipment.get()); - } else { - equipmentJson = componentBasedEquipment.get(); - } - try { - Files.createDirectories(equipmentPath.getParent()); - } catch (IOException e) { - plugin.logger().severe("Error creating " + equipmentPath.toAbsolutePath()); - return; - } - try { - GsonHelper.writeJsonFile(equipmentJson, equipmentPath); - } catch (IOException e) { - this.plugin.logger().severe("Error writing equipment file", e); - } - } + processComponentBasedEquipment(componentBasedEquipment, generatedPackPath); } else if (equipment instanceof TrimBasedEquipment trimBasedEquipment) { Key assetId = trimBasedEquipment.assetId(); Pair result = processTrimBasedEquipment(trimBasedEquipment, generatedPackPath); @@ -1423,6 +1356,77 @@ public abstract class AbstractPackManager implements PackManager { } } + private void processComponentBasedEquipment(ComponentBasedEquipment componentBasedEquipment, Path generatedPackPath) { + Key assetId = componentBasedEquipment.assetId(); + if (Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_4)) { + Path equipmentPath = generatedPackPath + .resolve("assets") + .resolve(assetId.namespace()) + .resolve("equipment") + .resolve(assetId.value() + ".json"); + + JsonObject equipmentJson = null; + if (Files.exists(equipmentPath)) { + try (BufferedReader reader = Files.newBufferedReader(equipmentPath)) { + equipmentJson = JsonParser.parseReader(reader).getAsJsonObject(); + } catch (IOException e) { + plugin.logger().warn("Failed to load existing sounds.json", e); + return; + } + } + if (equipmentJson != null) { + equipmentJson = GsonHelper.deepMerge(equipmentJson, componentBasedEquipment.get()); + } else { + equipmentJson = componentBasedEquipment.get(); + } + try { + Files.createDirectories(equipmentPath.getParent()); + } catch (IOException e) { + plugin.logger().severe("Error creating " + equipmentPath.toAbsolutePath()); + return; + } + try { + GsonHelper.writeJsonFile(equipmentJson, equipmentPath); + } catch (IOException e) { + this.plugin.logger().severe("Error writing equipment file", e); + } + } + if (Config.packMaxVersion().isAtOrAbove(MinecraftVersions.V1_21_2) && Config.packMinVersion().isBelow(MinecraftVersions.V1_21_4)) { + Path equipmentPath = generatedPackPath + .resolve("assets") + .resolve(assetId.namespace()) + .resolve("models") + .resolve("equipment") + .resolve(assetId.value() + ".json"); + + JsonObject equipmentJson = null; + if (Files.exists(equipmentPath)) { + try (BufferedReader reader = Files.newBufferedReader(equipmentPath)) { + equipmentJson = JsonParser.parseReader(reader).getAsJsonObject(); + } catch (IOException e) { + plugin.logger().warn("Failed to load existing sounds.json", e); + return; + } + } + if (equipmentJson != null) { + equipmentJson = GsonHelper.deepMerge(equipmentJson, componentBasedEquipment.get()); + } else { + equipmentJson = componentBasedEquipment.get(); + } + try { + Files.createDirectories(equipmentPath.getParent()); + } catch (IOException e) { + plugin.logger().severe("Error creating " + equipmentPath.toAbsolutePath()); + return; + } + try { + GsonHelper.writeJsonFile(equipmentJson, equipmentPath); + } catch (IOException e) { + this.plugin.logger().severe("Error writing equipment file", e); + } + } + } + @Nullable private Pair processTrimBasedEquipment(TrimBasedEquipment trimBasedEquipment, Path generatedPackPath) { Key assetId = trimBasedEquipment.assetId(); @@ -1439,7 +1443,7 @@ public abstract class AbstractPackManager implements PackManager { .resolve("textures") .resolve(humanoidResourceLocation.value() + ".png"); if (!Files.exists(texture) || !Files.isRegularFile(texture)) { - // todo 说话 + TranslationManager.instance().log("warning.config.resource_pack.generation.missing_equipment_texture", assetId.asString(), texture.toString()); return null; } boolean shouldPreserve = false; @@ -1498,7 +1502,7 @@ public abstract class AbstractPackManager implements PackManager { .resolve("textures") .resolve(humanoidLeggingsResourceLocation.value() + ".png"); if (!Files.exists(texture) && !Files.isRegularFile(texture)) { - // todo 说话 + TranslationManager.instance().log("warning.config.resource_pack.generation.missing_equipment_texture", assetId.asString(), texture.toString()); return null; } boolean shouldPreserve = false; diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/AlistHost.java b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/AlistHost.java index 74abddf6a..674fbf908 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/AlistHost.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/AlistHost.java @@ -77,17 +77,14 @@ public class AlistHost implements ResourcePackHost { } private void readCacheFromDisk() { - Path cachePath = CraftEngine.instance().dataFolderPath().resolve("alist.cache"); - if (!Files.exists(cachePath)) return; - + Path cachePath = CraftEngine.instance().dataFolderPath().resolve("cache").resolve("alist.json"); + if (!Files.exists(cachePath) || !Files.isRegularFile(cachePath)) return; try (InputStream is = Files.newInputStream(cachePath)) { Map cache = GsonHelper.get().fromJson( new InputStreamReader(is), new TypeToken>(){}.getType() ); - this.cachedSha1 = cache.get("sha1"); - CraftEngine.instance().logger().info("[Alist] Loaded cached resource pack metadata"); } catch (Exception e) { CraftEngine.instance().logger().warn("[Alist] Failed to load cache " + cachePath, e); @@ -97,9 +94,9 @@ public class AlistHost implements ResourcePackHost { private void saveCacheToDisk() { Map cache = new HashMap<>(); cache.put("sha1", this.cachedSha1 != null ? this.cachedSha1 : ""); - - Path cachePath = CraftEngine.instance().dataFolderPath().resolve("alist.cache"); + Path cachePath = CraftEngine.instance().dataFolderPath().resolve("cache").resolve("alist.json"); try { + Files.createDirectories(cachePath.getParent()); Files.writeString( cachePath, GsonHelper.get().toJson(cache), diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/DropboxHost.java b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/DropboxHost.java index 98a1f483b..8f6cf2b92 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/DropboxHost.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/DropboxHost.java @@ -49,18 +49,15 @@ public class DropboxHost implements ResourcePackHost { } public void readCacheFromDisk() { - Path cachePath = CraftEngine.instance().dataFolderPath().resolve("dropbox.cache"); + Path cachePath = CraftEngine.instance().dataFolderPath().resolve("cache").resolve("dropbox.json"); if (!Files.exists(cachePath)) return; - try (InputStream is = Files.newInputStream(cachePath)) { JsonObject cache = GsonHelper.parseJsonToJsonObject(new String(is.readAllBytes(), StandardCharsets.UTF_8)); - this.url = getString(cache, "url"); this.sha1 = getString(cache, "sha1"); this.refreshToken = getString(cache, "refresh_token"); this.accessToken = getString(cache, "access_token"); this.expiresAt = getLong(cache, "expires_at"); - CraftEngine.instance().logger().info("[Dropbox] Loaded cached resource pack info"); } catch (Exception e) { CraftEngine.instance().logger().warn("[Dropbox] Failed to load cache " + cachePath, e); @@ -74,9 +71,9 @@ public class DropboxHost implements ResourcePackHost { cache.addProperty("refresh_token", this.refreshToken); cache.addProperty("access_token", this.accessToken); cache.addProperty("expires_at", this.expiresAt); - - Path cachePath = CraftEngine.instance().dataFolderPath().resolve("dropbox.cache"); + Path cachePath = CraftEngine.instance().dataFolderPath().resolve("cache").resolve("dropbox.json"); try { + Files.createDirectories(cachePath); Files.writeString( cachePath, GsonHelper.get().toJson(cache), diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/GitLabHost.java b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/GitLabHost.java index c2d1cc5e9..b94adf1f1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/GitLabHost.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/GitLabHost.java @@ -45,23 +45,19 @@ public class GitLabHost implements ResourcePackHost { } public void readCacheFromDisk() { - Path cachePath = CraftEngine.instance().dataFolderPath().resolve("gitlab.cache"); - if (!Files.exists(cachePath)) return; - + Path cachePath = CraftEngine.instance().dataFolderPath().resolve("cache").resolve("gitlab.json"); + if (!Files.exists(cachePath) || !Files.isRegularFile(cachePath)) return; try (InputStream is = Files.newInputStream(cachePath)) { Map cache = GsonHelper.get().fromJson( new InputStreamReader(is), new TypeToken>(){}.getType() ); - this.url = cache.get("url"); this.sha1 = cache.get("sha1"); - String uuidString = cache.get("uuid"); if (uuidString != null && !uuidString.isEmpty()) { this.uuid = UUID.fromString(uuidString); } - CraftEngine.instance().logger().info("[GitLab] Loaded cached resource pack info"); } catch (Exception e) { CraftEngine.instance().logger().warn( @@ -74,9 +70,9 @@ public class GitLabHost implements ResourcePackHost { cache.put("url", this.url); cache.put("sha1", this.sha1); cache.put("uuid", this.uuid != null ? this.uuid.toString() : ""); - - Path cachePath = CraftEngine.instance().dataFolderPath().resolve("gitlab.cache"); + Path cachePath = CraftEngine.instance().dataFolderPath().resolve("cache").resolve("gitlab.json"); try { + Files.createDirectories(cachePath.getParent()); Files.writeString( cachePath, GsonHelper.get().toJson(cache), diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/LobFileHost.java b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/LobFileHost.java index 36a965a8c..275521957 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/LobFileHost.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/LobFileHost.java @@ -56,23 +56,19 @@ public class LobFileHost implements ResourcePackHost { } public void readCacheFromDisk() { - Path cachePath = CraftEngine.instance().dataFolderPath().resolve("lobfile.cache"); - if (!Files.exists(cachePath)) return; - + Path cachePath = CraftEngine.instance().dataFolderPath().resolve("cache").resolve("lobfile.json"); + if (!Files.exists(cachePath) || !Files.isRegularFile(cachePath)) return; try (InputStream is = Files.newInputStream(cachePath)) { Map cache = GsonHelper.get().fromJson( new InputStreamReader(is), new TypeToken>(){}.getType() ); - this.url = cache.get("url"); this.sha1 = cache.get("sha1"); - String uuidString = cache.get("uuid"); if (uuidString != null && !uuidString.isEmpty()) { this.uuid = UUID.fromString(uuidString); } - CraftEngine.instance().logger().info("[LobFile] Loaded cached resource pack info"); } catch (Exception e) { CraftEngine.instance().logger().warn( @@ -85,9 +81,9 @@ public class LobFileHost implements ResourcePackHost { cache.put("url", this.url); cache.put("sha1", this.sha1); cache.put("uuid", this.uuid != null ? this.uuid.toString() : ""); - - Path cachePath = CraftEngine.instance().dataFolderPath().resolve("lobfile.cache"); + Path cachePath = CraftEngine.instance().dataFolderPath().resolve("cache").resolve("lobfile.json"); try { + Files.createDirectories(cachePath.getParent()); Files.writeString( cachePath, GsonHelper.get().toJson(cache), diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/OneDriveHost.java b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/OneDriveHost.java index 844e2f538..a15fa632f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/OneDriveHost.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/host/impl/OneDriveHost.java @@ -61,9 +61,8 @@ public class OneDriveHost implements ResourcePackHost { } public void readCacheFromDisk() { - Path cachePath = CraftEngine.instance().dataFolderPath().resolve("onedrive.cache"); - if (!Files.exists(cachePath)) return; - + Path cachePath = CraftEngine.instance().dataFolderPath().resolve("cache").resolve("onedrive.json"); + if (!Files.exists(cachePath) || !Files.isRegularFile(cachePath)) return; try (InputStream is = Files.newInputStream(cachePath)) { Map cache = GsonHelper.get().fromJson( new InputStreamReader(is), @@ -91,9 +90,9 @@ public class OneDriveHost implements ResourcePackHost { cache.put("refresh-token-expires-in", String.valueOf(this.refreshToken.right().getTime())); cache.put("sha1", this.sha1); cache.put("file-id", this.fileId); - - Path cachePath = CraftEngine.instance().dataFolderPath().resolve("onedrive.cache"); + Path cachePath = CraftEngine.instance().dataFolderPath().resolve("cache").resolve("onedrive.json"); try { + Files.createDirectories(cachePath.getParent()); Files.writeString( cachePath, GsonHelper.get().toJson(cache), diff --git a/gradle.properties b/gradle.properties index ae2ad91b3..2ba49566a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.59.2 +project_version=0.0.59.3 config_version=41 lang_version=21 project_group=net.momirealms