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

refactor(core): 优化合并方法

This commit is contained in:
jhqwqmc
2025-03-15 17:38:35 +08:00
parent e1683b422e
commit a90719c3ea

View File

@@ -1,20 +1,17 @@
package net.momirealms.craftengine.core.pack.conflict.resolution;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.GsonHelper;
import net.momirealms.craftengine.core.util.Key;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MergePackMcMetaResolution implements Resolution {
@@ -25,159 +22,94 @@ public class MergePackMcMetaResolution implements Resolution {
this.description = description;
}
@SuppressWarnings("unchecked")
public static void mergeMcmeta(Path existing, Path conflict, String customDescription) throws IOException {
Gson gson = GsonHelper.get();
Type dataType = new TypeToken<Map<String, Object>>() {}.getType();
public static void mergeMcmeta(Path existing, Path conflict, JsonObject customDescription) throws IOException {
// 读取并解析JSON文件
JsonObject existingJson = GsonHelper.readJsonFile(existing).getAsJsonObject();
JsonObject conflictJson = GsonHelper.readJsonFile(conflict).getAsJsonObject();
String jsonDescription = gson.fromJson(AdventureHelper.miniMessageToJson(customDescription), dataType);
// 合并根对象
JsonObject merged = GsonHelper.deepMerge(existingJson, conflictJson);
Map<String, Object> existingData = gson.fromJson(new FileReader(existing.toFile()), dataType);
Map<String, Object> conflictData = gson.fromJson(new FileReader(conflict.toFile()), dataType);
// 处理pack字段的特殊逻辑
processPackField(merged, existingJson, conflictJson, customDescription);
Map<String, Object> merged = (Map<String, Object>) mergeValues(existingData, conflictData);
processPackField(merged, existingData, conflictData, jsonDescription);
Object cleaned = cleanEmpty(merged);
try (FileWriter writer = new FileWriter(existing.toFile())) {
gson.toJson(cleaned, writer);
}
// 写回文件
GsonHelper.writeJsonFile(merged, existing);
}
@SuppressWarnings("unchecked")
private static Object mergeValues(Object v1, Object v2) {
if (v1 instanceof Map && v2 instanceof Map) {
Map<String, Object> merged = new HashMap<>();
((Map<String, Object>) v1).forEach((k, val) ->
merged.put(k, ((Map<?, ?>) v2).containsKey(k) ? mergeValues(val, ((Map<?, ?>) v2).get(k)) : val));
((Map<String, Object>) v2).forEach(merged::putIfAbsent);
return merged;
}
if (v1 instanceof List && v2 instanceof List) {
List<Object> mergedList = new ArrayList<>((List<?>) v2);
mergedList.addAll((List<?>) v1);
return mergedList;
}
return v2 != null ? v2 : v1;
}
private static void processPackField(JsonObject merged, JsonObject data1, JsonObject data2, JsonObject customDescription) {
JsonObject pack1 = data1.getAsJsonObject("pack");
JsonObject pack2 = data2.getAsJsonObject("pack");
@SuppressWarnings("unchecked")
private static Object cleanEmpty(Object data) {
if (data instanceof Map) {
Map<String, Object> map = new HashMap<>((Map<String, Object>) data);
map.values().removeIf(MergePackMcMetaResolution::isEmpty);
map.replaceAll((k, v) -> cleanEmpty(v));
return map.isEmpty() ? null : map;
}
if (data instanceof List) {
List<Object> list = new ArrayList<>((List<Object>) data);
list.removeIf(MergePackMcMetaResolution::isEmpty);
list.replaceAll(MergePackMcMetaResolution::cleanEmpty);
return list.isEmpty() ? null : list;
}
return data;
}
JsonObject mergedPack = new JsonObject();
private static boolean isEmpty(Object value) {
return value == null ||
(value instanceof Map && ((Map<?, ?>) value).isEmpty()) ||
(value instanceof List && ((List<?>) value).isEmpty()) ||
(value instanceof String && ((String) value).isEmpty());
}
@SuppressWarnings("unchecked")
private static void processPackField(Map<String, Object> merged, Map<String, Object> data1, Map<String, Object> data2, Object customDescription) {
if (merged.containsKey("pack")) {
Map<String, Object> pack = (Map<String, Object>) merged.get("pack");
pack.put("pack_format", Math.max(
getPackFormat(data1),
getPackFormat(data2)
));
processSupportedFormats(pack, data1, data2);
if (customDescription != null && !isEmpty(customDescription)) {
pack.put("description", customDescription);
}
/* else {
String desc1 = getDescription(data1);
String desc2 = getDescription(data2);
String mergedDesc = desc1.isEmpty() ? desc2 : desc2.isEmpty() ? desc1 : desc1 + "\n" + desc2;
if (!mergedDesc.isEmpty()) pack.put("description", mergedDesc);
}*/
}
}
private static int getPackFormat(Map<String, Object> data) {
if (data.containsKey("pack") && ((Map<?, ?>) data.get("pack")).containsKey("pack_format")) {
return ((Number) ((Map<?, ?>) data.get("pack")).get("pack_format")).intValue();
}
return 0;
}
private static void processSupportedFormats(Map<String, Object> pack, Map<String, Object> data1, Map<String, Object> data2) {
Object sf1 = getSupportedFormats(data1);
Object sf2 = getSupportedFormats(data2);
// 合并pack_format
int packFormat1 = pack1 != null && pack1.has("pack_format") ? pack1.get("pack_format").getAsInt() : 0;
int packFormat2 = pack2 != null && pack2.has("pack_format") ? pack2.get("pack_format").getAsInt() : 0;
mergedPack.addProperty("pack_format", Math.max(packFormat1, packFormat2));
// 处理supported_formats
JsonElement sf1 = pack1 != null ? pack1.get("supported_formats") : null;
JsonElement sf2 = pack2 != null ? pack2.get("supported_formats") : null;
if (sf1 != null || sf2 != null) {
Object mergedSf = mergeValues(sf1, sf2);
int[] minMax = parseSupportedFormats(mergedSf);
Map<String, Integer> supported = new HashMap<>();
supported.put("min_inclusive", minMax[0]);
supported.put("max_inclusive", minMax[1]);
pack.put("supported_formats", supported);
JsonElement mergedSf = mergeSupportedFormats(sf1, sf2);
mergedPack.add("supported_formats", mergedSf);
}
// 处理description
mergedPack.add("description", customDescription);
merged.add("pack", mergedPack);
}
private static JsonElement mergeSupportedFormats(JsonElement sf1, JsonElement sf2) {
final int[] min = {Integer.MAX_VALUE};
final int[] max = {Integer.MIN_VALUE};
parseSupportedFormats(sf1, (m, n) -> {
min[0] = Math.min(min[0], m);
max[0] = Math.max(max[0], n);
});
parseSupportedFormats(sf2, (m, n) -> {
min[0] = Math.min(min[0], m);
max[0] = Math.max(max[0], n);
});
JsonObject result = new JsonObject();
result.addProperty("min_inclusive", min[0]);
result.addProperty("max_inclusive", max[0]);
return result;
}
private static void parseSupportedFormats(JsonElement element, MinMaxConsumer consumer) {
if (element == null) return;
if (element.isJsonPrimitive()) {
int value = element.getAsInt();
consumer.accept(value, value);
} else if (element.isJsonArray()) {
JsonArray array = element.getAsJsonArray();
if (!array.isEmpty()) {
int first = array.get(0).getAsInt();
int last = array.get(array.size() - 1).getAsInt();
consumer.accept(first, last);
}
} else if (element.isJsonObject()) {
JsonObject obj = element.getAsJsonObject();
int m = obj.has("min_inclusive") ? obj.get("min_inclusive").getAsInt() : 0;
int n = obj.has("max_inclusive") ? obj.get("max_inclusive").getAsInt() : 0;
consumer.accept(m, n);
}
}
private static Object getSupportedFormats(Map<String, Object> data) {
if (data.containsKey("pack") && ((Map<?, ?>) data.get("pack")).containsKey("supported_formats")) {
return ((Map<?, ?>) data.get("pack")).get("supported_formats");
}
return null;
}
private static int[] parseSupportedFormats(Object supported) {
if (supported instanceof Number) {
int val = ((Number) supported).intValue();
return new int[]{val, val};
}
if (supported instanceof List<?> list) {
return new int[]{
getNumberValue(list.getFirst()),
getNumberValue(list.getLast())
};
}
if (supported instanceof Map<?, ?> map) {
return new int[]{
getNumberValue(map.get("min_inclusive")),
getNumberValue(map.get("max_inclusive"))
};
}
return new int[]{0, 0};
}
private static int getNumberValue(Object value) {
if (value instanceof Number) {
return ((Number) value).intValue();
}
return 0;
}
private static String getDescription(Map<String, Object> data) {
if (data.containsKey("pack") && ((Map<?, ?>) data.get("pack")).containsKey("description")) {
Object desc = ((Map<?, ?>) data.get("pack")).get("description");
return desc instanceof String ? (String) desc : "";
}
return "";
private interface MinMaxConsumer {
void accept(int min, int max);
}
@Override
public void run(Path existing, Path conflict) {
try {
mergeMcmeta(existing, conflict, description);
mergeMcmeta(existing, conflict, JsonParser.parseString(AdventureHelper.miniMessageToJson(this.description)).getAsJsonObject());
} catch (IOException e) {
CraftEngine.instance().logger().severe("Failed to merge pack.mcmeta when resolving file conflicts", e);
}