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

增强pack.mcmeta校验

This commit is contained in:
XiaoMoMi
2025-12-18 18:10:08 +08:00
parent a0055cc356
commit 37d045aabf
8 changed files with 103 additions and 93 deletions

View File

@@ -24,6 +24,8 @@ resource-pack:
supported-version:
min: server
max: latest
# The description of your resource pack
description: "<gray>CraftEngine ResourcePack</gray>"
# Remove 1.21.5+ tinted_leaves particles
remove-tinted-leaves-particle: true
# Define the name of the overlay folders
@@ -65,7 +67,6 @@ resource-pack:
path: "pack.mcmeta"
resolution:
type: merge_pack_mcmeta
description: "<gray>CraftEngine ResourcePack</gray>"
- term:
type: exact
path: "pack.png"

View File

@@ -1,12 +0,0 @@
{
"pack": {
"pack_format": 15,
"description": "CraftEngine",
"supported_formats": {
"min_inclusive": 15,
"max_inclusive": 1000
},
"min_format": 15,
"max_format": 1000
}
}

View File

@@ -788,19 +788,28 @@ public abstract class AbstractPackManager implements PackManager {
this.generateClientLang(generatedPackPath);
this.generateEquipments(generatedPackPath, revisions::add);
this.generateParticle(generatedPackPath);
this.generatePackMetadata(generatedPackPath.resolve("pack.mcmeta"), revisions);
Path packMcMetaPath = generatedPackPath.resolve("pack.mcmeta");
JsonObject packMcMeta = Files.isRegularFile(packMcMetaPath) ? GsonHelper.readJsonFile(packMcMetaPath).getAsJsonObject() : new JsonObject();
// 生成revision overlay
this.generateRevisionOverlays(packMcMeta, revisions);
if (Config.excludeShaders()) {
this.removeAllShaders(generatedPackPath);
}
long time2 = System.currentTimeMillis();
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.generate.finish", String.valueOf(time2 - time1)));
// 校验资源包
if (Config.validateResourcePack()) {
this.validateResourcePack(generatedPackPath);
this.validateResourcePack(generatedPackPath, packMcMeta);
}
long time3 = System.currentTimeMillis();
if (Config.validateResourcePack()) {
this.plugin.logger().info(TranslationManager.instance().translateLog("info.resource_pack.validate.finish", String.valueOf(time3 - time2)));
}
// 验证完成后应该重新校验pack.mcmeta并写入
this.validatePackMetadata(generatedPackPath.resolve("pack.mcmeta"), packMcMeta);
// 优化资源包
if (Config.optimizeResourcePack()) {
this.optimizeResourcePack(generatedPackPath);
}
@@ -824,29 +833,61 @@ public abstract class AbstractPackManager implements PackManager {
}
}
private void generatePackMetadata(Path path, Set<Revision> revisions) throws IOException {
JsonObject rawMeta;
boolean changed = false;
if (!Files.exists(path)) {
rawMeta = new JsonObject();
changed = true;
} else {
rawMeta = GsonHelper.readJsonFile(path).getAsJsonObject();
private void validatePackMetadata(Path path, JsonObject rawMeta) throws IOException {
// 获取设定的最大和最小值
PackVersion minVersion = Config.packMinVersion().packFormat();
PackVersion maxVersion = Config.packMaxVersion().packFormat();
// 设置pack
{
JsonObject packJson = new JsonObject();
rawMeta.add("pack", packJson);
JsonElement description = AdventureHelper.componentToJsonElement(AdventureHelper.miniMessage().deserialize(Config.packDescription()));
packJson.add("description", description);
// 需要旧版本兼容性
if (minVersion.isBelow(PackVersion.PACK_FORMAT_CHANGE_VERSION)) {
packJson.addProperty("pack_format", minVersion.major());
JsonObject supportedVersions = new JsonObject();
supportedVersions.addProperty("min_inclusive", minVersion.major());
supportedVersions.addProperty("max_inclusive", maxVersion.major());
packJson.add("supported_formats", supportedVersions);
}
if (!rawMeta.has("pack")) {
JsonObject pack = new JsonObject();
rawMeta.add("pack", pack);
pack.addProperty("pack_format", Config.packMinVersion().majorPackFormat());
JsonObject supportedFormats = new JsonObject();
supportedFormats.addProperty("min_inclusive", Config.packMinVersion().majorPackFormat());
supportedFormats.addProperty("max_inclusive", Config.packMaxVersion().majorPackFormat());
pack.add("supported_formats", supportedFormats);
changed = true;
// 到达了1.21.9
if (maxVersion.isAtOrAbove(PackVersion.PACK_FORMAT_CHANGE_VERSION)) {
// 同时要兼容低版本
packJson.add("min_format", minVersion.getAsJsonArray());
packJson.add("max_format", maxVersion.getAsJsonArray());
}
if (revisions.isEmpty()) {
if (changed) {
}
// 验证overlay
{
PackMcMeta mcMeta = new PackMcMeta(rawMeta);
List<Overlay> overlays = mcMeta.overlays();
if (!overlays.isEmpty()) {
boolean legacySupported = false;
for (Overlay overlay : overlays) {
if (overlay.minVersion().isBelow(PackVersion.PACK_FORMAT_CHANGE_VERSION)) {
legacySupported = true;
break;
}
}
JsonArray newOverlayEntries = new JsonArray();
for (Overlay overlay : overlays) {
newOverlayEntries.add(overlay.getAsOverlayEntry(legacySupported));
}
JsonObject overlaysJson = new JsonObject();
overlaysJson.add("entries", newOverlayEntries);
rawMeta.add("overlays", overlaysJson);
}
}
GsonHelper.writeJsonFile(rawMeta, path);
}
// 这里都是随便写写的,重点在之后的校验里
private void generateRevisionOverlays(JsonObject rawMeta, Set<Revision> revisions) throws IOException {
if (revisions.isEmpty()) {
return;
}
JsonObject overlays;
@@ -865,18 +906,15 @@ public abstract class AbstractPackManager implements PackManager {
}
for (Revision revision : revisions) {
JsonObject entry = new JsonObject();
if (revision.minPackVersion().major() < 65) {
JsonArray formatsArray = new JsonArray();
entry.add("formats", formatsArray);
formatsArray.add(revision.minPackVersion().major());
formatsArray.add(revision.maxPackVersion().major());
}
entry.add("min_format", revision.minPackVersion().getAsJsonArray());
entry.add("max_format", revision.maxPackVersion().getAsJsonArray());
entry.addProperty("directory", Config.createOverlayFolderName(revision.versionString()));
entries.add(entry);
}
GsonHelper.writeJsonFile(rawMeta, path);
}
private void removeAllShaders(Path path) {
@@ -1186,18 +1224,8 @@ public abstract class AbstractPackManager implements PackManager {
}
}
private void validateResourcePack(Path path) {
Path packMcMetaPath = path.resolve("pack.mcmeta");
PackMcMeta packMeta;
JsonObject packMetaJson;
try {
packMetaJson = GsonHelper.readJsonFile(packMcMetaPath).getAsJsonObject();
packMeta = new PackMcMeta(packMetaJson);
} catch (IOException e) {
this.plugin.logger().warn("Failed to read pack.mcmeta " + packMcMetaPath.toAbsolutePath(), e);
return;
}
private void validateResourcePack(Path path, JsonObject packMetaJson) {
PackMcMeta packMeta = new PackMcMeta(packMetaJson);
List<OverlayCombination.Segment> segments = new ArrayList<>();
// 完全小于1.21.11或完全大于1.21.11
if (Config.packMaxVersion().isBelow(MinecraftVersion.V1_21_11) || Config.packMinVersion().isAtOrAbove(MinecraftVersion.V1_21_11)) {
@@ -1292,7 +1320,7 @@ public abstract class AbstractPackManager implements PackManager {
GsonHelper.writeJsonFile(entry.atlas(), atlasPath);
if (!atlasToAdd.containsKey(directoryName)) {
Overlay overlay = new Overlay(new PackVersion(min), new PackVersion(max), directoryName);
atlasToAdd.put(directoryName, overlay.getAsOverlayEntry());
atlasToAdd.put(directoryName, overlay.getAsOverlayEntry(true));
}
} catch (IOException e) {
this.plugin.logger().warn("Failed to write atlas " + atlasPath.toAbsolutePath(), e);
@@ -1326,7 +1354,7 @@ public abstract class AbstractPackManager implements PackManager {
GsonHelper.writeJsonFile(entry.atlas(), atlasPath);
if (!atlasToAdd.containsKey(directoryName)) {
Overlay overlay = new Overlay(new PackVersion(min), new PackVersion(max), directoryName);
atlasToAdd.put(directoryName, overlay.getAsOverlayEntry());
atlasToAdd.put(directoryName, overlay.getAsOverlayEntry(true));
}
} catch (IOException e) {
this.plugin.logger().warn("Failed to write atlas " + atlasPath.toAbsolutePath(), e);
@@ -1347,11 +1375,6 @@ public abstract class AbstractPackManager implements PackManager {
for (JsonElement entry : atlasToAdd.values()) {
overlayEntries.add(entry);
}
try {
GsonHelper.writeJsonFile(packMetaJson, packMcMetaPath);
} catch (IOException e) {
this.plugin.logger().warn("Failed to write pack.mcmeta", e);
}
}
}

View File

@@ -9,7 +9,6 @@ import net.momirealms.craftengine.core.pack.conflict.PathContext;
import net.momirealms.craftengine.core.pack.mcmeta.PackVersion;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.GsonHelper;
import net.momirealms.craftengine.core.util.Key;
import net.momirealms.craftengine.core.util.Pair;
@@ -26,13 +25,7 @@ public class ResolutionMergePackMcMeta implements Resolution {
public static final Factory FACTORY = new Factory();
public static final Set<String> STANDARD_PACK_KEYS = ImmutableSet.of("pack", "features", "filter", "overlays", "language");
private final String description;
public ResolutionMergePackMcMeta(String description) {
this.description = description;
}
public static void merge(Path file1, Path file2, JsonElement customDescription) throws IOException {
public static void merge(Path file1, Path file2) throws IOException {
// 第一步解析全部的mcmeta文件为json对象
JsonObject mcmeta1;
try {
@@ -49,13 +42,15 @@ public class ResolutionMergePackMcMeta implements Resolution {
return;
}
JsonObject merged = new JsonObject();
// 第三步处理pack区域
JsonObject pack1 = mcmeta1.getAsJsonObject("pack");
JsonObject pack2 = mcmeta2.getAsJsonObject("pack");
JsonObject mergedPack = new JsonObject();
mergedPack.add("description", customDescription);
merged.add("pack", mergedPack);
mergePack(mergedPack, pack1, pack2);
// 注释: 无需处理,由后续验证合并
// //第二步处理pack区域
// JsonObject pack1 = mcmeta1.getAsJsonObject("pack");
// JsonObject pack2 = mcmeta2.getAsJsonObject("pack");
// JsonObject mergedPack = new JsonObject();
// merged.add("pack", mergedPack);
// mergePack(mergedPack, pack1, pack2);
// 第三步合并overlays
List<JsonObject> overlays = new ArrayList<>();
collectOverlays(mcmeta1.getAsJsonObject("overlays"), overlays::add);
@@ -165,14 +160,11 @@ public class ResolutionMergePackMcMeta implements Resolution {
Pair<PackVersion, PackVersion> supportedVersions = getSupportedVersions(entryJson);
PackVersion min = PackVersion.getHigher(supportedVersions.left(), PackVersion.MIN_OVERLAY_VERSION);
PackVersion max = PackVersion.getHigher(supportedVersions.right(), PackVersion.MIN_OVERLAY_VERSION);
// https://minecraft.wiki/w/Java_Edition_25w31a
if (min.major() < 65) {
// 旧版格式支持
JsonArray supportedFormats = new JsonArray();
supportedFormats.add(min.major());
supportedFormats.add(max.major());
entryJson.add("formats", supportedFormats);
}
// 新版格式支持
JsonArray minFormat = new JsonArray();
minFormat.add(min.major());
@@ -285,7 +277,7 @@ public class ResolutionMergePackMcMeta implements Resolution {
@Override
public void run(PathContext existing, PathContext conflict) {
try {
merge(existing.path(), conflict.path(), AdventureHelper.componentToJsonElement(AdventureHelper.miniMessage().deserialize(this.description)));
merge(existing.path(), conflict.path());
} catch (Exception e) {
CraftEngine.instance().logger().severe("Failed to merge pack.mcmeta when resolving file conflicts for '" + existing.path() + "' and '" + conflict.path() + "'", e);
}
@@ -299,8 +291,7 @@ public class ResolutionMergePackMcMeta implements Resolution {
public static class Factory implements ResolutionFactory {
@Override
public Resolution create(Map<String, Object> arguments) {
String description = arguments.getOrDefault("description", "<gray>CraftEngine ResourcePack</gray>").toString();
return new ResolutionMergePackMcMeta(description);
return new ResolutionMergePackMcMeta();
}
}
}

View File

@@ -41,7 +41,7 @@ public class Overlay {
'}';
}
public JsonObject getAsOverlayEntry() {
public JsonObject getAsOverlayEntry(boolean legacy) {
JsonObject entry = new JsonObject();
entry.addProperty("directory", this.directory);
JsonArray minFormat = new JsonArray();
@@ -52,7 +52,7 @@ public class Overlay {
maxFormat.add(new JsonPrimitive(this.maxVersion.major()));
maxFormat.add(new JsonPrimitive(this.maxVersion.minor()));
entry.add("max_format", maxFormat);
if (this.minVersion.major() < 65) {
if (legacy) {
JsonArray formats = new JsonArray();
formats.add(new JsonPrimitive(this.minVersion.major()));
formats.add(new JsonPrimitive(this.maxVersion.major()));

View File

@@ -8,6 +8,7 @@ import java.util.List;
public record PackVersion(int major, int minor) implements Comparable<PackVersion> {
public static final PackVersion MIN_PACK_VERSION = new PackVersion(15, 0); // 1.20
public static final PackVersion MIN_OVERLAY_VERSION = new PackVersion(18, 0); // 1.20
public static final PackVersion PACK_FORMAT_CHANGE_VERSION = new PackVersion(65, 0); // 25w31a
public static final PackVersion MAX_PACK_VERSION = new PackVersion(1000, 0); // future
public PackVersion(int major) {

View File

@@ -66,6 +66,7 @@ public class Config {
protected List<String> resource_pack$merge_external_zips;
protected Set<String> resource_pack$exclude_file_extensions;
protected Path resource_pack$path;
protected String resource_pack$description;
protected boolean resource_pack$protection$crash_tools$method_1;
protected boolean resource_pack$protection$crash_tools$method_2;
@@ -329,6 +330,7 @@ public class Config {
// resource pack
resource_pack$path = resolvePath(config.getString("resource-pack.path", "./generated/resource_pack.zip"));
resource_pack$description = config.getString("resource-pack.description", "<gray>CraftEngine ResourcePack</gray>");
resource_pack$override_uniform_font = config.getBoolean("resource-pack.override-uniform-font", false);
resource_pack$generate_mod_assets = config.getBoolean("resource-pack.generate-mod-assets", false);
resource_pack$remove_tinted_leaves_particle = config.getBoolean("resource-pack.remove-tinted-leaves-particle", true);
@@ -1130,6 +1132,10 @@ public class Config {
return instance.equipment$sacrificed_vanilla_armor$humanoid_leggings;
}
public static String packDescription() {
return instance.resource_pack$description;
}
public static String sacrificedVanillaArmorType() {
return instance.equipment$sacrificed_vanilla_armor$type;
}

View File

@@ -1,8 +1,8 @@
org.gradle.jvmargs=-Xmx4G
# Project settings
project_version=0.0.66.5
config_version=63
project_version=0.0.66.6
config_version=64
lang_version=46
project_group=net.momirealms
latest_supported_version=1.21.11