Start migrating to Gson only

This commit is contained in:
Camotoy 2024-05-27 19:48:35 -04:00
parent a135d3c4da
commit 25a755fd03
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
15 changed files with 135 additions and 127 deletions

View file

@ -14,6 +14,8 @@ dependencies {
implementation(libs.bundles.jline)
implementation(libs.bundles.log4j)
implementation(libs.gson.runtime)
}
application {

View file

@ -26,9 +26,11 @@
package org.geysermc.geyser;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
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;
import io.netty.util.concurrent.DefaultThreadFactory;
@ -87,8 +89,10 @@ import org.geysermc.geyser.util.*;
import org.geysermc.mcprotocollib.network.tcp.TcpSession;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
@ -112,6 +116,8 @@ 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 String NAME = "Geyser";
public static final String GIT_VERSION = "${gitVersion}";
public static final String VERSION = "${version}";
@ -527,11 +533,11 @@ public class GeyserImpl implements GeyserApi {
File tokensFile = bootstrap.getSavedUserLoginsFolder().resolve(Constants.SAVED_REFRESH_TOKEN_FILE).toFile();
if (tokensFile.exists()) {
TypeReference<Map<String, String>> type = new TypeReference<>() { };
Type type = new TypeToken<Map<String, String>>() { }.getType();
Map<String, String> refreshTokenFile = null;
try {
refreshTokenFile = JSON_MAPPER.readValue(tokensFile, type);
try (FileReader reader = new FileReader(tokensFile)) {
refreshTokenFile = GSON.fromJson(reader, type);
} catch (IOException e) {
logger.error("Cannot load saved user tokens!", e);
}
@ -824,11 +830,9 @@ public class GeyserImpl implements GeyserApi {
scheduledThread.execute(() -> {
// Ensure all writes are handled on the same thread
File savedTokens = getBootstrap().getSavedUserLoginsFolder().resolve(Constants.SAVED_REFRESH_TOKEN_FILE).toFile();
TypeReference<Map<String, String>> type = new TypeReference<>() { };
Type type = new TypeToken<Map<String, String>>() { }.getType();
try (FileWriter writer = new FileWriter(savedTokens)) {
JSON_MAPPER.writerFor(type)
.withDefaultPrettyPrinter()
.writeValue(writer, savedRefreshTokens);
GSON.toJson(savedRefreshTokens, type, writer);
} catch (IOException e) {
getLogger().error("Unable to write saved refresh tokens!", e);
}

View file

@ -25,7 +25,8 @@
package org.geysermc.geyser.command.defaults;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.util.PlatformType;
@ -179,7 +180,7 @@ public class ConnectionTestCommand extends GeyserCommand {
CONNECTION_TEST_MOTD = connectionTestMotd;
sender.sendMessage("Testing server connection to " + ip + " with port: " + port + " now. Please wait...");
JsonNode output;
JsonObject output;
try {
String hostname = URLEncoder.encode(ip, StandardCharsets.UTF_8);
output = WebUtils.getJson("https://checker.geysermc.org/ping?hostname=" + hostname + "&port=" + port);
@ -187,18 +188,18 @@ public class ConnectionTestCommand extends GeyserCommand {
CONNECTION_TEST_MOTD = null;
}
if (output.get("success").asBoolean()) {
JsonNode cache = output.get("cache");
if (output.get("success").getAsBoolean()) {
JsonObject cache = output.getAsJsonObject("cache");
String when;
if (cache.get("fromCache").asBoolean()) {
when = cache.get("secondsSince").asInt() + " seconds ago";
if (cache.get("fromCache").isJsonPrimitive()) {
when = cache.get("secondsSince").getAsBoolean() + " seconds ago";
} else {
when = "now";
}
JsonNode ping = output.get("ping");
JsonNode pong = ping.get("pong");
String remoteMotd = pong.get("motd").asText();
JsonObject ping = output.getAsJsonObject("ping");
JsonObject pong = ping.getAsJsonObject("pong");
String remoteMotd = pong.get("motd").getAsString();
if (!connectionTestMotd.equals(remoteMotd)) {
sender.sendMessage("The MOTD did not match when we pinged the server (we got '" + remoteMotd + "'). " +
"Did you supply the correct IP and port of your server?");
@ -206,7 +207,7 @@ public class ConnectionTestCommand extends GeyserCommand {
return;
}
if (ping.get("tcpFirst").asBoolean()) {
if (ping.get("tcpFirst").getAsBoolean()) {
sender.sendMessage("Your server hardware likely has some sort of firewall preventing people from joining easily. See https://geysermc.link/ovh-firewall for more information.");
sendLinks(sender);
return;
@ -218,9 +219,9 @@ public class ConnectionTestCommand extends GeyserCommand {
}
sender.sendMessage("Your server is likely unreachable from outside the network!");
JsonNode message = output.get("message");
if (message != null && !message.asText().isEmpty()) {
sender.sendMessage("Got the error message: " + message.asText());
JsonElement message = output.get("message");
if (message != null && !message.getAsString().isEmpty()) {
sender.sendMessage("Got the error message: " + message.getAsString());
}
sendLinks(sender);
} catch (Exception e) {

View file

@ -52,6 +52,9 @@ public class ConfigLoaderTemp {
--------------------------------""";
public static <T extends GeyserConfig> T load(Class<T> configClass) throws IOException {
if (true) {
return null; // For now
}
var loader = YamlConfigurationLoader.builder()
.file(new File("newconfig.yml"))
.defaultOptions(InterfaceDefaultOptions.get()

View file

@ -27,10 +27,11 @@ package org.geysermc.geyser.dump;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.hash.Hashing;
import com.google.common.io.ByteSource;
import com.google.common.io.Files;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.Getter;
@ -249,9 +250,9 @@ public class DumpInfo {
Map<String, String> fields = new HashMap<>();
fields.put("content", FileUtils.readAllLines(GeyserImpl.getInstance().getBootstrap().getLogsPath()).collect(Collectors.joining("\n")));
JsonNode logData = GeyserImpl.JSON_MAPPER.readTree(WebUtils.postForm("https://api.mclo.gs/1/log", fields));
JsonObject logData = new JsonParser().parse(WebUtils.postForm("https://api.mclo.gs/1/log", fields)).getAsJsonObject();
this.link = logData.get("url").textValue();
this.link = logData.get("url").getAsString();
} catch (IOException ignored) { }
}
}

View file

@ -25,14 +25,16 @@
package org.geysermc.geyser.registry.loader;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import org.geysermc.geyser.GeyserImpl;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.Map;
public class BiomeIdentifierRegistryLoader implements RegistryLoader<String, Object2IntMap<String>> {
@ -44,11 +46,11 @@ public class BiomeIdentifierRegistryLoader implements RegistryLoader<String, Obj
// The server sends the corresponding Java network IDs, so we don't need to worry about that now.
// Reference variable for Jackson to read off of
TypeReference<Map<String, BiomeEntry>> biomeEntriesType = new TypeReference<>() { };
Type biomeEntriesType = new TypeToken<Map<String, BiomeEntry>>() { }.getType();
Map<String, BiomeEntry> biomeEntries;
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/biomes.json")) {
biomeEntries = GeyserImpl.JSON_MAPPER.readValue(stream, biomeEntriesType);
biomeEntries = GeyserImpl.GSON.fromJson(new InputStreamReader(stream), biomeEntriesType);
} catch (IOException e) {
throw new AssertionError("Unable to load Bedrock runtime biomes", e);
}
@ -66,7 +68,7 @@ public class BiomeIdentifierRegistryLoader implements RegistryLoader<String, Obj
/**
* The Bedrock network ID for this biome.
*/
@JsonProperty("bedrock_id")
@SerializedName("bedrock_id")
private int bedrockId;
}
}

View file

@ -25,12 +25,12 @@
package org.geysermc.geyser.registry.loader;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.geysermc.geyser.GeyserImpl;
import java.io.InputStream;
import java.util.Map;
import java.util.WeakHashMap;
import java.io.InputStreamReader;
/**
* An abstract registry loader for loading effects from a resource path.
@ -38,21 +38,12 @@ import java.util.WeakHashMap;
* @param <T> the value
*/
public abstract class EffectRegistryLoader<T> implements RegistryLoader<String, T> {
private static final Map<String, JsonNode> loadedFiles = new WeakHashMap<>();
public void loadFile(String input) {
if (!loadedFiles.containsKey(input)) {
JsonNode effects;
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input)) {
effects = GeyserImpl.JSON_MAPPER.readTree(stream);
} catch (Exception e) {
throw new AssertionError("Unable to load registrations for " + input, e);
}
loadedFiles.put(input, effects);
public JsonObject loadFile(String input) {
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input)) {
return new JsonParser().parse(new InputStreamReader(stream)).getAsJsonObject();
} catch (Exception e) {
throw new AssertionError("Unable to load registrations for " + input, e);
}
}
public JsonNode get(String input) {
return loadedFiles.get(input);
}
}

View file

@ -25,7 +25,10 @@
package org.geysermc.geyser.registry.loader;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import org.geysermc.geyser.GeyserImpl;
@ -35,41 +38,39 @@ import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.EnchantmentData;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Map;
public class EnchantmentRegistryLoader implements RegistryLoader<String, Map<JavaEnchantment, EnchantmentData>> {
@Override
public Map<JavaEnchantment, EnchantmentData> load(String input) {
JsonNode enchantmentsNode;
JsonObject enchantmentsJson;
try (InputStream enchantmentsStream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input)) {
enchantmentsNode = GeyserImpl.JSON_MAPPER.readTree(enchantmentsStream);
enchantmentsJson = new JsonParser().parse(new InputStreamReader(enchantmentsStream)).getAsJsonObject();
} catch (Exception e) {
throw new AssertionError("Unable to load enchantment data", e);
}
Map<JavaEnchantment, EnchantmentData> enchantments = new EnumMap<>(JavaEnchantment.class);
Iterator<Map.Entry<String, JsonNode>> it = enchantmentsNode.fields();
while (it.hasNext()) {
Map.Entry<String, JsonNode> entry = it.next();
for (Map.Entry<String, JsonElement> entry : enchantmentsJson.entrySet()) {
JavaEnchantment key = JavaEnchantment.getByJavaIdentifier(entry.getKey());
JsonNode node = entry.getValue();
int rarityMultiplier = node.get("anvil_cost").asInt();
int maxLevel = node.get("max_level").asInt();
JsonObject node = entry.getValue().getAsJsonObject();
int rarityMultiplier = node.get("anvil_cost").getAsInt();
int maxLevel = node.get("max_level").getAsInt();
EnumSet<JavaEnchantment> incompatibleEnchantments = EnumSet.noneOf(JavaEnchantment.class);
JsonNode incompatibleEnchantmentsNode = node.get("incompatible_enchantments");
if (incompatibleEnchantmentsNode != null) {
for (JsonNode incompatibleNode : incompatibleEnchantmentsNode) {
incompatibleEnchantments.add(JavaEnchantment.getByJavaIdentifier(incompatibleNode.textValue()));
JsonArray incompatibleEnchantmentsJson = node.getAsJsonArray("incompatible_enchantments");
if (incompatibleEnchantmentsJson != null) {
for (JsonElement incompatibleNode : incompatibleEnchantmentsJson) {
incompatibleEnchantments.add(JavaEnchantment.getByJavaIdentifier(incompatibleNode.getAsString()));
}
}
IntSet validItems = new IntOpenHashSet();
for (JsonNode itemNode : node.get("valid_items")) {
String javaIdentifier = itemNode.textValue();
for (JsonElement itemNode : node.getAsJsonArray("valid_items")) {
String javaIdentifier = itemNode.getAsString();
Item item = Registries.JAVA_ITEM_IDENTIFIERS.get(javaIdentifier);
if (item != null) {
validItems.add(item.javaId());

View file

@ -25,15 +25,15 @@
package org.geysermc.geyser.registry.loader;
import com.fasterxml.jackson.databind.JsonNode;
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
import org.cloudburstmc.protocol.bedrock.data.LevelEventType;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.registry.type.ParticleMapping;
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleType;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
@ -44,16 +44,13 @@ public class ParticleTypesRegistryLoader extends EffectRegistryLoader<Map<Partic
@Override
public Map<ParticleType, ParticleMapping> load(String input) {
this.loadFile(input);
Iterator<Map.Entry<String, JsonNode>> particlesIterator = this.get(input).fields();
JsonObject particlesJson = this.loadFile(input);
Map<ParticleType, ParticleMapping> particles = new Object2ObjectOpenHashMap<>();
try {
while (particlesIterator.hasNext()) {
Map.Entry<String, JsonNode> entry = particlesIterator.next();
for (Map.Entry<String, JsonElement> entry : particlesJson.entrySet()) {
String key = entry.getKey().toUpperCase(Locale.ROOT);
JsonNode bedrockId = entry.getValue().get("bedrockId");
JsonNode eventType = entry.getValue().get("eventType");
JsonElement bedrockId = entry.getValue().getAsJsonObject().get("bedrockId");
JsonElement eventType = entry.getValue().getAsJsonObject().get("eventType");
if (eventType == null && bedrockId == null) {
GeyserImpl.getInstance().getLogger().debug("Skipping particle mapping " + key + " because no Bedrock equivalent exists.");
continue;
@ -63,16 +60,16 @@ public class ParticleTypesRegistryLoader extends EffectRegistryLoader<Map<Partic
if (eventType != null) {
try {
// Check if we have a particle type mapping
type = org.cloudburstmc.protocol.bedrock.data.ParticleType.valueOf(eventType.asText().toUpperCase(Locale.ROOT));
type = org.cloudburstmc.protocol.bedrock.data.ParticleType.valueOf(eventType.getAsString().toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException ex) {
// No particle type; try level event
type = LevelEvent.valueOf(eventType.asText().toUpperCase(Locale.ROOT));
type = LevelEvent.valueOf(eventType.getAsString().toUpperCase(Locale.ROOT));
}
}
particles.put(ParticleType.valueOf(key), new ParticleMapping(
type,
bedrockId == null ? null : bedrockId.asText())
bedrockId == null ? null : bedrockId.getAsString())
);
}
} catch (Exception e) {

View file

@ -25,8 +25,8 @@
package org.geysermc.geyser.registry.loader;
import com.fasterxml.jackson.databind.JsonNode;
import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.cloudburstmc.protocol.bedrock.data.LevelEventType;
import org.geysermc.geyser.GeyserImpl;
@ -34,8 +34,8 @@ import org.geysermc.geyser.translator.level.event.LevelEventTranslator;
import org.geysermc.geyser.translator.level.event.PlaySoundEventTranslator;
import org.geysermc.geyser.translator.level.event.SoundEventEventTranslator;
import org.geysermc.geyser.translator.level.event.SoundLevelEventTranslator;
import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent;
import java.util.Iterator;
import java.util.Map;
/**
@ -47,37 +47,36 @@ public class SoundEventsRegistryLoader extends EffectRegistryLoader<Map<LevelEve
public Map<LevelEvent, LevelEventTranslator> load(String input) {
this.loadFile(input);
Iterator<Map.Entry<String, JsonNode>> effectsIterator = this.get(input).fields();
JsonObject effectsJson = this.loadFile(input);
Map<LevelEvent, LevelEventTranslator> soundEffects = new Object2ObjectOpenHashMap<>();
while (effectsIterator.hasNext()) {
Map.Entry<String, JsonNode> entry = effectsIterator.next();
JsonNode node = entry.getValue();
for (Map.Entry<String, JsonElement> entry : effectsJson.entrySet()) {
JsonObject node = entry.getValue().getAsJsonObject();
try {
String type = node.get("type").asText();
String type = node.get("type").getAsString();
LevelEvent javaEffect = null;
LevelEventTranslator transformer = null;
switch (type) {
case "soundLevel" -> {
javaEffect = org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEventType.valueOf(entry.getKey());
LevelEventType levelEventType = org.cloudburstmc.protocol.bedrock.data.LevelEvent.valueOf(node.get("name").asText());
int data = node.has("data") ? node.get("data").intValue() : 0;
LevelEventType levelEventType = org.cloudburstmc.protocol.bedrock.data.LevelEvent.valueOf(node.get("name").getAsString());
int data = node.has("data") ? node.get("data").getAsInt() : 0;
transformer = new SoundLevelEventTranslator(levelEventType, data);
}
case "soundEvent" -> {
javaEffect = org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEventType.valueOf(entry.getKey());
org.cloudburstmc.protocol.bedrock.data.SoundEvent soundEvent = org.cloudburstmc.protocol.bedrock.data.SoundEvent.valueOf(node.get("name").asText());
String identifier = node.has("identifier") ? node.get("identifier").asText() : "";
int extraData = node.has("extraData") ? node.get("extraData").intValue() : -1;
org.cloudburstmc.protocol.bedrock.data.SoundEvent soundEvent = org.cloudburstmc.protocol.bedrock.data.SoundEvent.valueOf(node.get("name").getAsString());
String identifier = node.has("identifier") ? node.get("identifier").getAsString() : "";
int extraData = node.has("extraData") ? node.get("extraData").getAsInt() : -1;
transformer = new SoundEventEventTranslator(soundEvent, identifier, extraData);
}
case "playSound" -> {
javaEffect = org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEventType.valueOf(entry.getKey());
String name = node.get("name").asText();
float volume = node.has("volume") ? node.get("volume").floatValue() : 1.0f;
boolean pitchSub = node.has("pitch_sub") && node.get("pitch_sub").booleanValue();
float pitchMul = node.has("pitch_mul") ? node.get("pitch_mul").floatValue() : 1.0f;
float pitchAdd = node.has("pitch_add") ? node.get("pitch_add").floatValue() : 0.0f;
boolean relative = !node.has("relative") || node.get("relative").booleanValue();
String name = node.get("name").getAsString();
float volume = node.has("volume") ? node.get("volume").getAsFloat() : 1.0f;
boolean pitchSub = node.has("pitch_sub") && node.get("pitch_sub").getAsBoolean();
float pitchMul = node.has("pitch_mul") ? node.get("pitch_mul").getAsFloat() : 1.0f;
float pitchAdd = node.has("pitch_add") ? node.get("pitch_add").getAsFloat() : 0.0f;
boolean relative = !node.has("relative") || node.get("relative").getAsBoolean();
transformer = new PlaySoundEventTranslator(name, volume, pitchSub, pitchMul, pitchAdd, relative);
}
}

View file

@ -25,14 +25,16 @@
package org.geysermc.geyser.registry.loader;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.registry.type.SoundMapping;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
@ -42,26 +44,24 @@ public class SoundRegistryLoader implements RegistryLoader<String, Map<String, S
@Override
public Map<String, SoundMapping> load(String input) {
JsonNode soundsTree;
JsonObject soundsJson;
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow(input)) {
soundsTree = GeyserImpl.JSON_MAPPER.readTree(stream);
soundsJson = new JsonParser().parse(new InputStreamReader(stream)).getAsJsonObject();
} catch (IOException e) {
throw new AssertionError("Unable to load sound mappings", e);
}
Map<String, SoundMapping> soundMappings = new HashMap<>();
Iterator<Map.Entry<String, JsonNode>> soundsIterator = soundsTree.fields();
while(soundsIterator.hasNext()) {
Map.Entry<String, JsonNode> next = soundsIterator.next();
JsonNode brMap = next.getValue();
String javaSound = next.getKey();
for (Map.Entry<String, JsonElement> entry : soundsJson.entrySet()) {
JsonObject brMap = entry.getValue().getAsJsonObject();
String javaSound = entry.getKey();
soundMappings.put(javaSound, new SoundMapping(
javaSound,
brMap.has("bedrock_mapping") && brMap.get("bedrock_mapping").isTextual() ? brMap.get("bedrock_mapping").asText() : null,
brMap.has("playsound_mapping") && brMap.get("playsound_mapping").isTextual() ? brMap.get("playsound_mapping").asText() : null,
brMap.has("extra_data") && brMap.get("extra_data").isInt() ? brMap.get("extra_data").asInt() : -1,
brMap.has("identifier") && brMap.get("identifier").isTextual() ? brMap.get("identifier").asText() : null,
brMap.has("level_event") && brMap.get("level_event").isBoolean() && brMap.get("level_event").asBoolean()
brMap.has("bedrock_mapping") ? brMap.get("bedrock_mapping").getAsString() : null,
brMap.has("playsound_mapping") ? brMap.get("playsound_mapping").getAsString() : null,
brMap.has("extra_data") ? brMap.get("extra_data").getAsInt() : -1,
brMap.has("identifier") ? brMap.get("identifier").getAsString() : null,
brMap.has("level_event") && brMap.get("level_event").getAsBoolean()
)
);
}

View file

@ -25,13 +25,11 @@
package org.geysermc.geyser.skin;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.bytes.ByteArrays;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl;
@ -56,7 +54,9 @@ import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.*;
import java.util.function.Predicate;
@ -486,13 +486,13 @@ public class SkinProvider {
public static CompletableFuture<@Nullable String> requestTexturesFromUUID(String uuid) {
return CompletableFuture.supplyAsync(() -> {
try {
JsonNode node = WebUtils.getJson("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid);
JsonNode properties = node.get("properties");
JsonObject node = WebUtils.getJson("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid);
JsonObject properties = node.getAsJsonObject("properties");
if (properties == null) {
GeyserImpl.getInstance().getLogger().debug("No properties found in Mojang response for " + uuid);
return null;
}
return node.get("properties").get(0).get("value").asText();
return node.getAsJsonArray("properties").get(0).getAsJsonObject().get("value").getAsString();
} catch (Exception e) {
GeyserImpl.getInstance().getLogger().debug("Unable to request textures for " + uuid);
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
@ -513,13 +513,13 @@ public class SkinProvider {
return CompletableFuture.supplyAsync(() -> {
try {
// Offline skin, or no present UUID
JsonNode node = WebUtils.getJson("https://api.mojang.com/users/profiles/minecraft/" + username);
JsonNode id = node.get("id");
JsonObject node = WebUtils.getJson("https://api.mojang.com/users/profiles/minecraft/" + username);
JsonElement id = node.get("id");
if (id == null) {
GeyserImpl.getInstance().getLogger().debug("No UUID found in Mojang response for " + username);
return null;
}
return id.asText();
return id.getAsString();
} catch (Exception e) {
if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
e.printStackTrace();

View file

@ -25,7 +25,7 @@
package org.geysermc.geyser.util;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonObject;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.event.ClickEvent;
@ -92,9 +92,9 @@ public final class VersionCheckUtils {
public static void checkForGeyserUpdate(Supplier<GeyserCommandSource> recipient) {
CompletableFuture.runAsync(() -> {
try {
JsonNode json = WebUtils.getJson("https://api.geysermc.org/v2/versions/geyser");
JsonNode bedrock = json.get("bedrock").get("protocol");
int protocolVersion = bedrock.get("id").asInt();
JsonObject json = WebUtils.getJson("https://api.geysermc.org/v2/versions/geyser");
JsonObject bedrock = json.getAsJsonObject("bedrock").getAsJsonObject("protocol");
int protocolVersion = bedrock.get("id").getAsInt();
if (GameProtocol.getBedrockCodec(protocolVersion) != null) {
LATEST_BEDROCK_RELEASE = OptionalInt.empty();
// We support the latest version! No need to print a message.
@ -102,7 +102,7 @@ public final class VersionCheckUtils {
}
LATEST_BEDROCK_RELEASE = OptionalInt.of(protocolVersion);
final String newBedrockVersion = bedrock.get("name").asText();
final String newBedrockVersion = bedrock.get("name").getAsString();
// Delayed for two reasons: save unnecessary processing, and wait to load locale if this is on join.
GeyserCommandSource sender = recipient.get();

View file

@ -26,6 +26,9 @@
package org.geysermc.geyser.util;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl;
@ -71,12 +74,14 @@ public class WebUtils {
* @param reqURL URL to fetch
* @return the response as JSON
*/
public static JsonNode getJson(String reqURL) throws IOException {
public static JsonObject getJson(String reqURL) throws IOException {
HttpURLConnection con = (HttpURLConnection) new URL(reqURL).openConnection();
con.setRequestProperty("User-Agent", getUserAgent());
con.setConnectTimeout(10000);
con.setReadTimeout(10000);
return GeyserImpl.JSON_MAPPER.readTree(con.getInputStream());
try (JsonReader reader = GeyserImpl.GSON.newJsonReader(new InputStreamReader(con.getInputStream()))) {
return new JsonParser().parse(reader).getAsJsonObject();
}
}
/**

View file

@ -9,7 +9,8 @@ fastutil = "8.5.2"
netty = "4.1.107.Final"
netty-io-uring = "0.0.25.Final-SNAPSHOT"
guava = "29.0-jre"
gson = "2.3.1" # Provided by Spigot 1.8.8
gson = "2.3.1" # Provided by Spigot 1.8.8 TODO bump to 2.8.1 or similar (Spigot 1.16.5 version) after Merge
gson-runtime = "2.10.1"
websocket = "1.5.1"
protocol = "3.0.0.Beta1-20240411.165033-129"
protocol-connection = "3.0.0.Beta1-20240411.165033-128"
@ -111,6 +112,7 @@ checker-qual = { group = "org.checkerframework", name = "checker-qual", version.
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" }
junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" }
mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" }
mcprotocollib = { group = "com.github.geysermc", name = "mcprotocollib", version.ref = "mcprotocollib" }