Fix: failed to parse datapack pack.mcmeta in 6th format. Closes #840.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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", "") : "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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, "", "", "", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user