diff --git a/common-files/src/main/resources/config.yml b/common-files/src/main/resources/config.yml index ee7b4e559..16ad6dbe5 100644 --- a/common-files/src/main/resources/config.yml +++ b/common-files/src/main/resources/config.yml @@ -110,10 +110,15 @@ resource-pack: - term: type: any_of terms: - - type: parent_path_suffix - suffix: "minecraft/items" - type: parent_path_suffix suffix: "minecraft/models/item" + resolution: + type: merge_legacy_model + - term: + type: any_of + terms: + - type: parent_path_suffix + suffix: "minecraft/items" resolution: type: merge_json deeply: true 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 6ee669d9a..c3a3f8900 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 @@ -2108,17 +2108,21 @@ public abstract class AbstractPackManager implements PackManager { } originalItemModel = originalItemModel.deepCopy(); } - JsonArray overrides; + TreeSet overridesModels = new TreeSet<>(entry.getValue()); + + JsonArray newOverrides = new JsonArray(); if (originalItemModel.has("overrides")) { - overrides = originalItemModel.getAsJsonArray("overrides"); - } else { - overrides = new JsonArray(); - originalItemModel.add("overrides", overrides); + JsonArray overrides = originalItemModel.getAsJsonArray("overrides"); + for (JsonElement override : overrides) { + if (override instanceof JsonObject jo) { + overridesModels.add(new LegacyOverridesModel(jo)); + } + } } - Collection legacyOverridesModels = entry.getValue(); - for (LegacyOverridesModel model : legacyOverridesModels) { - overrides.add(model.toLegacyPredicateElement()); + for (LegacyOverridesModel model : overridesModels) { + newOverrides.add(model.toLegacyPredicateElement()); } + originalItemModel.add("overrides", newOverrides); try { Files.createDirectories(overridedItemPath.getParent()); } catch (IOException e) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/ResolutionMergeLegacyModel.java b/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/ResolutionMergeLegacyModel.java new file mode 100644 index 000000000..851f9589a --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/ResolutionMergeLegacyModel.java @@ -0,0 +1,76 @@ +package net.momirealms.craftengine.core.pack.conflict.resolution; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import net.momirealms.craftengine.core.pack.conflict.PathContext; +import net.momirealms.craftengine.core.pack.model.LegacyOverridesModel; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.GsonHelper; +import net.momirealms.craftengine.core.util.Key; + +import java.io.IOException; +import java.util.Map; +import java.util.TreeSet; + +public class ResolutionMergeLegacyModel implements Resolution { + public static final Factory FACTORY = new Factory(); + + @Override + public void run(PathContext existing, PathContext conflict) { + try { + JsonObject j1 = GsonHelper.readJsonFile(existing.path()).getAsJsonObject(); + JsonObject j2 = GsonHelper.readJsonFile(conflict.path()).getAsJsonObject(); + + if (!isJsonArray(j2.get("overrides"))) { + return; + } + + if (!isJsonArray(j1.get("overrides"))) { + GsonHelper.writeJsonFile(j2, existing.path()); + return; + } + + JsonArray ja1 = j1.getAsJsonArray("overrides"); + JsonArray ja2 = j2.getAsJsonArray("overrides"); + TreeSet legacyOverridesModels = new TreeSet<>(); + for (JsonElement je : ja1) { + if (je instanceof JsonObject jo) { + legacyOverridesModels.add(new LegacyOverridesModel(jo)); + } + } + for (JsonElement je : ja2) { + if (je instanceof JsonObject jo) { + legacyOverridesModels.add(new LegacyOverridesModel(jo)); + } + } + + JsonArray newOverrides = new JsonArray(); + for (LegacyOverridesModel legacyOverridesModel : legacyOverridesModels) { + newOverrides.add(legacyOverridesModel.toLegacyPredicateElement()); + } + + j2.add("overrides", newOverrides); + GsonHelper.writeJsonFile(j2, existing.path()); + } catch (IOException e) { + CraftEngine.instance().logger().severe("Failed to merge json when resolving file conflicts", e); + } + } + + private boolean isJsonArray(JsonElement element) { + return element != null && element.isJsonArray(); + } + + @Override + public Key type() { + return Resolutions.MERGE_LEGACY_MODEL; + } + + public static class Factory implements ResolutionFactory { + + @Override + public Resolution create(Map arguments) { + return new ResolutionMergeLegacyModel(); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/Resolutions.java b/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/Resolutions.java index 9d16ffa7d..f7651d881 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/Resolutions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/conflict/resolution/Resolutions.java @@ -16,6 +16,7 @@ public class Resolutions { public static final Key MERGE_ATLAS = Key.of("craftengine:merge_atlas"); public static final Key CONDITIONAL = Key.of("craftengine:conditional"); public static final Key MERGE_PACK_MCMETA = Key.of("craftengine:merge_pack_mcmeta"); + public static final Key MERGE_LEGACY_MODEL = Key.of("craftengine:merge_legacy_model"); static { register(RETAIN_MATCHING, RetainMatchingResolution.FACTORY); @@ -23,6 +24,7 @@ public class Resolutions { register(CONDITIONAL, ResolutionConditional.FACTORY); register(MERGE_PACK_MCMETA, ResolutionMergePackMcMeta.FACTORY); register(MERGE_ATLAS, ResolutionMergeAltas.FACTORY); + register(MERGE_LEGACY_MODEL, ResolutionMergeLegacyModel.FACTORY); } public static void register(Key key, ResolutionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyOverridesModel.java b/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyOverridesModel.java index 6f93c7777..91cb5cf49 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyOverridesModel.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/model/LegacyOverridesModel.java @@ -1,6 +1,9 @@ package net.momirealms.craftengine.core.pack.model; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -14,7 +17,7 @@ public class LegacyOverridesModel implements Comparable { private final int customModelData; public LegacyOverridesModel(@Nullable Map predicate, @NotNull String model, int customModelData) { - this.predicate = predicate == null ? new HashMap<>() : predicate; + this.predicate = predicate == null ? Map.of() : predicate; this.model = model; this.customModelData = customModelData; if (customModelData > 0 && !this.predicate.containsKey("custom_model_data")) { @@ -22,23 +25,51 @@ public class LegacyOverridesModel implements Comparable { } } + public LegacyOverridesModel(JsonObject json) { + this.model = json.get("model").getAsString(); + JsonObject predicate = json.getAsJsonObject("predicate"); + if (predicate != null) { + this.predicate = new HashMap<>(); + for (Map.Entry entry : predicate.entrySet()) { + JsonElement value = entry.getValue(); + if (value instanceof JsonPrimitive primitive) { + if (primitive.isBoolean()) { + this.predicate.put(entry.getKey(), primitive.getAsBoolean()); + } else if (primitive.isNumber()) { + this.predicate.put(entry.getKey(), primitive.getAsNumber()); + } else if (primitive.isString()) { + this.predicate.put(entry.getKey(), primitive.getAsString()); + } + } + } + if (this.predicate.containsKey("custom_model_data")) { + this.customModelData = ResourceConfigUtils.getAsInt(this.predicate.get("custom_model_data"), "custom_model_data"); + } else { + this.customModelData = 0; + } + } else { + this.predicate = Map.of(); + this.customModelData = 0; + } + } + public Map predicate() { - return predicate; + return this.predicate; } public boolean hasPredicate() { - return predicate != null && !predicate.isEmpty(); + return this.predicate != null && !this.predicate.isEmpty(); } public String model() { - return model; + return this.model; } public JsonObject toLegacyPredicateElement() { JsonObject json = new JsonObject(); JsonObject predicateJson = new JsonObject(); - if (predicate != null && !predicate.isEmpty()) { - for (Map.Entry entry : predicate.entrySet()) { + if (this.predicate != null && !this.predicate.isEmpty()) { + for (Map.Entry entry : this.predicate.entrySet()) { if (entry.getValue() instanceof Boolean b) { predicateJson.addProperty(entry.getKey(), b); } else if (entry.getValue() instanceof Number n) { @@ -49,12 +80,12 @@ public class LegacyOverridesModel implements Comparable { } json.add("predicate", predicateJson); } - json.addProperty("model", model); + json.addProperty("model", this.model); return json; } public int customModelData() { - return customModelData; + return this.customModelData; } @Override @@ -62,23 +93,23 @@ public class LegacyOverridesModel implements Comparable { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; LegacyOverridesModel that = (LegacyOverridesModel) o; - return customModelData == that.customModelData && Objects.equals(predicate, that.predicate) && Objects.equals(model, that.model); + return this.customModelData == that.customModelData && Objects.equals(predicate, that.predicate) && Objects.equals(model, that.model); } @Override public int hashCode() { - int result = predicate.hashCode(); + int result = this.predicate.hashCode(); result = 31 * result + Objects.hashCode(model); - result = 31 * result + customModelData; + result = 31 * result + this.customModelData; return result; } @Override public String toString() { return "LegacyOverridesModel{" + - "predicate=" + predicate + - ", model='" + model + '\'' + - ", custom-model-data=" + customModelData + + "predicate=" + this.predicate + + ", model='" + this.model + '\'' + + ", custom-model-data=" + this.customModelData + '}'; }