Fix: failed to parse datapack pack.mcmeta in 6th format. Closes #840.

This commit is contained in:
huanghongxun
2021-04-10 17:09:09 +08:00
parent 65952a5d81
commit 8afd8bde8b
8 changed files with 130 additions and 21 deletions

View File

@@ -132,7 +132,7 @@ class DatapackListPageSkin extends SkinBase<DatapackListPage> {
}
String getSubtitle() {
return StringUtils.parseColorEscapes(packInfo.getDescription());
return StringUtils.parseColorEscapes(packInfo.getDescription().toString());
}
Datapack.Pack getPackInfo() {

View File

@@ -202,10 +202,10 @@ public class Datapack {
private Path file;
private final BooleanProperty active;
private final String id;
private final String description;
private final ModInfo.Description description;
private final Datapack datapack;
public Pack(Path file, String id, String description, Datapack datapack) {
public Pack(Path file, String id, ModInfo.Description description, Datapack datapack) {
this.file = file;
this.id = id;
this.description = description;
@@ -235,7 +235,7 @@ public class Datapack {
return id;
}
public String getDescription() {
public ModInfo.Description getDescription() {
return description;
}

View File

@@ -67,7 +67,7 @@ public final class FabricModMetadata {
throw new IOException("File " + modFile + " is not a Fabric mod.");
FabricModMetadata metadata = JsonUtils.fromNonNullJson(FileUtils.readText(mcmod), FabricModMetadata.class);
String authors = metadata.authors == null ? "" : metadata.authors.stream().map(author -> author.name).collect(Collectors.joining(", "));
return new ModInfo(modManager, modFile, metadata.name, metadata.description,
return new ModInfo(modManager, modFile, metadata.name, new ModInfo.Description(metadata.description),
authors, metadata.version, "", metadata.contact != null ? metadata.contact.getOrDefault("homepage", "") : "");
}
}

View File

@@ -132,7 +132,7 @@ public final class ForgeModMetadata {
authors = String.join(", ", metadata.getAuthorList());
if (StringUtils.isBlank(authors))
authors = metadata.getCredits();
return new ModInfo(modManager, modFile, metadata.getName(), metadata.getDescription(),
return new ModInfo(modManager, modFile, metadata.getName(), new ModInfo.Description(metadata.getDescription()),
authors, metadata.getVersion(), metadata.getGameVersion(),
StringUtils.isBlank(metadata.getUrl()) ? metadata.getUpdateUrl() : metadata.url);
}

View File

@@ -116,7 +116,7 @@ public final class LiteModMetadata {
LiteModMetadata metadata = JsonUtils.GSON.fromJson(IOUtils.readFullyAsString(zipFile.getInputStream(entry)), LiteModMetadata.class);
if (metadata == null)
throw new IOException("Mod " + modFile + " `litemod.json` is malformed.");
return new ModInfo(modManager, modFile, metadata.getName(), metadata.getDescription(), metadata.getAuthor(),
return new ModInfo(modManager, modFile, metadata.getName(), new ModInfo.Description(metadata.getDescription()), metadata.getAuthor(),
metadata.getVersion(), metadata.getGameVersion(), metadata.getUpdateURI());
}
}

View File

@@ -17,16 +17,17 @@
*/
package org.jackhuang.hmcl.mod;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import org.jackhuang.hmcl.util.Logging;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
@@ -38,7 +39,7 @@ public final class ModInfo implements Comparable<ModInfo> {
private Path file;
private final String name;
private final String description;
private final Description description;
private final String authors;
private final String version;
private final String gameVersion;
@@ -46,11 +47,11 @@ public final class ModInfo implements Comparable<ModInfo> {
private final String fileName;
private final BooleanProperty activeProperty;
public ModInfo(ModManager modManager, File file, String name, String description) {
public ModInfo(ModManager modManager, File file, String name, Description description) {
this(modManager, file, name, description, "", "", "", "");
}
public ModInfo(ModManager modManager, File file, String name, String description, String authors, String version, String gameVersion, String url) {
public ModInfo(ModManager modManager, File file, String name, Description description, String authors, String version, String gameVersion, String url) {
this.file = file.toPath();
this.name = name;
this.description = description;
@@ -86,7 +87,7 @@ public final class ModInfo implements Comparable<ModInfo> {
return name;
}
public String getDescription() {
public Description getDescription() {
return description;
}
@@ -136,4 +137,48 @@ public final class ModInfo implements Comparable<ModInfo> {
public int hashCode() {
return Objects.hash(getFileName());
}
public static class Description {
private final List<Part> parts;
public Description(String text) {
this.parts = new ArrayList<>();
this.parts.add(new Part(text, "black"));
}
public Description(List<Part> parts) {
this.parts = parts;
}
public List<Part> getParts() {
return parts;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
for (Part part : parts) {
builder.append(part.text);
}
return builder.toString();
}
public static class Part {
private final String text;
private final String color;
public Part(String text, String color) {
this.text = Objects.requireNonNull(text);
this.color = Objects.requireNonNull(color);
}
public String getText() {
return text;
}
public String getColor() {
return color;
}
}
}
}

View File

@@ -94,7 +94,7 @@ public final class ModManager {
default:
throw new IllegalArgumentException("File " + modFile + " is not a mod file.");
}
return new ModInfo(this, modFile, FileUtils.getNameWithoutExtension(modFile), description);
return new ModInfo(this, modFile, FileUtils.getNameWithoutExtension(modFile), new ModInfo.Description(description));
}
public void refreshMods() throws IOException {

View File

@@ -17,7 +17,8 @@
*/
package org.jackhuang.hmcl.mod;
import com.google.gson.JsonParseException;
import com.google.gson.*;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import org.jackhuang.hmcl.util.Immutable;
import org.jackhuang.hmcl.util.gson.JsonUtils;
@@ -27,9 +28,13 @@ import org.jackhuang.hmcl.util.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Immutable
public class PackMcMeta implements Validation {
@@ -55,18 +60,19 @@ public class PackMcMeta implements Validation {
throw new JsonParseException("pack cannot be null");
}
@JsonAdapter(PackInfoDeserializer.class)
public static class PackInfo {
@SerializedName("pack_format")
private final int packFormat;
@SerializedName("description")
private final String description;
private final ModInfo.Description description;
public PackInfo() {
this(0, "");
this(0, new ModInfo.Description(Collections.emptyList()));
}
public PackInfo(int packFormat, String description) {
public PackInfo(int packFormat, ModInfo.Description description) {
this.packFormat = packFormat;
this.description = description;
}
@@ -75,18 +81,76 @@ public class PackMcMeta implements Validation {
return packFormat;
}
public String getDescription() {
public ModInfo.Description getDescription() {
return description;
}
}
public static class PackInfoDeserializer implements JsonDeserializer<PackInfo> {
private String parseText(JsonElement json) throws JsonParseException {
if (json.isJsonPrimitive()) {
JsonPrimitive primitive = json.getAsJsonPrimitive();
if (primitive.isBoolean()) {
return Boolean.toString(primitive.getAsBoolean());
} else if (primitive.isNumber()) {
return primitive.getAsNumber().toString();
} else if (primitive.isString()) {
return primitive.getAsString();
} else {
throw new JsonParseException("pack.mcmeta text not boolean nor number nor string???");
}
} else if (json.isJsonArray()) {
JsonArray arr = json.getAsJsonArray();
if (arr.size() == 0) {
return "";
} else {
return parseText(arr.get(0));
}
} else {
throw new JsonParseException("pack.mcmeta text should be a string, a boolean, a number or a list of raw JSON text components");
}
}
public ModInfo.Description.Part deserialize(JsonElement json, JsonDeserializationContext context) throws JsonParseException {
if (json.isJsonPrimitive()) {
return new ModInfo.Description.Part(parseText(json));
} else if (json.isJsonObject()) {
JsonObject obj = json.getAsJsonObject();
String text = parseText(obj.get("text"));
return new ModInfo.Description.Part(text);
} else {
throw new JsonParseException("pack.mcmeta Raw JSON text should be string or an object");
}
}
@Override
public PackInfo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
List<ModInfo.Description.Part> parts = new ArrayList<>();
JsonObject packInfo = json.getAsJsonObject();
int packFormat = packInfo.get("pack_format").getAsInt();
JsonElement description = packInfo.get("description");
if (description.isJsonPrimitive()) {
parts.add(new ModInfo.Description.Part(parseText(description)));
} else if (description.isJsonArray()) {
for (JsonElement element : description.getAsJsonArray()) {
JsonObject descriptionPart = element.getAsJsonObject();
parts.add(new ModInfo.Description.Part(descriptionPart.get("text").getAsString(), descriptionPart.get("color").getAsString()));
}
} else {
throw new JsonParseException("pack.mcmeta::pack::description should be String or array of text objects with text and color fields");
}
return new PackInfo(packFormat, new ModInfo.Description(parts));
}
}
public static ModInfo fromFile(ModManager modManager, File modFile) throws IOException, JsonParseException {
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modFile.toPath())) {
Path mcmod = fs.getPath("pack.mcmeta");
if (Files.notExists(mcmod))
throw new IOException("File " + modFile + " is not a resource pack.");
PackMcMeta metadata = JsonUtils.fromNonNullJson(FileUtils.readText(mcmod), PackMcMeta.class);
return new ModInfo(modManager, modFile, metadata.pack.description, "", "", "", "", "");
return new ModInfo(modManager, modFile, FileUtils.getNameWithoutExtension(modFile), metadata.pack.description, "", "", "", "");
}
}
}