Work around older Gson versions without record support

This commit is contained in:
Camotoy 2024-06-26 12:49:42 -04:00
parent 7eb5b539b5
commit 360350d44e
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
8 changed files with 60 additions and 19 deletions

View file

@ -25,6 +25,8 @@ dependencies {
compileOnly(libs.paper.mojangapi)
compileOnlyApi(libs.viaversion)
implementation(libs.gson.record.factory) // For 1.16.5/1.17.1
}
platformRelocate("it.unimi.dsi.fastutil")
@ -36,6 +38,7 @@ platformRelocate("me.lucko.commodore")
platformRelocate("org.yaml") // Broken as of 1.20
platformRelocate("org.spongepowered")
platformRelocate("io.leangen.geantyref")
platformRelocate("marcono1234.gson")
// These dependencies are already present on the platform
provided(libs.viaversion)

View file

@ -20,6 +20,10 @@ dependencies {
implementation(libs.configurate.yaml)
api(libs.guava)
compileOnly(libs.gson.record.factory) {
isTransitive = false
}
// Fastutil Maps
implementation(libs.bundles.fastutil)
@ -61,7 +65,7 @@ dependencies {
// Test
testImplementation(libs.junit)
testImplementation(libs.gson.runtime)
testImplementation(libs.gson.runtime) // Record support
// Annotation Processors
compileOnly(projects.ap)

View file

@ -29,7 +29,6 @@ import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import io.netty.channel.epoll.Epoll;
import io.netty.util.NettyRuntime;
@ -57,7 +56,11 @@ import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.command.CommandSource;
import org.geysermc.geyser.api.event.EventBus;
import org.geysermc.geyser.api.event.EventRegistrar;
import org.geysermc.geyser.api.event.lifecycle.*;
import org.geysermc.geyser.api.event.lifecycle.GeyserPostInitializeEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserPostReloadEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserPreInitializeEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserPreReloadEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserShutdownEvent;
import org.geysermc.geyser.api.network.AuthType;
import org.geysermc.geyser.api.network.BedrockListener;
import org.geysermc.geyser.api.network.RemoteServer;
@ -87,7 +90,14 @@ import org.geysermc.geyser.skin.SkinProvider;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.*;
import org.geysermc.geyser.util.AssetUtils;
import org.geysermc.geyser.util.CooldownUtils;
import org.geysermc.geyser.util.DimensionUtils;
import org.geysermc.geyser.util.JsonUtils;
import org.geysermc.geyser.util.Metrics;
import org.geysermc.geyser.util.NewsHandler;
import org.geysermc.geyser.util.VersionCheckUtils;
import org.geysermc.geyser.util.WebUtils;
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
import java.io.File;
@ -101,7 +111,14 @@ import java.net.UnknownHostException;
import java.nio.file.Path;
import java.security.Key;
import java.text.DecimalFormat;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
@ -118,7 +135,7 @@ public class GeyserImpl implements GeyserApi {
.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final Gson GSON = JsonUtils.createGson();
public static final String NAME = "Geyser";
public static final String GIT_VERSION = BuildData.GIT_VERSION;

View file

@ -30,6 +30,7 @@ import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.pack.ResourcePackManifest;
@ -46,6 +47,7 @@ public record GeyserResourcePackManifest(@SerializedName("format_version") int f
public record Dependency(UUID uuid, Version version) implements ResourcePackManifest.Dependency { }
@JsonAdapter(value = Version.VersionDeserializer.class)
public record Version(int major, int minor, int patch) implements ResourcePackManifest.Version {
@Override

View file

@ -25,8 +25,6 @@
package org.geysermc.geyser.registry.loader;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.event.lifecycle.GeyserLoadResourcePacksEvent;
import org.geysermc.geyser.api.pack.ResourcePack;
@ -57,9 +55,6 @@ import java.util.zip.ZipFile;
* Loads {@link ResourcePack}s within a {@link Path} directory, firing the {@link GeyserLoadResourcePacksEvent}.
*/
public class ResourcePackLoader implements RegistryLoader<Path, Map<String, ResourcePack>> {
private static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(GeyserResourcePackManifest.Version.class, new GeyserResourcePackManifest.Version.VersionDeserializer())
.create();
static final PathMatcher PACK_MATCHER = FileSystems.getDefault().getPathMatcher("glob:**.{zip,mcpack}");
@ -140,7 +135,7 @@ public class ResourcePackLoader implements RegistryLoader<Path, Map<String, Reso
}
if (name.contains("manifest.json")) {
try {
GeyserResourcePackManifest manifest = FileUtils.loadJson(GSON, zip.getInputStream(x), GeyserResourcePackManifest.class);
GeyserResourcePackManifest manifest = FileUtils.loadJson(zip.getInputStream(x), GeyserResourcePackManifest.class);
if (manifest.header().uuid() != null) {
manifestReference.set(manifest);
}

View file

@ -30,11 +30,15 @@ import com.fasterxml.jackson.annotation.Nulls;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.google.gson.Gson;
import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl;
import java.io.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.annotation.Annotation;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
@ -65,12 +69,8 @@ public class FileUtils {
}
public static <T> T loadJson(InputStream src, Class<T> valueType) {
return loadJson(GeyserImpl.GSON, src, valueType);
}
public static <T> T loadJson(Gson gson, InputStream src, Class<T> valueType) {
// Read specifically with UTF-8 to allow any non-UTF-encoded JSON to read
return gson.fromJson(new InputStreamReader(src, StandardCharsets.UTF_8), valueType);
return GeyserImpl.GSON.fromJson(new InputStreamReader(src, StandardCharsets.UTF_8), valueType);
}
/**

View file

@ -25,9 +25,13 @@
package org.geysermc.geyser.util;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import marcono1234.gson.recordadapter.RecordTypeAdapterFactory;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.pack.GeyserResourcePackManifest;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -48,6 +52,21 @@ public final class JsonUtils {
return GeyserImpl.GSON.fromJson(new InputStreamReader(stream), type);
}
public static Gson createGson() {
GsonBuilder builder = new GsonBuilder().setPrettyPrinting();
try {
new Gson().fromJson("{\"version\":[1,0,0],\"uuid\":\"eebb4ea8-a701-11eb-95ba-047d7bb283ba\"}", GeyserResourcePackManifest.Dependency.class);
} catch (Throwable e) {
// 1.16.5 and 1.17.1 (at minimum) have an outdated Gson version that doesn't support records.
// Remove this workaround when all platforms support Gson 2.10+
// (Explicitly allow missing component values - the dependencies module for resource packs, for example, can be missing)
builder.registerTypeAdapterFactory(RecordTypeAdapterFactory.builder().allowMissingComponentValues().create())
// Since this is a record, the above will take precedence unless we explicitly declare it.
.registerTypeAdapter(GeyserResourcePackManifest.Version.class, new GeyserResourcePackManifest.Version.VersionDeserializer());
}
return builder.create();
}
private JsonUtils() {
}
}

View file

@ -113,6 +113,7 @@ commodore = { group = "me.lucko", name = "commodore", version.ref = "commodore"
guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
gson-runtime = { group = "com.google.code.gson", name = "gson", version.ref = "gson-runtime" }
gson-record-factory = { group = "com.github.Marcono1234", name = "gson-record-type-adapter-factory", version = "0.3.0" }
junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" }
mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" }
mcprotocollib = { group = "org.geysermc.mcprotocollib", name = "protocol", version.ref = "mcprotocollib" }