3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-12-27 08:30:12 +01:00

Most things now use Gson for JSON

Dieser Commit ist enthalten in:
Camotoy 2024-06-26 01:04:19 -04:00
Ursprung 8d24891c97
Commit 2d33cfd149
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 7EEFB66FE798081F
20 geänderte Dateien mit 432 neuen und 296 gelöschten Zeilen

Datei anzeigen

@ -29,6 +29,7 @@ import lombok.extern.slf4j.Slf4j;
import net.minecrell.terminalconsole.SimpleTerminalConsole; import net.minecrell.terminalconsole.SimpleTerminalConsole;
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator; import org.apache.logging.log4j.core.config.Configurator;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.command.GeyserCommandSource;
@ -84,7 +85,12 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements Gey
@Override @Override
public void debug(String message) { public void debug(String message) {
log.debug(ChatColor.GRAY + message); log.debug(ChatColor.GRAY + "{}", message);
}
@Override
public void debug(@Nullable Object object) {
log.debug("{}", object);
} }
@Override @Override

Datei anzeigen

@ -26,6 +26,7 @@ package org.geysermc.geyser.platform.viaproxy;
import net.raphimc.viaproxy.cli.ConsoleFormatter; import net.raphimc.viaproxy.cli.ConsoleFormatter;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.GeyserLogger;
import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.command.GeyserCommandSource;
@ -75,6 +76,13 @@ public class GeyserViaProxyLogger implements GeyserLogger, GeyserCommandSource {
} }
} }
@Override
public void debug(@Nullable Object object) {
if (this.debug) {
this.logger.debug(ConsoleFormatter.convert(String.valueOf(object)));
}
}
@Override @Override
public void setDebug(boolean debug) { public void setDebug(boolean debug) {
this.debug = debug; this.debug = debug;

Datei anzeigen

@ -99,7 +99,10 @@ public interface GeyserLogger extends GeyserCommandSource {
* @param object the object to log * @param object the object to log
*/ */
default void debug(@Nullable Object object) { default void debug(@Nullable Object object) {
debug(String.valueOf(object)); if (isDebug()) {
// Don't create String object by default
info(String.valueOf(object));
}
} }
/** /**

Datei anzeigen

@ -43,6 +43,7 @@ import java.nio.file.Path;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
@ConfigSerializable
public interface GeyserConfig { public interface GeyserConfig {
BedrockConfig bedrock(); BedrockConfig bedrock();

Datei anzeigen

@ -25,11 +25,10 @@
package org.geysermc.geyser.pack; package org.geysermc.geyser.pack;
import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.TypeAdapter;
import com.fasterxml.jackson.core.JsonParser; import com.google.gson.annotations.SerializedName;
import com.fasterxml.jackson.databind.DeserializationContext; import com.google.gson.stream.JsonReader;
import com.fasterxml.jackson.databind.JsonDeserializer; import com.google.gson.stream.JsonWriter;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.pack.ResourcePackManifest; import org.geysermc.geyser.api.pack.ResourcePackManifest;
@ -37,15 +36,14 @@ import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.UUID; import java.util.UUID;
public record GeyserResourcePackManifest(@JsonProperty("format_version") int formatVersion, Header header, Collection<Module> modules, Collection<Dependency> dependencies) implements ResourcePackManifest { public record GeyserResourcePackManifest(@SerializedName("format_version") int formatVersion, Header header, Collection<Module> modules, Collection<Dependency> dependencies) implements ResourcePackManifest {
public record Header(UUID uuid, Version version, String name, String description, @JsonProperty("min_engine_version") Version minimumSupportedMinecraftVersion) implements ResourcePackManifest.Header { } public record Header(UUID uuid, Version version, String name, String description, @SerializedName("min_engine_version") Version minimumSupportedMinecraftVersion) implements ResourcePackManifest.Header { }
public record Module(UUID uuid, Version version, String type, String description) implements ResourcePackManifest.Module { } public record Module(UUID uuid, Version version, String type, String description) implements ResourcePackManifest.Module { }
public record Dependency(UUID uuid, Version version) implements ResourcePackManifest.Dependency { } public record Dependency(UUID uuid, Version version) implements ResourcePackManifest.Dependency { }
@JsonDeserialize(using = Version.VersionDeserializer.class)
public record Version(int major, int minor, int patch) implements ResourcePackManifest.Version { public record Version(int major, int minor, int patch) implements ResourcePackManifest.Version {
@Override @Override
@ -53,11 +51,17 @@ public record GeyserResourcePackManifest(@JsonProperty("format_version") int for
return major + "." + minor + "." + patch; return major + "." + minor + "." + patch;
} }
public static class VersionDeserializer extends JsonDeserializer<Version> { public static class VersionDeserializer extends TypeAdapter<Version> {
@Override @Override
public Version deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { public void write(JsonWriter jsonWriter, Version version) throws IOException {
int[] version = ctxt.readValue(p, int[].class); }
return new Version(version[0], version[1], version[2]);
@Override
public Version read(JsonReader jsonReader) throws IOException {
jsonReader.beginArray();
Version version = new Version(jsonReader.nextInt(), jsonReader.nextInt(), jsonReader.nextInt());
jsonReader.endArray();
return version;
} }
} }
} }

Datei anzeigen

@ -25,8 +25,7 @@
package org.geysermc.geyser.ping; package org.geysermc.geyser.ping;
import com.fasterxml.jackson.core.JsonParseException; import com.google.gson.JsonSyntaxException;
import com.fasterxml.jackson.databind.JsonMappingException;
import io.netty.handler.codec.haproxy.HAProxyCommand; import io.netty.handler.codec.haproxy.HAProxyCommand;
import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol; import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol;
import io.netty.util.NetUtil; import io.netty.util.NetUtil;
@ -34,9 +33,19 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.util.VarInts; import org.cloudburstmc.nbt.util.VarInts;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.util.JsonUtils;
import java.io.*; import java.io.ByteArrayOutputStream;
import java.net.*; import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.ConnectException;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runnable { public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runnable {
@ -130,11 +139,11 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn
} }
} }
this.pingInfo = GeyserImpl.JSON_MAPPER.readValue(buffer, GeyserPingInfo.class); this.pingInfo = JsonUtils.fromJson(buffer, GeyserPingInfo.class);
} catch (SocketTimeoutException | ConnectException ex) { } catch (SocketTimeoutException | ConnectException ex) {
this.pingInfo = null; this.pingInfo = null;
this.geyser.getLogger().debug("Connection timeout for ping passthrough."); this.geyser.getLogger().debug("Connection timeout for ping passthrough.");
} catch (JsonParseException | JsonMappingException ex) { } catch (JsonSyntaxException ex) {
this.geyser.getLogger().error("Failed to parse json when pinging server!", ex); this.geyser.getLogger().error("Failed to parse json when pinging server!", ex);
} catch (EOFException e) { } catch (EOFException e) {
this.pingInfo = null; this.pingInfo = null;

Datei anzeigen

@ -30,10 +30,10 @@ import com.google.gson.reflect.TypeToken;
import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.util.JsonUtils;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
@ -50,7 +50,7 @@ public class BiomeIdentifierRegistryLoader implements RegistryLoader<String, Obj
Map<String, BiomeEntry> biomeEntries; Map<String, BiomeEntry> biomeEntries;
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/biomes.json")) { try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/biomes.json")) {
biomeEntries = GeyserImpl.GSON.fromJson(new InputStreamReader(stream), biomeEntriesType); biomeEntries = JsonUtils.fromJson(stream, biomeEntriesType);
} catch (IOException e) { } catch (IOException e) {
throw new AssertionError("Unable to load Bedrock runtime biomes", e); throw new AssertionError("Unable to load Bedrock runtime biomes", e);
} }

Datei anzeigen

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

Datei anzeigen

@ -25,7 +25,8 @@
package org.geysermc.geyser.registry.mappings; package org.geysermc.geyser.registry.mappings;
import com.fasterxml.jackson.databind.JsonNode; import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -35,6 +36,7 @@ import org.geysermc.geyser.registry.mappings.util.CustomBlockMapping;
import org.geysermc.geyser.registry.mappings.versions.MappingsReader; import org.geysermc.geyser.registry.mappings.versions.MappingsReader;
import org.geysermc.geyser.registry.mappings.versions.MappingsReader_v1; import org.geysermc.geyser.registry.mappings.versions.MappingsReader_v1;
import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@ -95,10 +97,10 @@ public class MappingsConfigReader {
} }
} }
public @Nullable JsonNode getMappingsRoot(Path file) { public @Nullable JsonObject getMappingsRoot(Path file) {
JsonNode mappingsRoot; JsonObject mappingsRoot;
try { try (FileReader reader = new FileReader(file.toFile())) {
mappingsRoot = GeyserImpl.JSON_MAPPER.readTree(file.toFile()); mappingsRoot = (JsonObject) new JsonParser().parse(reader);
} catch (IOException e) { } catch (IOException e) {
GeyserImpl.getInstance().getLogger().error("Failed to read custom mapping file: " + file, e); GeyserImpl.getInstance().getLogger().error("Failed to read custom mapping file: " + file, e);
return null; return null;
@ -112,8 +114,8 @@ public class MappingsConfigReader {
return mappingsRoot; return mappingsRoot;
} }
public int getFormatVersion(JsonNode mappingsRoot, Path file) { public int getFormatVersion(JsonObject mappingsRoot, Path file) {
int formatVersion = mappingsRoot.get("format_version").asInt(); int formatVersion = mappingsRoot.get("format_version").getAsInt();
if (!this.mappingReaders.containsKey(formatVersion)) { if (!this.mappingReaders.containsKey(formatVersion)) {
GeyserImpl.getInstance().getLogger().error("Mappings file " + file + " has an unknown format version: " + formatVersion); GeyserImpl.getInstance().getLogger().error("Mappings file " + file + " has an unknown format version: " + formatVersion);
return -1; return -1;
@ -122,7 +124,7 @@ public class MappingsConfigReader {
} }
public void readItemMappingsFromJson(Path file, BiConsumer<String, CustomItemData> consumer) { public void readItemMappingsFromJson(Path file, BiConsumer<String, CustomItemData> consumer) {
JsonNode mappingsRoot = getMappingsRoot(file); JsonObject mappingsRoot = getMappingsRoot(file);
if (mappingsRoot == null) { if (mappingsRoot == null) {
return; return;
@ -138,7 +140,7 @@ public class MappingsConfigReader {
} }
public void readBlockMappingsFromJson(Path file, BiConsumer<String, CustomBlockMapping> consumer) { public void readBlockMappingsFromJson(Path file, BiConsumer<String, CustomBlockMapping> consumer) {
JsonNode mappingsRoot = getMappingsRoot(file); JsonObject mappingsRoot = getMappingsRoot(file);
if (mappingsRoot == null) { if (mappingsRoot == null) {
return; return;

Datei anzeigen

@ -25,7 +25,7 @@
package org.geysermc.geyser.registry.mappings.versions; package org.geysermc.geyser.registry.mappings.versions;
import com.fasterxml.jackson.databind.JsonNode; import com.google.gson.JsonObject;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomItemData;
import org.geysermc.geyser.api.item.custom.CustomRenderOffsets; import org.geysermc.geyser.api.item.custom.CustomRenderOffsets;
@ -36,14 +36,14 @@ import java.nio.file.Path;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
public abstract class MappingsReader { public abstract class MappingsReader {
public abstract void readItemMappings(Path file, JsonNode mappingsRoot, BiConsumer<String, CustomItemData> consumer); public abstract void readItemMappings(Path file, JsonObject mappingsRoot, BiConsumer<String, CustomItemData> consumer);
public abstract void readBlockMappings(Path file, JsonNode mappingsRoot, BiConsumer<String, CustomBlockMapping> consumer); public abstract void readBlockMappings(Path file, JsonObject mappingsRoot, BiConsumer<String, CustomBlockMapping> consumer);
public abstract CustomItemData readItemMappingEntry(JsonNode node) throws InvalidCustomMappingsFileException; public abstract CustomItemData readItemMappingEntry(JsonObject node) throws InvalidCustomMappingsFileException;
public abstract CustomBlockMapping readBlockMappingEntry(String identifier, JsonNode node) throws InvalidCustomMappingsFileException; public abstract CustomBlockMapping readBlockMappingEntry(String identifier, JsonObject node) throws InvalidCustomMappingsFileException;
protected @Nullable CustomRenderOffsets fromJsonNode(JsonNode node) { protected @Nullable CustomRenderOffsets fromJsonObject(JsonObject node) {
if (node == null || !node.isObject()) { if (node == null) {
return null; return null;
} }
@ -53,9 +53,8 @@ public abstract class MappingsReader {
); );
} }
protected CustomRenderOffsets.@Nullable Hand getHandOffsets(JsonNode node, String hand) { protected CustomRenderOffsets.@Nullable Hand getHandOffsets(JsonObject node, String hand) {
JsonNode tmpNode = node.get(hand); if (!(node.get(hand) instanceof JsonObject tmpNode)) {
if (tmpNode == null || !tmpNode.isObject()) {
return null; return null;
} }
@ -65,9 +64,8 @@ public abstract class MappingsReader {
); );
} }
protected CustomRenderOffsets.@Nullable Offset getPerspectiveOffsets(JsonNode node, String perspective) { protected CustomRenderOffsets.@Nullable Offset getPerspectiveOffsets(JsonObject node, String perspective) {
JsonNode tmpNode = node.get(perspective); if (!(node.get(perspective) instanceof JsonObject tmpNode)) {
if (tmpNode == null || !tmpNode.isObject()) {
return null; return null;
} }
@ -78,9 +76,8 @@ public abstract class MappingsReader {
); );
} }
protected CustomRenderOffsets.@Nullable OffsetXYZ getOffsetXYZ(JsonNode node, String offsetType) { protected CustomRenderOffsets.@Nullable OffsetXYZ getOffsetXYZ(JsonObject node, String offsetType) {
JsonNode tmpNode = node.get(offsetType); if (!(node.get(offsetType) instanceof JsonObject tmpNode)) {
if (tmpNode == null || !tmpNode.isObject()) {
return null; return null;
} }
@ -89,9 +86,9 @@ public abstract class MappingsReader {
} }
return new CustomRenderOffsets.OffsetXYZ( return new CustomRenderOffsets.OffsetXYZ(
tmpNode.get("x").floatValue(), tmpNode.get("x").getAsFloat(),
tmpNode.get("y").floatValue(), tmpNode.get("y").getAsFloat(),
tmpNode.get("z").floatValue() tmpNode.get("z").getAsFloat()
); );
} }
} }

Datei anzeigen

@ -25,8 +25,10 @@
package org.geysermc.geyser.registry.mappings.versions; package org.geysermc.geyser.registry.mappings.versions;
import com.fasterxml.jackson.databind.JsonNode; import com.google.gson.JsonArray;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
@ -34,9 +36,14 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; import org.geysermc.geyser.api.block.custom.CustomBlockPermutation;
import org.geysermc.geyser.api.block.custom.CustomBlockState; import org.geysermc.geyser.api.block.custom.CustomBlockState;
import org.geysermc.geyser.api.block.custom.component.*; import org.geysermc.geyser.api.block.custom.component.BoxComponent;
import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents;
import org.geysermc.geyser.api.block.custom.component.GeometryComponent;
import org.geysermc.geyser.api.block.custom.component.MaterialInstance;
import org.geysermc.geyser.api.block.custom.component.PlacementConditions;
import org.geysermc.geyser.api.block.custom.component.PlacementConditions.BlockFilterType; import org.geysermc.geyser.api.block.custom.component.PlacementConditions.BlockFilterType;
import org.geysermc.geyser.api.block.custom.component.PlacementConditions.Face; import org.geysermc.geyser.api.block.custom.component.PlacementConditions.Face;
import org.geysermc.geyser.api.block.custom.component.TransformationComponent;
import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomItemData;
import org.geysermc.geyser.api.item.custom.CustomItemOptions; import org.geysermc.geyser.api.item.custom.CustomItemOptions;
import org.geysermc.geyser.api.util.CreativeCategory; import org.geysermc.geyser.api.util.CreativeCategory;
@ -57,7 +64,13 @@ import org.geysermc.geyser.util.MathUtils;
import org.geysermc.geyser.util.MinecraftKey; import org.geysermc.geyser.util.MinecraftKey;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.ArrayList;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -68,7 +81,7 @@ import java.util.stream.Collectors;
*/ */
public class MappingsReader_v1 extends MappingsReader { public class MappingsReader_v1 extends MappingsReader {
@Override @Override
public void readItemMappings(Path file, JsonNode mappingsRoot, BiConsumer<String, CustomItemData> consumer) { public void readItemMappings(Path file, JsonObject mappingsRoot, BiConsumer<String, CustomItemData> consumer) {
this.readItemMappingsV1(file, mappingsRoot, consumer); this.readItemMappingsV1(file, mappingsRoot, consumer);
} }
@ -76,24 +89,24 @@ public class MappingsReader_v1 extends MappingsReader {
* Read item block from a JSON node * Read item block from a JSON node
* *
* @param file The path to the file * @param file The path to the file
* @param mappingsRoot The {@link JsonNode} containing the mappings * @param mappingsRoot The {@link JsonObject} containing the mappings
* @param consumer The consumer to accept the mappings * @param consumer The consumer to accept the mappings
* @see #readBlockMappingsV1(Path, JsonNode, BiConsumer) * @see #readBlockMappingsV1(Path, JsonObject, BiConsumer)
*/ */
@Override @Override
public void readBlockMappings(Path file, JsonNode mappingsRoot, BiConsumer<String, CustomBlockMapping> consumer) { public void readBlockMappings(Path file, JsonObject mappingsRoot, BiConsumer<String, CustomBlockMapping> consumer) {
this.readBlockMappingsV1(file, mappingsRoot, consumer); this.readBlockMappingsV1(file, mappingsRoot, consumer);
} }
public void readItemMappingsV1(Path file, JsonNode mappingsRoot, BiConsumer<String, CustomItemData> consumer) { public void readItemMappingsV1(Path file, JsonObject mappingsRoot, BiConsumer<String, CustomItemData> consumer) {
JsonNode itemsNode = mappingsRoot.get("items"); JsonObject itemsNode = mappingsRoot.getAsJsonObject("items");
if (itemsNode != null && itemsNode.isObject()) { if (itemsNode != null) {
itemsNode.fields().forEachRemaining(entry -> { itemsNode.entrySet().forEach(entry -> {
if (entry.getValue().isArray()) { if (entry.getValue() instanceof JsonArray array) {
entry.getValue().forEach(data -> { array.forEach(data -> {
try { try {
CustomItemData customItemData = this.readItemMappingEntry(data); CustomItemData customItemData = this.readItemMappingEntry((JsonObject) data);
consumer.accept(entry.getKey(), customItemData); consumer.accept(entry.getKey(), customItemData);
} catch (InvalidCustomMappingsFileException e) { } catch (InvalidCustomMappingsFileException e) {
GeyserImpl.getInstance().getLogger().error("Error in registering items for custom mapping file: " + file.toString(), e); GeyserImpl.getInstance().getLogger().error("Error in registering items for custom mapping file: " + file.toString(), e);
@ -108,19 +121,17 @@ public class MappingsReader_v1 extends MappingsReader {
* Read block mappings from a JSON node * Read block mappings from a JSON node
* *
* @param file The path to the file * @param file The path to the file
* @param mappingsRoot The {@link JsonNode} containing the mappings * @param mappingsRoot The {@link JsonObject} containing the mappings
* @param consumer The consumer to accept the mappings * @param consumer The consumer to accept the mappings
* @see #readBlockMappings(Path, JsonNode, BiConsumer) * @see #readBlockMappings(Path, JsonObject, BiConsumer)
*/ */
public void readBlockMappingsV1(Path file, JsonNode mappingsRoot, BiConsumer<String, CustomBlockMapping> consumer) { public void readBlockMappingsV1(Path file, JsonObject mappingsRoot, BiConsumer<String, CustomBlockMapping> consumer) {
JsonNode blocksNode = mappingsRoot.get("blocks"); if (mappingsRoot.get("blocks") instanceof JsonObject blocksNode) {
blocksNode.entrySet().forEach(entry -> {
if (blocksNode != null && blocksNode.isObject()) { if (entry.getValue() instanceof JsonObject jsonObject) {
blocksNode.fields().forEachRemaining(entry -> {
if (entry.getValue().isObject()) {
try { try {
String identifier = MinecraftKey.key(entry.getKey()).asString(); String identifier = MinecraftKey.key(entry.getKey()).asString();
CustomBlockMapping customBlockMapping = this.readBlockMappingEntry(identifier, entry.getValue()); CustomBlockMapping customBlockMapping = this.readBlockMappingEntry(identifier, jsonObject);
consumer.accept(identifier, customBlockMapping); consumer.accept(identifier, customBlockMapping);
} catch (Exception e) { } catch (Exception e) {
GeyserImpl.getInstance().getLogger().error("Error in registering blocks for custom mapping file: " + file.toString()); GeyserImpl.getInstance().getLogger().error("Error in registering blocks for custom mapping file: " + file.toString());
@ -131,85 +142,85 @@ public class MappingsReader_v1 extends MappingsReader {
} }
} }
private CustomItemOptions readItemCustomItemOptions(JsonNode node) { private CustomItemOptions readItemCustomItemOptions(JsonObject node) {
CustomItemOptions.Builder customItemOptions = CustomItemOptions.builder(); CustomItemOptions.Builder customItemOptions = CustomItemOptions.builder();
JsonNode customModelData = node.get("custom_model_data"); JsonElement customModelData = node.get("custom_model_data");
if (customModelData != null && customModelData.isInt()) { if (customModelData != null && customModelData.isJsonPrimitive()) {
customItemOptions.customModelData(customModelData.asInt()); customItemOptions.customModelData(customModelData.getAsInt());
} }
JsonNode damagePredicate = node.get("damage_predicate"); JsonElement damagePredicate = node.get("damage_predicate");
if (damagePredicate != null && damagePredicate.isInt()) { if (damagePredicate != null && damagePredicate.isJsonPrimitive()) {
customItemOptions.damagePredicate(damagePredicate.asInt()); customItemOptions.damagePredicate(damagePredicate.getAsInt());
} }
JsonNode unbreakable = node.get("unbreakable"); JsonElement unbreakable = node.get("unbreakable");
if (unbreakable != null && unbreakable.isBoolean()) { if (unbreakable != null && unbreakable.isJsonPrimitive()) {
customItemOptions.unbreakable(unbreakable.asBoolean()); customItemOptions.unbreakable(unbreakable.getAsBoolean());
} }
JsonNode defaultItem = node.get("default"); JsonElement defaultItem = node.get("default");
if (defaultItem != null && defaultItem.isBoolean()) { if (defaultItem != null && defaultItem.isJsonPrimitive()) {
customItemOptions.defaultItem(defaultItem.asBoolean()); customItemOptions.defaultItem(defaultItem.getAsBoolean());
} }
return customItemOptions.build(); return customItemOptions.build();
} }
@Override @Override
public CustomItemData readItemMappingEntry(JsonNode node) throws InvalidCustomMappingsFileException { public CustomItemData readItemMappingEntry(JsonObject node) throws InvalidCustomMappingsFileException {
if (node == null || !node.isObject()) { if (node == null) {
throw new InvalidCustomMappingsFileException("Invalid item mappings entry"); throw new InvalidCustomMappingsFileException("Invalid item mappings entry");
} }
JsonNode name = node.get("name"); JsonElement name = node.get("name");
if (name == null || !name.isTextual() || name.asText().isEmpty()) { if (name == null || !name.isJsonPrimitive() || name.getAsString().isEmpty()) {
throw new InvalidCustomMappingsFileException("An item entry has no name"); throw new InvalidCustomMappingsFileException("An item entry has no name");
} }
CustomItemData.Builder customItemData = CustomItemData.builder() CustomItemData.Builder customItemData = CustomItemData.builder()
.name(name.asText()) .name(name.getAsString())
.customItemOptions(this.readItemCustomItemOptions(node)); .customItemOptions(this.readItemCustomItemOptions(node));
//The next entries are optional //The next entries are optional
if (node.has("display_name")) { if (node.has("display_name")) {
customItemData.displayName(node.get("display_name").asText()); customItemData.displayName(node.get("display_name").getAsString());
} }
if (node.has("icon")) { if (node.has("icon")) {
customItemData.icon(node.get("icon").asText()); customItemData.icon(node.get("icon").getAsString());
} }
if (node.has("creative_category")) { if (node.has("creative_category")) {
customItemData.creativeCategory(node.get("creative_category").asInt()); customItemData.creativeCategory(node.get("creative_category").getAsInt());
} }
if (node.has("creative_group")) { if (node.has("creative_group")) {
customItemData.creativeGroup(node.get("creative_group").asText()); customItemData.creativeGroup(node.get("creative_group").getAsString());
} }
if (node.has("allow_offhand")) { if (node.has("allow_offhand")) {
customItemData.allowOffhand(node.get("allow_offhand").asBoolean()); customItemData.allowOffhand(node.get("allow_offhand").getAsBoolean());
} }
if (node.has("display_handheld")) { if (node.has("display_handheld")) {
customItemData.displayHandheld(node.get("display_handheld").asBoolean()); customItemData.displayHandheld(node.get("display_handheld").getAsBoolean());
} }
if (node.has("texture_size")) { if (node.has("texture_size")) {
customItemData.textureSize(node.get("texture_size").asInt()); customItemData.textureSize(node.get("texture_size").getAsInt());
} }
if (node.has("render_offsets")) { if (node.has("render_offsets")) {
JsonNode tmpNode = node.get("render_offsets"); JsonObject tmpNode = node.getAsJsonObject("render_offsets");
customItemData.renderOffsets(fromJsonNode(tmpNode)); customItemData.renderOffsets(fromJsonObject(tmpNode));
} }
if (node.get("tags") instanceof ArrayNode tags) { if (node.get("tags") instanceof JsonArray tags) {
Set<String> tagsSet = new ObjectOpenHashSet<>(); Set<String> tagsSet = new ObjectOpenHashSet<>();
tags.forEach(tag -> tagsSet.add(tag.asText())); tags.forEach(tag -> tagsSet.add(tag.getAsString()));
customItemData.tags(tagsSet); customItemData.tags(tagsSet);
} }
@ -220,26 +231,26 @@ public class MappingsReader_v1 extends MappingsReader {
* Read a block mapping entry from a JSON node and Java identifier * Read a block mapping entry from a JSON node and Java identifier
* *
* @param identifier The Java identifier of the block * @param identifier The Java identifier of the block
* @param node The {@link JsonNode} containing the block mapping entry * @param node The {@link JsonObject} containing the block mapping entry
* @return The {@link CustomBlockMapping} record to be read by {@link org.geysermc.geyser.registry.populator.CustomBlockRegistryPopulator} * @return The {@link CustomBlockMapping} record to be read by {@link org.geysermc.geyser.registry.populator.CustomBlockRegistryPopulator}
* @throws InvalidCustomMappingsFileException If the JSON node is invalid * @throws InvalidCustomMappingsFileException If the JSON node is invalid
*/ */
@Override @Override
public CustomBlockMapping readBlockMappingEntry(String identifier, JsonNode node) throws InvalidCustomMappingsFileException { public CustomBlockMapping readBlockMappingEntry(String identifier, JsonObject node) throws InvalidCustomMappingsFileException {
if (node == null || !node.isObject()) { if (node == null) {
throw new InvalidCustomMappingsFileException("Invalid block mappings entry:" + node); throw new InvalidCustomMappingsFileException("Invalid block mappings entry:" + node);
} }
String name = node.get("name").asText(); String name = node.get("name").getAsString();
if (name == null || name.isEmpty()) { if (name == null || name.isEmpty()) {
throw new InvalidCustomMappingsFileException("A block entry has no name"); throw new InvalidCustomMappingsFileException("A block entry has no name");
} }
boolean includedInCreativeInventory = node.has("included_in_creative_inventory") && node.get("included_in_creative_inventory").asBoolean(); boolean includedInCreativeInventory = node.has("included_in_creative_inventory") && node.get("included_in_creative_inventory").getAsBoolean();
CreativeCategory creativeCategory = CreativeCategory.NONE; CreativeCategory creativeCategory = CreativeCategory.NONE;
if (node.has("creative_category")) { if (node.has("creative_category")) {
String categoryName = node.get("creative_category").asText(); String categoryName = node.get("creative_category").getAsString();
try { try {
creativeCategory = CreativeCategory.valueOf(categoryName.toUpperCase()); creativeCategory = CreativeCategory.valueOf(categoryName.toUpperCase());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
@ -249,11 +260,11 @@ public class MappingsReader_v1 extends MappingsReader {
String creativeGroup = ""; String creativeGroup = "";
if (node.has("creative_group")) { if (node.has("creative_group")) {
creativeGroup = node.get("creative_group").asText(); creativeGroup = node.get("creative_group").getAsString();
} }
// If this is true, we will only register the states the user has specified rather than all the possible block states // If this is true, we will only register the states the user has specified rather than all the possible block states
boolean onlyOverrideStates = node.has("only_override_states") && node.get("only_override_states").asBoolean(); boolean onlyOverrideStates = node.has("only_override_states") && node.get("only_override_states").getAsBoolean();
// Create the data for the overall block // Create the data for the overall block
CustomBlockData.Builder customBlockDataBuilder = new GeyserCustomBlockData.Builder() CustomBlockData.Builder customBlockDataBuilder = new GeyserCustomBlockData.Builder()
@ -273,12 +284,9 @@ public class MappingsReader_v1 extends MappingsReader {
Map<String, CustomBlockComponentsMapping> componentsMap = new LinkedHashMap<>(); Map<String, CustomBlockComponentsMapping> componentsMap = new LinkedHashMap<>();
JsonNode stateOverrides = node.get("state_overrides"); if (node.get("state_overrides") instanceof JsonObject stateOverrides) {
if (stateOverrides != null && stateOverrides.isObject()) {
// Load components for specific Java block states // Load components for specific Java block states
Iterator<Map.Entry<String, JsonNode>> fields = stateOverrides.fields(); for (Map.Entry<String, JsonElement> overrideEntry : stateOverrides.entrySet()) {
while (fields.hasNext()) {
Map.Entry<String, JsonNode> overrideEntry = fields.next();
String state = identifier + "[" + overrideEntry.getKey() + "]"; String state = identifier + "[" + overrideEntry.getKey() + "]";
if (!BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().containsKey(state)) { if (!BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().containsKey(state)) {
throw new InvalidCustomMappingsFileException("Unknown Java block state: " + state + " for state_overrides."); throw new InvalidCustomMappingsFileException("Unknown Java block state: " + state + " for state_overrides.");
@ -358,12 +366,12 @@ public class MappingsReader_v1 extends MappingsReader {
/** /**
* Creates a {@link CustomBlockComponents} object for the passed state override or base block node, Java block state identifier, and custom block name * Creates a {@link CustomBlockComponents} object for the passed state override or base block node, Java block state identifier, and custom block name
* *
* @param node the state override or base block {@link JsonNode} * @param element the state override or base block {@link JsonObject}
* @param stateKey the Java block state identifier * @param stateKey the Java block state identifier
* @param name the name of the custom block * @param name the name of the custom block
* @return the {@link CustomBlockComponents} object * @return the {@link CustomBlockComponents} object
*/ */
private CustomBlockComponentsMapping createCustomBlockComponentsMapping(JsonNode node, String stateKey, String name) { private CustomBlockComponentsMapping createCustomBlockComponentsMapping(JsonElement element, String stateKey, String name) {
// This is needed to find the correct selection box for the given block // This is needed to find the correct selection box for the given block
int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(stateKey, -1); int id = BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(stateKey, -1);
BoxComponent boxComponent = createBoxComponent(id); BoxComponent boxComponent = createBoxComponent(id);
@ -372,7 +380,7 @@ public class MappingsReader_v1 extends MappingsReader {
.collisionBox(boxComponent) .collisionBox(boxComponent)
.selectionBox(boxComponent); .selectionBox(boxComponent);
if (node == null) { if (!(element instanceof JsonObject node)) {
// No other components were defined // No other components were defined
return new CustomBlockComponentsMapping(builder.build(), extendedBoxComponent); return new CustomBlockComponentsMapping(builder.build(), extendedBoxComponent);
} }
@ -394,28 +402,28 @@ public class MappingsReader_v1 extends MappingsReader {
// We set this to max value by default so that we may dictate the correct destroy time ourselves // We set this to max value by default so that we may dictate the correct destroy time ourselves
float destructibleByMining = Float.MAX_VALUE; float destructibleByMining = Float.MAX_VALUE;
if (node.has("destructible_by_mining")) { if (node.has("destructible_by_mining")) {
destructibleByMining = node.get("destructible_by_mining").floatValue(); destructibleByMining = node.get("destructible_by_mining").getAsFloat();
} }
builder.destructibleByMining(destructibleByMining); builder.destructibleByMining(destructibleByMining);
if (node.has("geometry")) { if (node.has("geometry")) {
if (node.get("geometry").isTextual()) { if (node.get("geometry").isJsonPrimitive()) {
builder.geometry(new GeyserGeometryComponent.Builder() builder.geometry(new GeyserGeometryComponent.Builder()
.identifier(node.get("geometry").asText()) .identifier(node.get("geometry").getAsString())
.build()); .build());
} else { } else {
JsonNode geometry = node.get("geometry"); JsonObject geometry = node.getAsJsonObject("geometry");
GeometryComponent.Builder geometryBuilder = new GeyserGeometryComponent.Builder(); GeometryComponent.Builder geometryBuilder = new GeyserGeometryComponent.Builder();
if (geometry.has("identifier")) { if (geometry.has("identifier")) {
geometryBuilder.identifier(geometry.get("identifier").asText()); geometryBuilder.identifier(geometry.get("identifier").getAsString());
} }
if (geometry.has("bone_visibility")) { if (geometry.has("bone_visibility")) {
JsonNode boneVisibility = geometry.get("bone_visibility"); if (geometry.get("bone_visibility") instanceof JsonObject boneVisibility) {
if (boneVisibility.isObject()) {
Map<String, String> boneVisibilityMap = new Object2ObjectOpenHashMap<>(); Map<String, String> boneVisibilityMap = new Object2ObjectOpenHashMap<>();
boneVisibility.fields().forEachRemaining(entry -> { boneVisibility.entrySet().forEach(entry -> {
String key = entry.getKey(); String key = entry.getKey();
String value = entry.getValue().isBoolean() ? (entry.getValue().asBoolean() ? "1" : "0") : entry.getValue().asText(); String value = entry.getValue() instanceof JsonPrimitive primitive && primitive.isBoolean()
? (entry.getValue().getAsBoolean() ? "1" : "0") : entry.getValue().getAsString();
boneVisibilityMap.put(key, value); boneVisibilityMap.put(key, value);
}); });
geometryBuilder.boneVisibility(boneVisibilityMap); geometryBuilder.boneVisibility(boneVisibilityMap);
@ -427,30 +435,30 @@ public class MappingsReader_v1 extends MappingsReader {
String displayName = name; String displayName = name;
if (node.has("display_name")) { if (node.has("display_name")) {
displayName = node.get("display_name").asText(); displayName = node.get("display_name").getAsString();
} }
builder.displayName(displayName); builder.displayName(displayName);
if (node.has("friction")) { if (node.has("friction")) {
builder.friction(node.get("friction").floatValue()); builder.friction(node.get("friction").getAsFloat());
} }
if (node.has("light_emission")) { if (node.has("light_emission")) {
builder.lightEmission(node.get("light_emission").asInt()); builder.lightEmission(node.get("light_emission").getAsInt());
} }
if (node.has("light_dampening")) { if (node.has("light_dampening")) {
builder.lightDampening(node.get("light_dampening").asInt()); builder.lightDampening(node.get("light_dampening").getAsInt());
} }
boolean placeAir = true; boolean placeAir = true;
if (node.has("place_air")) { if (node.has("place_air")) {
placeAir = node.get("place_air").asBoolean(); placeAir = node.get("place_air").getAsBoolean();
} }
builder.placeAir(placeAir); builder.placeAir(placeAir);
if (node.has("transformation")) { if (node.has("transformation")) {
JsonNode transformation = node.get("transformation"); JsonObject transformation = node.getAsJsonObject("transformation");
int rotationX = 0; int rotationX = 0;
int rotationY = 0; int rotationY = 0;
@ -463,22 +471,22 @@ public class MappingsReader_v1 extends MappingsReader {
float transformZ = 0; float transformZ = 0;
if (transformation.has("rotation")) { if (transformation.has("rotation")) {
JsonNode rotation = transformation.get("rotation"); JsonArray rotation = transformation.getAsJsonArray("rotation");
rotationX = rotation.get(0).asInt(); rotationX = rotation.get(0).getAsInt();
rotationY = rotation.get(1).asInt(); rotationY = rotation.get(1).getAsInt();
rotationZ = rotation.get(2).asInt(); rotationZ = rotation.get(2).getAsInt();
} }
if (transformation.has("scale")) { if (transformation.has("scale")) {
JsonNode scale = transformation.get("scale"); JsonArray scale = transformation.getAsJsonArray("scale");
scaleX = scale.get(0).floatValue(); scaleX = scale.get(0).getAsFloat();
scaleY = scale.get(1).floatValue(); scaleY = scale.get(1).getAsFloat();
scaleZ = scale.get(2).floatValue(); scaleZ = scale.get(2).getAsFloat();
} }
if (transformation.has("translation")) { if (transformation.has("translation")) {
JsonNode translation = transformation.get("translation"); JsonArray translation = transformation.getAsJsonArray("translation");
transformX = translation.get(0).floatValue(); transformX = translation.get(0).getAsFloat();
transformY = translation.get(1).floatValue(); transformY = translation.get(1).getAsFloat();
transformZ = translation.get(2).floatValue(); transformZ = translation.get(2).getAsFloat();
} }
builder.transformation(new TransformationComponent(rotationX, rotationY, rotationZ, scaleX, scaleY, scaleZ, transformX, transformY, transformZ)); builder.transformation(new TransformationComponent(rotationX, rotationY, rotationZ, scaleX, scaleY, scaleZ, transformX, transformY, transformZ));
} }
@ -490,12 +498,10 @@ public class MappingsReader_v1 extends MappingsReader {
} }
if (node.has("material_instances")) { if (node.has("material_instances")) {
JsonNode materialInstances = node.get("material_instances"); if (node.get("material_instances") instanceof JsonObject materialInstances) {
if (materialInstances.isObject()) { materialInstances.entrySet().forEach(entry -> {
materialInstances.fields().forEachRemaining(entry -> {
String key = entry.getKey(); String key = entry.getKey();
JsonNode value = entry.getValue(); if (entry.getValue() instanceof JsonObject value) {
if (value.isObject()) {
MaterialInstance materialInstance = createMaterialInstanceComponent(value); MaterialInstance materialInstance = createMaterialInstanceComponent(value);
builder.materialInstance(key, materialInstance); builder.materialInstance(key, materialInstance);
} }
@ -503,16 +509,10 @@ public class MappingsReader_v1 extends MappingsReader {
} }
} }
if (node.has("placement_filter")) { if (node.get("placement_filter") instanceof JsonObject placementFilter) {
JsonNode placementFilter = node.get("placement_filter"); if (placementFilter.get("conditions") instanceof JsonArray conditions) {
if (placementFilter.isObject()) { List<PlacementConditions> filter = createPlacementFilterComponent(conditions);
if (placementFilter.has("conditions")) { builder.placementFilter(filter);
JsonNode conditions = placementFilter.get("conditions");
if (conditions.isArray()) {
List<PlacementConditions> filter = createPlacementFilterComponent(conditions);
builder.placementFilter(filter);
}
}
} }
} }
@ -521,9 +521,9 @@ public class MappingsReader_v1 extends MappingsReader {
// Ideally we could programmatically extract the tags here https://wiki.bedrock.dev/blocks/block-tags.html // Ideally we could programmatically extract the tags here https://wiki.bedrock.dev/blocks/block-tags.html
// This would let us automatically apply the correct vanilla tags to blocks // This would let us automatically apply the correct vanilla tags to blocks
// However, its worth noting that vanilla tools do not currently honor these tags anyway // However, its worth noting that vanilla tools do not currently honor these tags anyway
if (node.get("tags") instanceof ArrayNode tags) { if (node.get("tags") instanceof JsonArray tags) {
Set<String> tagsSet = new ObjectOpenHashSet<>(); Set<String> tagsSet = new ObjectOpenHashSet<>();
tags.forEach(tag -> tagsSet.add(tag.asText())); tags.forEach(tag -> tagsSet.add(tag.getAsString()));
builder.tags(tagsSet); builder.tags(tagsSet);
} }
@ -613,21 +613,21 @@ public class MappingsReader_v1 extends MappingsReader {
/** /**
* Creates a {@link BoxComponent} from a JSON Node * Creates a {@link BoxComponent} from a JSON Node
* *
* @param node the JSON node * @param element the JSON node
* @return the {@link BoxComponent} * @return the {@link BoxComponent}
*/ */
private @Nullable BoxComponent createBoxComponent(JsonNode node) { private @Nullable BoxComponent createBoxComponent(JsonElement element) {
if (node != null && node.isObject()) { if (element instanceof JsonObject node) {
if (node.has("origin") && node.has("size")) { if (node.has("origin") && node.has("size")) {
JsonNode origin = node.get("origin"); JsonArray origin = node.getAsJsonArray("origin");
float originX = origin.get(0).floatValue(); float originX = origin.get(0).getAsFloat();
float originY = origin.get(1).floatValue(); float originY = origin.get(1).getAsFloat();
float originZ = origin.get(2).floatValue(); float originZ = origin.get(2).getAsFloat();
JsonNode size = node.get("size"); JsonArray size = node.getAsJsonArray("size");
float sizeX = size.get(0).floatValue(); float sizeX = size.get(0).getAsFloat();
float sizeY = size.get(1).floatValue(); float sizeY = size.get(1).getAsFloat();
float sizeZ = size.get(2).floatValue(); float sizeZ = size.get(2).getAsFloat();
return new BoxComponent(originX, originY, originZ, sizeX, sizeY, sizeZ); return new BoxComponent(originX, originY, originZ, sizeX, sizeY, sizeZ);
} }
@ -642,26 +642,26 @@ public class MappingsReader_v1 extends MappingsReader {
* @param node the material instance node * @param node the material instance node
* @return the {@link MaterialInstance} * @return the {@link MaterialInstance}
*/ */
private MaterialInstance createMaterialInstanceComponent(JsonNode node) { private MaterialInstance createMaterialInstanceComponent(JsonObject node) {
// Set default values, and use what the user provides if they have provided something // Set default values, and use what the user provides if they have provided something
String texture = null; String texture = null;
if (node.has("texture")) { if (node.has("texture")) {
texture = node.get("texture").asText(); texture = node.get("texture").getAsString();
} }
String renderMethod = "opaque"; String renderMethod = "opaque";
if (node.has("render_method")) { if (node.has("render_method")) {
renderMethod = node.get("render_method").asText(); renderMethod = node.get("render_method").getAsString();
} }
boolean faceDimming = true; boolean faceDimming = true;
if (node.has("face_dimming")) { if (node.has("face_dimming")) {
faceDimming = node.get("face_dimming").asBoolean(); faceDimming = node.get("face_dimming").getAsBoolean();
} }
boolean ambientOcclusion = true; boolean ambientOcclusion = true;
if (node.has("ambient_occlusion")) { if (node.has("ambient_occlusion")) {
ambientOcclusion = node.get("ambient_occlusion").asBoolean(); ambientOcclusion = node.get("ambient_occlusion").getAsBoolean();
} }
return new GeyserMaterialInstance.Builder() return new GeyserMaterialInstance.Builder()
@ -678,32 +678,33 @@ public class MappingsReader_v1 extends MappingsReader {
* @param node the conditions node * @param node the conditions node
* @return the list of {@link PlacementConditions} * @return the list of {@link PlacementConditions}
*/ */
private List<PlacementConditions> createPlacementFilterComponent(JsonNode node) { private List<PlacementConditions> createPlacementFilterComponent(JsonArray node) {
List<PlacementConditions> conditions = new ArrayList<>(); List<PlacementConditions> conditions = new ArrayList<>();
// The structure of the placement filter component is the most complex of the current components // The structure of the placement filter component is the most complex of the current components
// Each condition effectively separated into two arrays: one of allowed faces, and one of blocks/block Molang queries // Each condition effectively separated into two arrays: one of allowed faces, and one of blocks/block Molang queries
node.forEach(condition -> { node.forEach(json -> {
if (!(json instanceof JsonObject condition)) {
return;
}
Set<Face> faces = EnumSet.noneOf(Face.class); Set<Face> faces = EnumSet.noneOf(Face.class);
if (condition.has("allowed_faces")) { if (condition.has("allowed_faces")) {
JsonNode allowedFaces = condition.get("allowed_faces"); if (condition.get("allowed_faces") instanceof JsonArray allowedFaces) {
if (allowedFaces.isArray()) { allowedFaces.forEach(face -> faces.add(Face.valueOf(face.getAsString().toUpperCase())));
allowedFaces.forEach(face -> faces.add(Face.valueOf(face.asText().toUpperCase())));
} }
} }
LinkedHashMap<String, BlockFilterType> blockFilters = new LinkedHashMap<>(); LinkedHashMap<String, BlockFilterType> blockFilters = new LinkedHashMap<>();
if (condition.has("block_filter")) { if (condition.has("block_filter")) {
JsonNode blockFilter = condition.get("block_filter"); if (condition.get("block_filter") instanceof JsonArray blockFilter) {
if (blockFilter.isArray()) {
blockFilter.forEach(filter -> { blockFilter.forEach(filter -> {
if (filter.isObject()) { if (filter instanceof JsonObject jsonObject) {
if (filter.has("tags")) { if (jsonObject.has("tags")) {
JsonNode tags = filter.get("tags"); JsonElement tags = jsonObject.get("tags");
blockFilters.put(tags.asText(), BlockFilterType.TAG); blockFilters.put(tags.getAsString(), BlockFilterType.TAG);
} }
} else if (filter.isTextual()) { } else if (filter instanceof JsonPrimitive primitive && primitive.isString()) {
blockFilters.put(filter.asText(), BlockFilterType.BLOCK); blockFilters.put(filter.getAsString(), BlockFilterType.BLOCK);
} }
}); });
} }

Datei anzeigen

@ -25,17 +25,26 @@
package org.geysermc.geyser.registry.populator; package org.geysermc.geyser.registry.populator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Interner; import com.google.common.collect.Interner;
import com.google.common.collect.Interners; import com.google.common.collect.Interners;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.*; import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import org.cloudburstmc.nbt.*; import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.cloudburstmc.nbt.NBTInputStream;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.nbt.NbtUtils;
import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671; import org.cloudburstmc.protocol.bedrock.codec.v671.Bedrock_v671;
import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685; import org.cloudburstmc.protocol.bedrock.codec.v685.Bedrock_v685;
import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData; import org.cloudburstmc.protocol.bedrock.data.BlockPropertyData;
@ -56,12 +65,21 @@ import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.BlockMappings;
import org.geysermc.geyser.registry.type.GeyserBedrockBlock; import org.geysermc.geyser.registry.type.GeyserBedrockBlock;
import org.geysermc.geyser.util.BlockUtils; import org.geysermc.geyser.util.BlockUtils;
import org.geysermc.geyser.util.JsonUtils;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.*; import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@ -461,23 +479,23 @@ public final class BlockRegistryPopulator {
BLOCKS_NBT = blocksNbt; BLOCKS_NBT = blocksNbt;
JsonNode blockInteractionsJson; JsonObject blockInteractionsJson;
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/interactions.json")) { try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResourceOrThrow("mappings/interactions.json")) {
blockInteractionsJson = GeyserImpl.JSON_MAPPER.readTree(stream); blockInteractionsJson = JsonUtils.fromJson(stream);
} catch (Exception e) { } catch (Exception e) {
throw new AssertionError("Unable to load Java block interaction mappings", e); throw new AssertionError("Unable to load Java block interaction mappings", e);
} }
BlockRegistries.INTERACTIVE.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("always_consumes"))); BlockRegistries.INTERACTIVE.set(toBlockStateSet(blockInteractionsJson.getAsJsonArray("always_consumes")));
BlockRegistries.INTERACTIVE_MAY_BUILD.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("requires_may_build"))); BlockRegistries.INTERACTIVE_MAY_BUILD.set(toBlockStateSet(blockInteractionsJson.getAsJsonArray("requires_may_build")));
BlockRegistries.BLOCK_STATES.freeze(); BlockRegistries.BLOCK_STATES.freeze();
} }
private static BitSet toBlockStateSet(ArrayNode node) { private static BitSet toBlockStateSet(JsonArray node) {
BitSet blockStateSet = new BitSet(node.size()); BitSet blockStateSet = new BitSet(node.size());
for (JsonNode javaIdentifier : node) { for (JsonElement javaIdentifier : node) {
blockStateSet.set(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt(javaIdentifier.textValue())); blockStateSet.set(BlockRegistries.JAVA_IDENTIFIER_TO_ID.get().getInt(javaIdentifier.getAsString()));
} }
return blockStateSet; return blockStateSet;
} }

Datei anzeigen

@ -25,7 +25,9 @@
package org.geysermc.geyser.registry.populator; package org.geysermc.geyser.registry.populator;
import com.fasterxml.jackson.databind.JsonNode; import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
@ -37,6 +39,7 @@ import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.BlockMappings;
import org.geysermc.geyser.registry.type.GeyserBedrockBlock; import org.geysermc.geyser.registry.type.GeyserBedrockBlock;
import org.geysermc.geyser.util.JsonUtils;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
@ -61,16 +64,16 @@ public class CreativeItemRegistryPopulator {
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
// Load creative items // Load creative items
JsonNode creativeItemEntries; JsonArray creativeItemEntries;
try (InputStream stream = bootstrap.getResourceOrThrow(String.format("bedrock/creative_items.%s.json", palette.version()))) { try (InputStream stream = bootstrap.getResourceOrThrow(String.format("bedrock/creative_items.%s.json", palette.version()))) {
creativeItemEntries = GeyserImpl.JSON_MAPPER.readTree(stream).get("items"); creativeItemEntries = JsonUtils.fromJson(stream).getAsJsonArray("items");
} catch (Exception e) { } catch (Exception e) {
throw new AssertionError("Unable to load creative items", e); throw new AssertionError("Unable to load creative items", e);
} }
BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(palette.protocolVersion()); BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(palette.protocolVersion());
for (JsonNode itemNode : creativeItemEntries) { for (JsonElement itemNode : creativeItemEntries) {
ItemData.Builder itemBuilder = createItemData(itemNode, blockMappings, definitions); ItemData.Builder itemBuilder = createItemData((JsonObject) itemNode, blockMappings, definitions);
if (itemBuilder == null) { if (itemBuilder == null) {
continue; continue;
} }
@ -79,41 +82,41 @@ public class CreativeItemRegistryPopulator {
} }
} }
private static ItemData.@Nullable Builder createItemData(JsonNode itemNode, BlockMappings blockMappings, Map<String, ItemDefinition> definitions) { private static ItemData.@Nullable Builder createItemData(JsonObject itemNode, BlockMappings blockMappings, Map<String, ItemDefinition> definitions) {
int count = 1; int count = 1;
int damage = 0; int damage = 0;
int bedrockBlockRuntimeId; int bedrockBlockRuntimeId;
NbtMap tag = null; NbtMap tag = null;
String identifier = itemNode.get("id").textValue(); String identifier = itemNode.get("id").getAsString();
for (BiPredicate<String, Integer> predicate : JAVA_ONLY_ITEM_FILTER) { for (BiPredicate<String, Integer> predicate : JAVA_ONLY_ITEM_FILTER) {
if (predicate.test(identifier, damage)) { if (predicate.test(identifier, damage)) {
return null; return null;
} }
} }
JsonNode damageNode = itemNode.get("damage"); JsonElement damageNode = itemNode.get("damage");
if (damageNode != null) { if (damageNode != null) {
damage = damageNode.asInt(); damage = damageNode.getAsInt();
} }
JsonNode countNode = itemNode.get("count"); JsonElement countNode = itemNode.get("count");
if (countNode != null) { if (countNode != null) {
count = countNode.asInt(); count = countNode.getAsInt();
} }
GeyserBedrockBlock blockDefinition = null; GeyserBedrockBlock blockDefinition = null;
JsonNode blockRuntimeIdNode = itemNode.get("blockRuntimeId"); JsonElement blockRuntimeIdNode = itemNode.get("blockRuntimeId");
JsonNode blockStateNode; JsonElement blockStateNode;
if (blockRuntimeIdNode != null) { if (blockRuntimeIdNode != null) {
bedrockBlockRuntimeId = blockRuntimeIdNode.asInt(); bedrockBlockRuntimeId = blockRuntimeIdNode.getAsInt();
if (bedrockBlockRuntimeId == 0 && !identifier.equals("minecraft:blue_candle")) { // FIXME if (bedrockBlockRuntimeId == 0 && !identifier.equals("minecraft:blue_candle")) { // FIXME
bedrockBlockRuntimeId = -1; bedrockBlockRuntimeId = -1;
} }
blockDefinition = bedrockBlockRuntimeId == -1 ? null : blockMappings.getDefinition(bedrockBlockRuntimeId); blockDefinition = bedrockBlockRuntimeId == -1 ? null : blockMappings.getDefinition(bedrockBlockRuntimeId);
} else if ((blockStateNode = itemNode.get("block_state_b64")) != null) { } else if ((blockStateNode = itemNode.get("block_state_b64")) != null) {
byte[] bytes = Base64.getDecoder().decode(blockStateNode.asText()); byte[] bytes = Base64.getDecoder().decode(blockStateNode.getAsString());
ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
try { try {
NbtMap stateTag = (NbtMap) NbtUtils.createReaderLE(bais).readTag(); NbtMap stateTag = (NbtMap) NbtUtils.createReaderLE(bais).readTag();
@ -132,9 +135,9 @@ public class CreativeItemRegistryPopulator {
} }
} }
JsonNode nbtNode = itemNode.get("nbt_b64"); JsonElement nbtNode = itemNode.get("nbt_b64");
if (nbtNode != null) { if (nbtNode != null) {
byte[] bytes = Base64.getDecoder().decode(nbtNode.asText()); byte[] bytes = Base64.getDecoder().decode(nbtNode.getAsString());
ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
try { try {
tag = (NbtMap) NbtUtils.createReaderLE(bais).readTag(); tag = (NbtMap) NbtUtils.createReaderLE(bais).readTag();

Datei anzeigen

@ -25,15 +25,21 @@
package org.geysermc.geyser.registry.populator; package org.geysermc.geyser.registry.populator;
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder; import com.google.common.collect.MultimapBuilder;
import com.google.gson.reflect.TypeToken;
import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.*; import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
@ -61,10 +67,24 @@ import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.item.type.Item; import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.*; import org.geysermc.geyser.registry.type.BlockMappings;
import org.geysermc.geyser.registry.type.GeyserBedrockBlock;
import org.geysermc.geyser.registry.type.GeyserMappingItem;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.registry.type.NonVanillaItemRegistration;
import org.geysermc.geyser.registry.type.PaletteItem;
import org.geysermc.geyser.util.JsonUtils;
import java.io.InputStream; import java.io.InputStream;
import java.util.*; import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
/** /**
@ -92,12 +112,12 @@ public class ItemRegistryPopulator {
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
TypeReference<Map<String, GeyserMappingItem>> mappingItemsType = new TypeReference<>() { }; Type mappingItemsType = new TypeToken<Map<String, GeyserMappingItem>>() { }.getType();
Map<String, GeyserMappingItem> items; Map<String, GeyserMappingItem> items;
try (InputStream stream = bootstrap.getResourceOrThrow("mappings/items.json")) { try (InputStream stream = bootstrap.getResourceOrThrow("mappings/items.json")) {
// Load item mappings from Java Edition to Bedrock Edition // Load item mappings from Java Edition to Bedrock Edition
items = GeyserImpl.JSON_MAPPER.readValue(stream, mappingItemsType); items = JsonUtils.fromJson(stream, mappingItemsType);
} catch (Exception e) { } catch (Exception e) {
throw new AssertionError("Unable to load Java runtime item IDs", e); throw new AssertionError("Unable to load Java runtime item IDs", e);
} }
@ -126,11 +146,11 @@ public class ItemRegistryPopulator {
/* Load item palette */ /* Load item palette */
for (PaletteVersion palette : paletteVersions) { for (PaletteVersion palette : paletteVersions) {
TypeReference<List<PaletteItem>> paletteEntriesType = new TypeReference<>() {}; Type paletteEntriesType = new TypeToken<List<PaletteItem>>() { }.getType();
List<PaletteItem> itemEntries; List<PaletteItem> itemEntries;
try (InputStream stream = bootstrap.getResourceOrThrow(String.format("bedrock/runtime_item_states.%s.json", palette.version()))) { try (InputStream stream = bootstrap.getResourceOrThrow(String.format("bedrock/runtime_item_states.%s.json", palette.version()))) {
itemEntries = GeyserImpl.JSON_MAPPER.readValue(stream, paletteEntriesType); itemEntries = JsonUtils.fromJson(stream, paletteEntriesType);
} catch (Exception e) { } catch (Exception e) {
throw new AssertionError("Unable to load Bedrock runtime item IDs", e); throw new AssertionError("Unable to load Bedrock runtime item IDs", e);
} }

Datei anzeigen

@ -25,7 +25,7 @@
package org.geysermc.geyser.registry.type; package org.geysermc.geyser.registry.type;
import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
@ -43,14 +43,14 @@ import lombok.With;
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class GeyserMappingItem { public class GeyserMappingItem {
@JsonProperty("bedrock_identifier") String bedrockIdentifier; @SerializedName("bedrock_identifier") String bedrockIdentifier;
@JsonProperty("bedrock_data") int bedrockData; @SerializedName("bedrock_data") int bedrockData;
Integer firstBlockRuntimeId; Integer firstBlockRuntimeId;
Integer lastBlockRuntimeId; Integer lastBlockRuntimeId;
@JsonProperty("tool_type") String toolType; @SerializedName("tool_type") String toolType;
@JsonProperty("tool_tier") String toolTier; @SerializedName("tool_tier") String toolTier;
@JsonProperty("armor_type") String armorType; @SerializedName("armor_type") String armorType;
@JsonProperty("protection_value") int protectionValue; @SerializedName("protection_value") int protectionValue;
@JsonProperty("is_edible") boolean edible = false; @SerializedName("is_edible") boolean edible = false;
@JsonProperty("is_entity_placer") boolean entityPlacer = false; @SerializedName("is_entity_placer") boolean entityPlacer = false;
} }

Datei anzeigen

@ -282,6 +282,7 @@ public class SkinManager {
} }
public static @Nullable GameProfileData loadFromJson(String encodedJson) throws IOException, IllegalArgumentException { public static @Nullable GameProfileData loadFromJson(String encodedJson) throws IOException, IllegalArgumentException {
// TODO use GameProfile method.
JsonNode skinObject; JsonNode skinObject;
try { try {
skinObject = GeyserImpl.JSON_MAPPER.readTree(new String(Base64.getDecoder().decode(encodedJson), StandardCharsets.UTF_8)); skinObject = GeyserImpl.JSON_MAPPER.readTree(new String(Base64.getDecoder().decode(encodedJson), StandardCharsets.UTF_8));
@ -334,4 +335,4 @@ public class SkinManager {
private static final String DEFAULT_FLOODGATE_STEVE = "https://textures.minecraft.net/texture/31f477eb1a7beee631c2ca64d06f8f68fa93a3386d04452ab27f43acdf1b60cb"; private static final String DEFAULT_FLOODGATE_STEVE = "https://textures.minecraft.net/texture/31f477eb1a7beee631c2ca64d06f8f68fa93a3386d04452ab27f43acdf1b60cb";
} }
} }

Datei anzeigen

@ -25,11 +25,13 @@
package org.geysermc.geyser.text; package org.geysermc.geyser.text;
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.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.util.AssetUtils; import org.geysermc.geyser.util.AssetUtils;
import org.geysermc.geyser.util.FileUtils; import org.geysermc.geyser.util.FileUtils;
import org.geysermc.geyser.util.JsonUtils;
import org.geysermc.geyser.util.WebUtils; import org.geysermc.geyser.util.WebUtils;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -39,7 +41,6 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -189,14 +190,12 @@ public class MinecraftLocale {
// Read the localefile // Read the localefile
try (InputStream localeStream = Files.newInputStream(localeFile, StandardOpenOption.READ)) { try (InputStream localeStream = Files.newInputStream(localeFile, StandardOpenOption.READ)) {
// Parse the file as json // Parse the file as json
JsonNode localeObj = GeyserImpl.JSON_MAPPER.readTree(localeStream); JsonObject localeObj = JsonUtils.fromJson(localeStream);
// Parse all the locale fields // Parse all the locale fields
Iterator<Map.Entry<String, JsonNode>> localeIterator = localeObj.fields();
Map<String, String> langMap = new HashMap<>(); Map<String, String> langMap = new HashMap<>();
while (localeIterator.hasNext()) { for (Map.Entry<String, JsonElement> entry : localeObj.entrySet()) {
Map.Entry<String, JsonNode> entry = localeIterator.next(); langMap.put(entry.getKey(), entry.getValue().getAsString());
langMap.put(entry.getKey(), entry.getValue().asText());
} }
return langMap; return langMap;
} catch (FileNotFoundException e){ } catch (FileNotFoundException e){
@ -266,4 +265,4 @@ public class MinecraftLocale {
} }
return result.toString(); return result.toString();
} }
} }

Datei anzeigen

@ -25,18 +25,28 @@
package org.geysermc.geyser.util; package org.geysermc.geyser.util;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.google.gson.JsonElement;
import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.JsonObject;
import com.fasterxml.jackson.databind.JsonNode; import com.google.gson.JsonParser;
import com.google.gson.annotations.SerializedName;
import lombok.Getter; import lombok.Getter;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.GeyserLocale;
import java.io.*; import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.ArrayDeque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
@ -83,7 +93,7 @@ public final class AssetUtils {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
try { try {
// Get the version manifest from Mojang // Get the version manifest from Mojang
VersionManifest versionManifest = GeyserImpl.JSON_MAPPER.readValue( VersionManifest versionManifest = GeyserImpl.GSON.fromJson(
WebUtils.getBody("https://launchermeta.mojang.com/mc/game/version_manifest.json"), VersionManifest.class); WebUtils.getBody("https://launchermeta.mojang.com/mc/game/version_manifest.json"), VersionManifest.class);
// Get the url for the latest version of the games manifest // Get the url for the latest version of the games manifest
@ -101,26 +111,24 @@ public final class AssetUtils {
} }
// Get the individual version manifest // Get the individual version manifest
VersionInfo versionInfo = GeyserImpl.JSON_MAPPER.readValue(WebUtils.getBody(latestInfoURL), VersionInfo.class); VersionInfo versionInfo = GeyserImpl.GSON.fromJson(WebUtils.getBody(latestInfoURL), VersionInfo.class);
// Get the client jar for use when downloading the en_us locale // Get the client jar for use when downloading the en_us locale
GeyserImpl.getInstance().getLogger().debug(GeyserImpl.JSON_MAPPER.writeValueAsString(versionInfo.getDownloads())); GeyserImpl.getInstance().getLogger().debug(versionInfo.getDownloads()); // Was previously a Jackson call for writeValueToString
CLIENT_JAR_INFO = versionInfo.getDownloads().get("client"); CLIENT_JAR_INFO = versionInfo.getDownloads().get("client");
GeyserImpl.getInstance().getLogger().debug(GeyserImpl.JSON_MAPPER.writeValueAsString(CLIENT_JAR_INFO)); GeyserImpl.getInstance().getLogger().debug(CLIENT_JAR_INFO); // Was previously a Jackson call for writeValueToString
// Get the assets list // Get the assets list
JsonNode assets = GeyserImpl.JSON_MAPPER.readTree(WebUtils.getBody(versionInfo.getAssetIndex().getUrl())).get("objects"); JsonObject assets = ((JsonObject) new JsonParser().parse(WebUtils.getBody(versionInfo.getAssetIndex().getUrl()))).getAsJsonObject("objects");
// Put each asset into an array for use later // Put each asset into an array for use later
Iterator<Map.Entry<String, JsonNode>> assetIterator = assets.fields(); for (Map.Entry<String, JsonElement> entry : assets.entrySet()) {
while (assetIterator.hasNext()) {
Map.Entry<String, JsonNode> entry = assetIterator.next();
if (!entry.getKey().startsWith("minecraft/lang/")) { if (!entry.getKey().startsWith("minecraft/lang/")) {
// No need to cache non-language assets as we don't use them // No need to cache non-language assets as we don't use them
continue; continue;
} }
Asset asset = GeyserImpl.JSON_MAPPER.treeToValue(entry.getValue(), Asset.class); Asset asset = GeyserImpl.GSON.fromJson(entry.getValue(), Asset.class);
ASSET_MAP.put(entry.getKey(), asset); ASSET_MAP.put(entry.getKey(), asset);
} }
@ -221,106 +229,99 @@ public final class AssetUtils {
/* Classes that map to JSON files served by Mojang */ /* Classes that map to JSON files served by Mojang */
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Getter
static class VersionManifest { static class VersionManifest {
@JsonProperty("latest") @SerializedName("latest")
private LatestVersion latestVersion; private LatestVersion latestVersion;
@JsonProperty("versions") @SerializedName("versions")
private List<Version> versions; private List<Version> versions;
} }
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Getter
static class LatestVersion { static class LatestVersion {
@JsonProperty("release") @SerializedName("release")
private String release; private String release;
@JsonProperty("snapshot") @SerializedName("snapshot")
private String snapshot; private String snapshot;
} }
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Getter
static class Version { static class Version {
@JsonProperty("id") @SerializedName("id")
private String id; private String id;
@JsonProperty("type") @SerializedName("type")
private String type; private String type;
@JsonProperty("url") @SerializedName("url")
private String url; private String url;
@JsonProperty("time") @SerializedName("time")
private String time; private String time;
@JsonProperty("releaseTime") @SerializedName("releaseTime")
private String releaseTime; private String releaseTime;
} }
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Getter
static class VersionInfo { static class VersionInfo {
@JsonProperty("id") @SerializedName("id")
private String id; private String id;
@JsonProperty("type") @SerializedName("type")
private String type; private String type;
@JsonProperty("time") @SerializedName("time")
private String time; private String time;
@JsonProperty("releaseTime") @SerializedName("releaseTime")
private String releaseTime; private String releaseTime;
@JsonProperty("assetIndex") @SerializedName("assetIndex")
private AssetIndex assetIndex; private AssetIndex assetIndex;
@JsonProperty("downloads") @SerializedName("downloads")
private Map<String, VersionDownload> downloads; private Map<String, VersionDownload> downloads;
} }
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Getter
static class VersionDownload { static class VersionDownload {
@JsonProperty("sha1") @SerializedName("sha1")
private String sha1; private String sha1;
@JsonProperty("size") @SerializedName("size")
private int size; private int size;
@JsonProperty("url") @SerializedName("url")
private String url; private String url;
} }
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Getter
static class AssetIndex { static class AssetIndex {
@JsonProperty("id") @SerializedName("id")
private String id; private String id;
@JsonProperty("sha1") @SerializedName("sha1")
private String sha1; private String sha1;
@JsonProperty("size") @SerializedName("size")
private int size; private int size;
@JsonProperty("totalSize") @SerializedName("totalSize")
private int totalSize; private int totalSize;
@JsonProperty("url") @SerializedName("url")
private String url; private String url;
} }
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter @Getter
public static class Asset { public static class Asset {
@JsonProperty("hash") @SerializedName("hash")
private String hash; private String hash;
@JsonProperty("size") @SerializedName("size")
private int size; private int size;
} }

Datei anzeigen

@ -30,6 +30,7 @@ import com.fasterxml.jackson.annotation.Nulls;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.google.gson.Gson;
import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
@ -63,9 +64,13 @@ public class FileUtils {
return objectMapper.readValue(src, valueType); return objectMapper.readValue(src, valueType);
} }
public static <T> T loadJson(InputStream src, Class<T> valueType) throws IOException { 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 // Read specifically with UTF-8 to allow any non-UTF-encoded JSON to read
return GeyserImpl.JSON_MAPPER.readValue(new InputStreamReader(src, StandardCharsets.UTF_8), valueType); return gson.fromJson(new InputStreamReader(src, StandardCharsets.UTF_8), valueType);
} }
/** /**

Datei anzeigen

@ -0,0 +1,53 @@
/*
* Copyright (c) 2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.util;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.geysermc.geyser.GeyserImpl;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
public final class JsonUtils {
public static <T> T fromJson(byte[] bytes, Class<T> type) {
return GeyserImpl.GSON.fromJson(new String(bytes, StandardCharsets.UTF_8), type);
}
public static JsonObject fromJson(InputStream stream) {
return (JsonObject) new JsonParser().parse(new InputStreamReader(stream));
}
public static <T> T fromJson(InputStream stream, Type type) {
return GeyserImpl.GSON.fromJson(new InputStreamReader(stream), type);
}
private JsonUtils() {
}
}