Fix: failed to parse datapack pack.mcmeta in 6th format. Closes #840.
This commit is contained in:
@@ -132,7 +132,7 @@ class DatapackListPageSkin extends SkinBase<DatapackListPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String getSubtitle() {
|
String getSubtitle() {
|
||||||
return StringUtils.parseColorEscapes(packInfo.getDescription());
|
return StringUtils.parseColorEscapes(packInfo.getDescription().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
Datapack.Pack getPackInfo() {
|
Datapack.Pack getPackInfo() {
|
||||||
|
|||||||
@@ -202,10 +202,10 @@ public class Datapack {
|
|||||||
private Path file;
|
private Path file;
|
||||||
private final BooleanProperty active;
|
private final BooleanProperty active;
|
||||||
private final String id;
|
private final String id;
|
||||||
private final String description;
|
private final ModInfo.Description description;
|
||||||
private final Datapack datapack;
|
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.file = file;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
@@ -235,7 +235,7 @@ public class Datapack {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription() {
|
public ModInfo.Description getDescription() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public final class FabricModMetadata {
|
|||||||
throw new IOException("File " + modFile + " is not a Fabric mod.");
|
throw new IOException("File " + modFile + " is not a Fabric mod.");
|
||||||
FabricModMetadata metadata = JsonUtils.fromNonNullJson(FileUtils.readText(mcmod), FabricModMetadata.class);
|
FabricModMetadata metadata = JsonUtils.fromNonNullJson(FileUtils.readText(mcmod), FabricModMetadata.class);
|
||||||
String authors = metadata.authors == null ? "" : metadata.authors.stream().map(author -> author.name).collect(Collectors.joining(", "));
|
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", "") : "");
|
authors, metadata.version, "", metadata.contact != null ? metadata.contact.getOrDefault("homepage", "") : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ public final class ForgeModMetadata {
|
|||||||
authors = String.join(", ", metadata.getAuthorList());
|
authors = String.join(", ", metadata.getAuthorList());
|
||||||
if (StringUtils.isBlank(authors))
|
if (StringUtils.isBlank(authors))
|
||||||
authors = metadata.getCredits();
|
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(),
|
authors, metadata.getVersion(), metadata.getGameVersion(),
|
||||||
StringUtils.isBlank(metadata.getUrl()) ? metadata.getUpdateUrl() : metadata.url);
|
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);
|
LiteModMetadata metadata = JsonUtils.GSON.fromJson(IOUtils.readFullyAsString(zipFile.getInputStream(entry)), LiteModMetadata.class);
|
||||||
if (metadata == null)
|
if (metadata == null)
|
||||||
throw new IOException("Mod " + modFile + " `litemod.json` is malformed.");
|
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());
|
metadata.getVersion(), metadata.getGameVersion(), metadata.getUpdateURI());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,16 +17,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.mod;
|
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.Logging;
|
||||||
import org.jackhuang.hmcl.util.StringUtils;
|
import org.jackhuang.hmcl.util.StringUtils;
|
||||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||||
|
|
||||||
import javafx.beans.property.BooleanProperty;
|
|
||||||
import javafx.beans.property.SimpleBooleanProperty;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ public final class ModInfo implements Comparable<ModInfo> {
|
|||||||
|
|
||||||
private Path file;
|
private Path file;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final String description;
|
private final Description description;
|
||||||
private final String authors;
|
private final String authors;
|
||||||
private final String version;
|
private final String version;
|
||||||
private final String gameVersion;
|
private final String gameVersion;
|
||||||
@@ -46,11 +47,11 @@ public final class ModInfo implements Comparable<ModInfo> {
|
|||||||
private final String fileName;
|
private final String fileName;
|
||||||
private final BooleanProperty activeProperty;
|
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, "", "", "", "");
|
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.file = file.toPath();
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
@@ -86,7 +87,7 @@ public final class ModInfo implements Comparable<ModInfo> {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription() {
|
public Description getDescription() {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,4 +137,48 @@ public final class ModInfo implements Comparable<ModInfo> {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(getFileName());
|
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:
|
default:
|
||||||
throw new IllegalArgumentException("File " + modFile + " is not a mod file.");
|
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 {
|
public void refreshMods() throws IOException {
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.mod;
|
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 com.google.gson.annotations.SerializedName;
|
||||||
import org.jackhuang.hmcl.util.Immutable;
|
import org.jackhuang.hmcl.util.Immutable;
|
||||||
import org.jackhuang.hmcl.util.gson.JsonUtils;
|
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.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.nio.file.FileSystem;
|
import java.nio.file.FileSystem;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
public class PackMcMeta implements Validation {
|
public class PackMcMeta implements Validation {
|
||||||
@@ -55,18 +60,19 @@ public class PackMcMeta implements Validation {
|
|||||||
throw new JsonParseException("pack cannot be null");
|
throw new JsonParseException("pack cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonAdapter(PackInfoDeserializer.class)
|
||||||
public static class PackInfo {
|
public static class PackInfo {
|
||||||
@SerializedName("pack_format")
|
@SerializedName("pack_format")
|
||||||
private final int packFormat;
|
private final int packFormat;
|
||||||
|
|
||||||
@SerializedName("description")
|
@SerializedName("description")
|
||||||
private final String description;
|
private final ModInfo.Description description;
|
||||||
|
|
||||||
public PackInfo() {
|
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.packFormat = packFormat;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
@@ -75,18 +81,76 @@ public class PackMcMeta implements Validation {
|
|||||||
return packFormat;
|
return packFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getDescription() {
|
public ModInfo.Description getDescription() {
|
||||||
return description;
|
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 {
|
public static ModInfo fromFile(ModManager modManager, File modFile) throws IOException, JsonParseException {
|
||||||
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modFile.toPath())) {
|
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modFile.toPath())) {
|
||||||
Path mcmod = fs.getPath("pack.mcmeta");
|
Path mcmod = fs.getPath("pack.mcmeta");
|
||||||
if (Files.notExists(mcmod))
|
if (Files.notExists(mcmod))
|
||||||
throw new IOException("File " + modFile + " is not a resource pack.");
|
throw new IOException("File " + modFile + " is not a resource pack.");
|
||||||
PackMcMeta metadata = JsonUtils.fromNonNullJson(FileUtils.readText(mcmod), PackMcMeta.class);
|
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