diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index b4b93dcac..19b655c29 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,7 +1,7 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
-patreon: GeyserMC
+patreon: #GeyserMC # Disabled currently
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
diff --git a/Jenkinsfile b/Jenkinsfile
index 1a93391db..7dfdaf304 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -24,6 +24,7 @@ pipeline {
when {
branch "master"
}
+
steps {
sh 'mvn javadoc:jar source:jar deploy -DskipTests'
}
diff --git a/README.md b/README.md
index f7201bb08..ab1ff24ac 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have now joined us here!
-### Currently supporting Minecraft Bedrock v1.16.x and Minecraft Java v1.16.3.
+### Currently supporting Minecraft Bedrock v1.16.100 and Minecraft Java v1.16.4.
## Setting Up
Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set up Geyser.
diff --git a/bootstrap/bungeecord/pom.xml b/bootstrap/bungeecord/pom.xml
index 44b28e931..124967b0a 100644
--- a/bootstrap/bungeecord/pom.xml
+++ b/bootstrap/bungeecord/pom.xml
@@ -6,15 +6,15 @@
org.geysermc
bootstrap-parent
- 1.1.0
- ../
+ 1.2.0-SNAPSHOT
bootstrap-bungeecord
+
org.geysermc
connector
- 1.1.0
+ 1.2.0-SNAPSHOT
compile
diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java
index e06640896..61bec3b37 100644
--- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java
+++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java
@@ -27,10 +27,10 @@ package org.geysermc.platform.bungeecord;
import net.md_5.bungee.api.config.ListenerInfo;
import net.md_5.bungee.api.plugin.Plugin;
+import org.geysermc.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager;
-import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml
index d9bac67d1..a5ad53cb5 100644
--- a/bootstrap/pom.xml
+++ b/bootstrap/pom.xml
@@ -6,12 +6,11 @@
org.geysermc
geyser-parent
- parent
- ../
+ 1.2.0-SNAPSHOT
bootstrap-parent
- 1.1.0
pom
+
spigot-public
diff --git a/bootstrap/spigot/pom.xml b/bootstrap/spigot/pom.xml
index d4dc33260..f3b9cf88d 100644
--- a/bootstrap/spigot/pom.xml
+++ b/bootstrap/spigot/pom.xml
@@ -6,15 +6,15 @@
org.geysermc
bootstrap-parent
- 1.1.0
- ../
+ 1.2.0-SNAPSHOT
bootstrap-spigot
+
org.geysermc
connector
- 1.1.0
+ 1.2.0-SNAPSHOT
compile
@@ -26,7 +26,7 @@
us.myles
viaversion
- 3.1.1
+ 3.2.0
provided
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java
index 7aeb6edc5..9d90e68c7 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java
@@ -27,10 +27,10 @@ package org.geysermc.platform.spigot;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
+import org.geysermc.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager;
-import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.network.translators.world.WorldManager;
@@ -43,6 +43,7 @@ import org.geysermc.platform.spigot.command.GeyserSpigotCommandManager;
import org.geysermc.platform.spigot.command.SpigotCommandSender;
import org.geysermc.platform.spigot.world.GeyserSpigotBlockPlaceListener;
import org.geysermc.platform.spigot.world.GeyserSpigotWorldManager;
+import us.myles.ViaVersion.api.Via;
import java.io.File;
import java.io.IOException;
@@ -121,6 +122,13 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
this.geyserCommandManager = new GeyserSpigotCommandManager(this, connector);
boolean isViaVersion = (Bukkit.getPluginManager().getPlugin("ViaVersion") != null);
+ if (isViaVersion) {
+ if (!isCompatible(Via.getAPI().getVersion().replace("-SNAPSHOT", ""), "3.2.0")) {
+ geyserLogger.warning(LanguageUtils.getLocaleStringLog("geyser.bootstrap.viaversion.too_old",
+ "https://ci.viaversion.com/job/ViaVersion/"));
+ isViaVersion = false;
+ }
+ }
// Used to determine if Block.getBlockData() is present.
boolean isLegacy = !isCompatible(Bukkit.getServer().getVersion(), "1.13.0");
if (isLegacy)
diff --git a/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotWorldManager.java
index 8a92526f1..3493fc25a 100644
--- a/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotWorldManager.java
+++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotWorldManager.java
@@ -26,6 +26,7 @@
package org.geysermc.platform.spigot.world;
import com.fasterxml.jackson.databind.JsonNode;
+import com.github.steveice10.mc.protocol.MinecraftConstants;
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
@@ -41,14 +42,32 @@ import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.utils.FileUtils;
import org.geysermc.connector.utils.GameRule;
import org.geysermc.connector.utils.LanguageUtils;
-import us.myles.ViaVersion.protocols.protocol1_13_1to1_13.Protocol1_13_1To1_13;
-import us.myles.ViaVersion.protocols.protocol1_16_2to1_16_1.data.MappingData;
+import us.myles.ViaVersion.api.Pair;
+import us.myles.ViaVersion.api.Via;
+import us.myles.ViaVersion.api.data.MappingData;
+import us.myles.ViaVersion.api.minecraft.Position;
+import us.myles.ViaVersion.api.protocol.Protocol;
+import us.myles.ViaVersion.api.protocol.ProtocolRegistry;
+import us.myles.ViaVersion.api.protocol.ProtocolVersion;
+import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
+import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.storage.BlockStorage;
import java.io.InputStream;
+import java.util.List;
public class GeyserSpigotWorldManager extends GeyserWorldManager {
+ /**
+ * The current client protocol version for ViaVersion usage.
+ */
+ private static final int CLIENT_PROTOCOL_VERSION = MinecraftConstants.PROTOCOL_VERSION;
+ /**
+ * Whether the server is pre-1.13.
+ */
private final boolean isLegacy;
+ /**
+ * Whether the server is pre-1.16 and therefore does not support 3D biomes on an API level guaranteed.
+ */
private final boolean use3dBiomes;
/**
* You need ViaVersion to connect to an older server with Geyser.
@@ -83,8 +102,9 @@ public class GeyserSpigotWorldManager extends GeyserWorldManager {
}
// Only load in the biomes that are present in this version of Minecraft
for (Biome enumBiome : Biome.values()) {
- if (biomes.has(enumBiome.toString())) {
- biomeToIdMap.put(enumBiome.ordinal(), biomes.get(enumBiome.toString()).intValue());
+ JsonNode biome = biomes.get(enumBiome.toString());
+ if (biome != null) {
+ biomeToIdMap.put(enumBiome.ordinal(), biome.intValue());
} else {
GeyserConnector.getInstance().getLogger().debug("No biome mapping found for " + enumBiome.toString() +
", defaulting to 0");
@@ -99,7 +119,7 @@ public class GeyserSpigotWorldManager extends GeyserWorldManager {
if ((this.isLegacy && !this.isViaVersion)
|| session.getPlayerEntity() == null
|| (bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
- return BlockTranslator.AIR;
+ return BlockTranslator.JAVA_AIR_ID;
}
World world = bukkitPlayer.getWorld();
if (isLegacy) {
@@ -111,28 +131,38 @@ public class GeyserSpigotWorldManager extends GeyserWorldManager {
public static int getLegacyBlock(GeyserSession session, int x, int y, int z, boolean isViaVersion) {
if (isViaVersion) {
- return getLegacyBlock(Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld(), x, y, z, true);
+ Player bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername());
+ // Get block entity storage
+ BlockStorage storage = Via.getManager().getConnection(bukkitPlayer.getUniqueId()).get(BlockStorage.class);
+ return getLegacyBlock(storage, bukkitPlayer.getWorld(), x, y, z);
} else {
- return BlockTranslator.AIR;
+ return BlockTranslator.JAVA_AIR_ID;
}
}
@SuppressWarnings("deprecation")
- public static int getLegacyBlock(World world, int x, int y, int z, boolean isViaVersion) {
- if (isViaVersion) {
- Block block = world.getBlockAt(x, y, z);
- // Black magic that gets the old block state ID
- int oldBlockId = (block.getType().getId() << 4) | (block.getData() & 0xF);
- // Convert block state from old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 -> 1.16 -> 1.16.2
- int thirteenBlockId = us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.MappingData.blockMappings.getNewId(oldBlockId);
- int thirteenPointOneBlockId = Protocol1_13_1To1_13.getNewBlockStateId(thirteenBlockId);
- int fourteenBlockId = us.myles.ViaVersion.protocols.protocol1_14to1_13_2.data.MappingData.blockStateMappings.getNewId(thirteenPointOneBlockId);
- int fifteenBlockId = us.myles.ViaVersion.protocols.protocol1_15to1_14_4.data.MappingData.blockStateMappings.getNewId(fourteenBlockId);
- int sixteenBlockId = us.myles.ViaVersion.protocols.protocol1_16to1_15_2.data.MappingData.blockStateMappings.getNewId(fifteenBlockId);
- return MappingData.blockStateMappings.getNewId(sixteenBlockId);
- } else {
- return BlockTranslator.AIR;
+ public static int getLegacyBlock(BlockStorage storage, World world, int x, int y, int z) {
+ Block block = world.getBlockAt(x, y, z);
+ // Black magic that gets the old block state ID
+ int blockId = (block.getType().getId() << 4) | (block.getData() & 0xF);
+ // Convert block state from old version (1.12.2) -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 -> 1.16 -> 1.16.2
+ blockId = ProtocolRegistry.getProtocol(Protocol1_13To1_12_2.class).getMappingData().getNewBlockId(blockId);
+ List> protocolList = ProtocolRegistry.getProtocolPath(CLIENT_PROTOCOL_VERSION,
+ ProtocolVersion.v1_13.getId());
+ // Translate block entity differences - some information was stored in block tags and not block states
+ if (storage.isWelcome(blockId)) { // No getOrDefault method
+ BlockStorage.ReplacementData data = storage.get(new Position(x, (short) y, z));
+ if (data != null && data.getReplacement() != -1) {
+ blockId = data.getReplacement();
+ }
}
+ for (int i = protocolList.size() - 1; i >= 0; i--) {
+ MappingData mappingData = protocolList.get(i).getValue().getMappingData();
+ if (mappingData != null) {
+ blockId = mappingData.getNewBlockStateId(blockId);
+ }
+ }
+ return blockId;
}
@Override
@@ -144,11 +174,13 @@ public class GeyserSpigotWorldManager extends GeyserWorldManager {
return;
}
World world = bukkitPlayer.getWorld();
- if (this.isLegacy) {
+ if (this.isLegacy) {
+ // Get block entity storage
+ BlockStorage storage = Via.getManager().getConnection(bukkitPlayer.getUniqueId()).get(BlockStorage.class);
for (int blockY = 0; blockY < 16; blockY++) { // Cache-friendly iteration order
for (int blockZ = 0; blockZ < 16; blockZ++) {
for (int blockX = 0; blockX < 16; blockX++) {
- chunk.set(blockX, blockY, blockZ, getLegacyBlock(world, (x << 4) + blockX, (y << 4) + blockY, (z << 4) + blockZ, true));
+ chunk.set(blockX, blockY, blockZ, getLegacyBlock(storage, world, (x << 4) + blockX, (y << 4) + blockY, (z << 4) + blockZ));
}
}
}
@@ -158,7 +190,7 @@ public class GeyserSpigotWorldManager extends GeyserWorldManager {
for (int blockZ = 0; blockZ < 16; blockZ++) {
for (int blockX = 0; blockX < 16; blockX++) {
Block block = world.getBlockAt((x << 4) + blockX, (y << 4) + blockY, (z << 4) + blockZ);
- int id = BlockTranslator.getJavaIdBlockMap().getOrDefault(block.getBlockData().getAsString(), 0);
+ int id = BlockTranslator.getJavaIdBlockMap().getOrDefault(block.getBlockData().getAsString(), BlockTranslator.JAVA_AIR_ID);
chunk.set(blockX, blockY, blockZ, id);
}
}
diff --git a/bootstrap/sponge/pom.xml b/bootstrap/sponge/pom.xml
index 132f38173..e6ce8f851 100644
--- a/bootstrap/sponge/pom.xml
+++ b/bootstrap/sponge/pom.xml
@@ -6,15 +6,15 @@
org.geysermc
bootstrap-parent
- 1.1.0
- ../
+ 1.2.0-SNAPSHOT
bootstrap-sponge
+
org.geysermc
connector
- 1.1.0
+ 1.2.0-SNAPSHOT
compile
diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java
index 106d2b155..c3231f3bf 100644
--- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java
+++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java
@@ -26,10 +26,10 @@
package org.geysermc.platform.sponge;
import com.google.inject.Inject;
+import org.geysermc.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager;
-import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
diff --git a/bootstrap/standalone/pom.xml b/bootstrap/standalone/pom.xml
index 07458f730..831239f66 100644
--- a/bootstrap/standalone/pom.xml
+++ b/bootstrap/standalone/pom.xml
@@ -6,15 +6,15 @@
org.geysermc
bootstrap-parent
- 1.1.0
- ../
+ 1.2.0-SNAPSHOT
bootstrap-standalone
+
org.geysermc
connector
- 1.1.0
+ 1.2.0-SNAPSHOT
compile
diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java
index 123a9a600..a0a8a3aea 100644
--- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java
+++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java
@@ -25,17 +25,23 @@
package org.geysermc.platform.standalone;
+import com.fasterxml.jackson.databind.BeanDescription;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.introspect.AnnotatedField;
+import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import lombok.Getter;
import net.minecrell.terminalconsole.TerminalConsoleAppender;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
+import org.geysermc.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager;
-import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.configuration.GeyserConfiguration;
+import org.geysermc.connector.configuration.GeyserJacksonConfiguration;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
@@ -50,7 +56,8 @@ import java.lang.reflect.Method;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
-import java.util.UUID;
+import java.util.*;
+import java.util.stream.Collectors;
public class GeyserStandaloneBootstrap implements GeyserBootstrap {
@@ -67,6 +74,9 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
private GeyserConnector connector;
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+ private static final Map argsConfigKeys = new HashMap<>();
public static void main(String[] args) {
GeyserStandaloneBootstrap bootstrap = new GeyserStandaloneBootstrap();
@@ -74,6 +84,8 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
boolean useGuiOpts = bootstrap.useGui;
String configFilenameOpt = bootstrap.configFilename;
+ List availableProperties = getPOJOForClass(GeyserJacksonConfiguration.class);
+
for (int i = 0; i < args.length; i++) {
// By default, standalone Geyser will check if it should open the GUI based on if the GUI is null
// Optionally, you can force the use of a GUI or no GUI by specifying args
@@ -91,11 +103,11 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
case "--config":
case "-c":
if (i >= args.length - 1) {
- System.err.println(MessageFormat.format(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.confignotspecified"), "-c"));
+ System.err.println(MessageFormat.format(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.config_not_specified"), "-c"));
return;
}
configFilenameOpt = args[i+1]; i++;
- System.out.println(MessageFormat.format(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.configspecified"), configFilenameOpt));
+ System.out.println(MessageFormat.format(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.config_specified"), configFilenameOpt));
break;
case "--help":
case "-h":
@@ -106,8 +118,43 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
System.out.println(" --gui, --nogui " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.gui"));
return;
default:
- String badArgMsg = LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.unrecognised");
- System.err.println(MessageFormat.format(badArgMsg, arg));
+ // We have likely added a config option argument
+ if (arg.startsWith("--")) {
+ // Split the argument by an =
+ String[] argParts = arg.substring(2).split("=");
+ if (argParts.length == 2) {
+ // Split the config key by . to allow for nested options
+ String[] configKeyParts = argParts[0].split("\\.");
+
+ // Loop the possible config options to check the passed key is valid
+ boolean found = false;
+ for (BeanPropertyDefinition property : availableProperties) {
+ if (configKeyParts[0].equals(property.getName())) {
+ if (configKeyParts.length > 1) {
+ // Loop sub-section options to check the passed key is valid
+ for (BeanPropertyDefinition subProperty : getPOJOForClass(property.getRawPrimaryType())) {
+ if (configKeyParts[1].equals(subProperty.getName())) {
+ found = true;
+ break;
+ }
+ }
+ } else {
+ found = true;
+ }
+
+ break;
+ }
+ }
+
+ // Add the found key to the stored list for later usage
+ if (found) {
+ argsConfigKeys.put(argParts[0], argParts[1]);
+ break;
+ }
+ }
+ }
+
+ System.err.println(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.unrecognised", arg));
return;
}
}
@@ -148,6 +195,9 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
try {
File configFile = FileUtils.fileOrCopiedFromResource(new File(configFilename), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString()));
geyserConfig = FileUtils.loadConfig(configFile, GeyserStandaloneConfiguration.class);
+
+ handleArgsConfigOptions();
+
if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) {
geyserConfig.setAutoconfiguredRemote(true); // Doesn't really need to be set but /shrug
geyserConfig.getRemote().setAddress("127.0.0.1");
@@ -223,4 +273,99 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
public BootstrapDumpInfo getDumpInfo() {
return new GeyserStandaloneDumpInfo(this);
}
+
+ /**
+ * Get the {@link BeanPropertyDefinition}s for the given class
+ *
+ * @param clazz The class to get the definitions for
+ * @return A list of {@link BeanPropertyDefinition} for the given class
+ */
+ public static List getPOJOForClass(Class> clazz) {
+ JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructType(clazz);
+
+ // Introspect the given type
+ BeanDescription beanDescription = OBJECT_MAPPER.getSerializationConfig().introspect(javaType);
+
+ // Find properties
+ List properties = beanDescription.findProperties();
+
+ // Get the ignored properties
+ Set ignoredProperties = OBJECT_MAPPER.getSerializationConfig().getAnnotationIntrospector()
+ .findPropertyIgnorals(beanDescription.getClassInfo()).getIgnored();
+
+ // Filter properties removing the ignored ones
+ return properties.stream()
+ .filter(property -> !ignoredProperties.contains(property.getName()))
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Set a POJO property value on an object
+ *
+ * @param property The {@link BeanPropertyDefinition} to set
+ * @param parentObject The object to alter
+ * @param value The new value of the property
+ */
+ private static void setConfigOption(BeanPropertyDefinition property, Object parentObject, Object value) {
+ Object parsedValue = value;
+
+ // Change the values type if needed
+ if (int.class.equals(property.getRawPrimaryType())) {
+ parsedValue = Integer.valueOf((String) parsedValue);
+ } else if (boolean.class.equals(property.getRawPrimaryType())) {
+ parsedValue = Boolean.valueOf((String) parsedValue);
+ }
+
+ // Force the value to be set
+ AnnotatedField field = property.getField();
+ field.fixAccess(true);
+ field.setValue(parentObject, parsedValue);
+ }
+
+ /**
+ * Update the loaded {@link GeyserStandaloneConfiguration} with any values passed in the command line arguments
+ */
+ private void handleArgsConfigOptions() {
+ // Get the available properties from the class
+ List availableProperties = getPOJOForClass(GeyserJacksonConfiguration.class);
+
+ for (Map.Entry configKey : argsConfigKeys.entrySet()) {
+ String[] configKeyParts = configKey.getKey().split("\\.");
+
+ // Loop over the properties looking for any matches against the stored one from the argument
+ for (BeanPropertyDefinition property : availableProperties) {
+ if (configKeyParts[0].equals(property.getName())) {
+ if (configKeyParts.length > 1) {
+ // Loop through the sub property if the first part matches
+ for (BeanPropertyDefinition subProperty : getPOJOForClass(property.getRawPrimaryType())) {
+ if (configKeyParts[1].equals(subProperty.getName())) {
+ geyserLogger.info(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
+
+ // Set the sub property value on the config
+ try {
+ Object subConfig = property.getGetter().callOn(geyserConfig);
+ setConfigOption(subProperty, subConfig, configKey.getValue());
+ } catch (Exception e) {
+ geyserLogger.error("Failed to set config option: " + property.getFullName());
+ }
+
+ break;
+ }
+ }
+ } else {
+ geyserLogger.info(LanguageUtils.getLocaleStringLog("geyser.bootstrap.args.set_config_option", configKey.getKey(), configKey.getValue()));
+
+ // Set the property value on the config
+ try {
+ setConfigOption(property, geyserConfig, configKey.getValue());
+ } catch (Exception e) {
+ geyserLogger.error("Failed to set config option: " + property.getFullName());
+ }
+ }
+
+ break;
+ }
+ }
+ }
+ }
}
diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml
index ee445b6e7..86de99ba6 100644
--- a/bootstrap/velocity/pom.xml
+++ b/bootstrap/velocity/pom.xml
@@ -6,21 +6,21 @@
org.geysermc
bootstrap-parent
- 1.1.0
- ../
+ 1.2.0-SNAPSHOT
bootstrap-velocity
+
org.geysermc
connector
- 1.1.0
+ 1.2.0-SNAPSHOT
compile
com.velocitypowered
velocity-api
- 1.0.0-SNAPSHOT
+ 1.1.0
provided
diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java
index 291d7a001..b5255e623 100644
--- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java
+++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java
@@ -33,9 +33,9 @@ import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.ProxyServer;
import lombok.Getter;
+import org.geysermc.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
-import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
@@ -121,7 +121,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
this.connector = GeyserConnector.start(PlatformType.VELOCITY, this);
this.geyserCommandManager = new GeyserVelocityCommandManager(connector);
- this.commandManager.register(new GeyserVelocityCommandExecutor(connector), "geyser");
+ this.commandManager.register("geyser", new GeyserVelocityCommandExecutor(connector));
if (geyserConfig.isLegacyPingPassthrough()) {
this.geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector);
} else {
diff --git a/common/pom.xml b/common/pom.xml
index 9223331be..af5664ca1 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -6,11 +6,10 @@
org.geysermc
geyser-parent
- parent
- ../
+ 1.2.0-SNAPSHOT
common
- 1.1.0
+
com.google.code.gson
diff --git a/connector/src/main/java/org/geysermc/connector/common/PlatformType.java b/common/src/main/java/org/geysermc/common/PlatformType.java
similarity index 97%
rename from connector/src/main/java/org/geysermc/connector/common/PlatformType.java
rename to common/src/main/java/org/geysermc/common/PlatformType.java
index 3e945d3ad..883490208 100644
--- a/connector/src/main/java/org/geysermc/connector/common/PlatformType.java
+++ b/common/src/main/java/org/geysermc/common/PlatformType.java
@@ -23,7 +23,7 @@
* @link https://github.com/GeyserMC/Geyser
*/
-package org.geysermc.connector.common;
+package org.geysermc.common;
import lombok.AllArgsConstructor;
import lombok.Getter;
diff --git a/connector/pom.xml b/connector/pom.xml
index 197319875..7c44ddfd2 100644
--- a/connector/pom.xml
+++ b/connector/pom.xml
@@ -6,16 +6,15 @@
org.geysermc
geyser-parent
- parent
- ../
+ 1.2.0-SNAPSHOT
connector
- 1.1.0
+
org.geysermc
common
- 1.1.0
+ 1.2.0-SNAPSHOT
compile
@@ -32,8 +31,8 @@
com.github.CloudburstMC.Protocol
- bedrock-v408
- 02f46a8700
+ bedrock-v419
+ ce59d39118
compile
@@ -111,7 +110,7 @@
com.github.steveice10
mcprotocollib
- 1b01b1ffef
+ 86e1901be5
compile
@@ -143,17 +142,23 @@
compile
- net.kyori
+ com.github.kyoripowered.adventure
adventure-text-serializer-gson
- 4.1.1
+ 4d8a67d798
compile
- net.kyori
+ com.github.kyoripowered.adventure
adventure-text-serializer-legacy
- 4.1.1
+ 0599048
compile
+
+ junit
+ junit
+ 4.13.1
+ test
+
@@ -283,6 +288,15 @@
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.22.0
+
+
+ -Dfile.encoding=${project.build.sourceEncoding}
+
+
diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
index c44f8f434..fa5f1ec74 100644
--- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
+++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
@@ -32,10 +32,10 @@ import com.nukkitx.network.raknet.RakNetConstants;
import com.nukkitx.protocol.bedrock.BedrockServer;
import lombok.Getter;
import lombok.Setter;
+import org.geysermc.common.PlatformType;
import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager;
import org.geysermc.connector.common.AuthType;
-import org.geysermc.connector.common.PlatformType;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.metrics.Metrics;
import org.geysermc.connector.network.ConnectorServerEventHandler;
@@ -197,8 +197,7 @@ public class GeyserConnector {
}
}
- if (config.isAboveBedrockNetherBuilding())
- DimensionUtils.changeBedrockNetherId(); // Apply End dimension ID workaround to Nether
+ DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether
// https://github.com/GeyserMC/Geyser/issues/957
RakNetConstants.MAXIMUM_MTU_SIZE = (short) config.getMtu();
diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java
index 6b2be2944..64d0017ec 100644
--- a/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java
+++ b/connector/src/main/java/org/geysermc/connector/command/defaults/ReloadCommand.java
@@ -25,7 +25,7 @@
package org.geysermc.connector.command.defaults;
-import org.geysermc.connector.common.PlatformType;
+import org.geysermc.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.command.GeyserCommand;
diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java
index c69a8705f..5be6253eb 100644
--- a/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java
+++ b/connector/src/main/java/org/geysermc/connector/command/defaults/StopCommand.java
@@ -25,7 +25,7 @@
package org.geysermc.connector.command.defaults;
-import org.geysermc.connector.common.PlatformType;
+import org.geysermc.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.command.GeyserCommand;
diff --git a/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java b/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java
index c1cc4d036..153a91746 100644
--- a/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java
+++ b/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java
@@ -81,6 +81,8 @@ public interface GeyserConfiguration {
boolean isForceResourcePacks();
+ boolean isXboxAchievementsEnabled();
+
int getCacheImages();
IMetricsInfo getMetrics();
diff --git a/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java b/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java
index 45676fbd8..d19cfe49f 100644
--- a/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java
+++ b/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java
@@ -107,6 +107,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
@JsonProperty("force-resource-packs")
private boolean forceResourcePacks = true;
+ @JsonProperty("xbox-achievements-enabled")
+ private boolean xboxAchievementsEnabled = false;
+
private MetricsInfo metrics = new MetricsInfo();
@Getter
diff --git a/connector/src/main/java/org/geysermc/connector/dump/BootstrapDumpInfo.java b/connector/src/main/java/org/geysermc/connector/dump/BootstrapDumpInfo.java
index 9fbe82cc8..585565533 100644
--- a/connector/src/main/java/org/geysermc/connector/dump/BootstrapDumpInfo.java
+++ b/connector/src/main/java/org/geysermc/connector/dump/BootstrapDumpInfo.java
@@ -27,7 +27,7 @@ package org.geysermc.connector.dump;
import lombok.AllArgsConstructor;
import lombok.Getter;
-import org.geysermc.connector.common.PlatformType;
+import org.geysermc.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import java.util.List;
diff --git a/connector/src/main/java/org/geysermc/connector/entity/CommandBlockMinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/CommandBlockMinecartEntity.java
index 8cabba645..7d34cc795 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/CommandBlockMinecartEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/CommandBlockMinecartEntity.java
@@ -26,13 +26,12 @@
package org.geysermc.connector.entity;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
-import com.github.steveice10.mc.protocol.data.message.Message;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
-import org.geysermc.connector.utils.MessageUtils;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
@@ -51,7 +50,7 @@ public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
metadata.put(EntityData.COMMAND_BLOCK_COMMAND, entityMetadata.getValue());
}
if (entityMetadata.getId() == 14) {
- metadata.put(EntityData.COMMAND_BLOCK_LAST_OUTPUT, MessageUtils.getBedrockMessage((Message) entityMetadata.getValue()));
+ metadata.put(EntityData.COMMAND_BLOCK_LAST_OUTPUT, MessageTranslator.convertMessage(entityMetadata.getValue().toString()));
}
super.updateBedrockMetadata(entityMetadata, session);
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java
index 2dfb0c04f..7b1fa1cf0 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java
@@ -54,7 +54,7 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.item.ItemRegistry;
import org.geysermc.connector.utils.AttributeUtils;
import org.geysermc.connector.utils.ChunkUtils;
-import org.geysermc.connector.utils.MessageUtils;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
import java.util.ArrayList;
import java.util.HashMap;
@@ -67,8 +67,6 @@ public class Entity {
protected long entityId;
protected long geyserId;
- protected String dimension;
-
protected Vector3f position;
protected Vector3f motion;
@@ -100,7 +98,6 @@ public class Entity {
this.rotation = rotation;
this.valid = false;
- this.dimension = "minecraft:overworld";
setPosition(position);
@@ -321,7 +318,7 @@ public class Entity {
Message message = (Message) entityMetadata.getValue();
if (message != null)
// Always translate even if it's a TextMessage since there could be translatable parameters
- metadata.put(EntityData.NAMETAG, MessageUtils.getTranslatedBedrockMessage(message, session.getLocale(), true));
+ metadata.put(EntityData.NAMETAG, MessageTranslator.convertMessage(message.toString(), session.getLocale()));
}
break;
case 3: // is custom name visible
@@ -339,18 +336,6 @@ public class Entity {
metadata.getFlags().setFlag(EntityFlag.SLEEPING, true);
// Has to be a byte or it does not work
metadata.put(EntityData.PLAYER_FLAGS, (byte) 2);
- if (entityId == session.getPlayerEntity().getEntityId()) {
- Vector3i lastInteractionPos = session.getLastInteractionPosition();
- metadata.put(EntityData.BED_POSITION, lastInteractionPos);
- if (session.getConnector().getConfig().isCacheChunks()) {
- int bed = session.getConnector().getWorldManager().getBlockAt(session, lastInteractionPos.getX(),
- lastInteractionPos.getY(), lastInteractionPos.getZ());
- // Bed has to be updated, or else player is floating in the air
- ChunkUtils.updateBlock(session, bed, lastInteractionPos);
- }
- } else {
- metadata.put(EntityData.BED_POSITION, Vector3i.from(position.getFloorX(), position.getFloorY() - 2, position.getFloorZ()));
- }
metadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.2f);
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.2f);
} else if (metadata.getFlags().getFlag(EntityFlag.SLEEPING)) {
diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java
index f9d2ace46..972fa8d02 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java
@@ -69,7 +69,6 @@ public class ItemFrameEntity extends Entity {
public ItemFrameEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, HangingDirection direction) {
super(entityId, geyserId, entityType, position, motion, rotation);
- NbtMapBuilder builder = NbtMap.builder();
NbtMapBuilder blockBuilder = NbtMap.builder()
.putString("name", "minecraft:frame")
.putInt("version", BlockTranslator.getBlockStateVersion());
@@ -77,9 +76,7 @@ public class ItemFrameEntity extends Entity {
.putInt("facing_direction", direction.ordinal())
.putByte("item_frame_map_bit", (byte) 0)
.build());
- builder.put("block", blockBuilder.build());
- builder.putShort("id", (short) 199);
- bedrockRuntimeId = BlockTranslator.getItemFrame(builder.build());
+ bedrockRuntimeId = BlockTranslator.getItemFrame(blockBuilder.build());
bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ());
}
@@ -101,14 +98,12 @@ public class ItemFrameEntity extends Entity {
ItemEntry itemEntry = ItemRegistry.getItem((ItemStack) entityMetadata.getValue());
NbtMapBuilder builder = NbtMap.builder();
- String blockName = ItemRegistry.getBedrockIdentifer(itemEntry);
-
builder.putByte("Count", (byte) itemData.getCount());
if (itemData.getTag() != null) {
builder.put("tag", itemData.getTag().toBuilder().build());
}
builder.putShort("Damage", itemData.getDamage());
- builder.putString("Name", blockName);
+ builder.putString("Name", itemEntry.getBedrockIdentifier());
NbtMapBuilder tag = getDefaultTag().toBuilder();
tag.put("Item", builder.build());
tag.putFloat("ItemDropChance", 1.0f);
@@ -141,7 +136,7 @@ public class ItemFrameEntity extends Entity {
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
updateBlockPacket.setDataLayer(0);
updateBlockPacket.setBlockPosition(bedrockPosition);
- updateBlockPacket.setRuntimeId(0);
+ updateBlockPacket.setRuntimeId(BlockTranslator.BEDROCK_AIR_ID);
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
@@ -196,18 +191,6 @@ public class ItemFrameEntity extends Entity {
return session.getItemFrameCache().getOrDefault(position, -1);
}
- /**
- * Determines if the position contains an item frame.
- * Does largely the same thing as getItemFrameEntityId, but for speed purposes is implemented separately,
- * since every block destroy packet has to check for an item frame.
- * @param position position of block.
- * @param session GeyserSession.
- * @return true if position contains item frame, false if not.
- */
- public static boolean positionContainsItemFrame(GeyserSession session, Vector3i position) {
- return session.getItemFrameCache().containsKey(position);
- }
-
/**
* Force-remove from the position-to-ID map so it doesn't cause conflicts.
* @param session GeyserSession.
diff --git a/connector/src/main/java/org/geysermc/connector/entity/ItemedFireballEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ItemedFireballEntity.java
index e04e04111..1544f767a 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/ItemedFireballEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/ItemedFireballEntity.java
@@ -27,10 +27,24 @@ package org.geysermc.connector.entity;
import com.nukkitx.math.vector.Vector3f;
import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
-public class ItemedFireballEntity extends Entity {
+public class ItemedFireballEntity extends ThrowableEntity {
+ private final Vector3f acceleration;
public ItemedFireballEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
- super(entityId, geyserId, entityType, position, motion, rotation);
+ super(entityId, geyserId, entityType, position, Vector3f.ZERO, rotation);
+ acceleration = motion;
+ }
+
+ @Override
+ protected void updatePosition(GeyserSession session) {
+ position = position.add(motion);
+ // TODO: While this reduces latency in position updating (needed for better fireball reflecting),
+ // TODO: movement is incredibly stiff. See if the MoveEntityDeltaPacket in 1.16.100 fixes this, and if not,
+ // TODO: only use this laggy movement for fireballs that be reflected
+ moveAbsoluteImmediate(session, position, rotation, false, true);
+ float drag = getDrag(session);
+ motion = motion.add(acceleration).mul(drag);
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java b/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java
index ae9eaee5f..345c19dea 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java
@@ -26,7 +26,9 @@
package org.geysermc.connector.entity;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.AttributeData;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
@@ -42,6 +44,7 @@ import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.item.ItemRegistry;
import org.geysermc.connector.utils.AttributeUtils;
+import org.geysermc.connector.utils.ChunkUtils;
import java.util.ArrayList;
import java.util.List;
@@ -84,6 +87,17 @@ public class LivingEntity extends Entity {
case 10:
metadata.put(EntityData.EFFECT_AMBIENT, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0));
break;
+ case 13: // Bed Position
+ Position bedPosition = (Position) entityMetadata.getValue();
+ if (bedPosition != null) {
+ metadata.put(EntityData.BED_POSITION, Vector3i.from(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ()));
+ if (session.getConnector().getConfig().isCacheChunks()) {
+ int bed = session.getConnector().getWorldManager().getBlockAt(session, bedPosition);
+ // Bed has to be updated, or else player is floating in the air
+ ChunkUtils.updateBlock(session, bed, bedPosition);
+ }
+ }
+ break;
}
super.updateBedrockMetadata(entityMetadata, session);
diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java
index 390110d18..be65525cb 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java
@@ -27,14 +27,15 @@ package org.geysermc.connector.entity;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
-import com.github.steveice10.mc.protocol.data.game.scoreboard.NameTagVisibility;
import com.github.steveice10.mc.protocol.data.message.TextMessage;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.AttributeData;
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
+import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData;
import com.nukkitx.protocol.bedrock.packet.AddPlayerPacket;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
@@ -50,7 +51,7 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.session.cache.EntityEffectCache;
import org.geysermc.connector.scoreboard.Team;
import org.geysermc.connector.utils.AttributeUtils;
-import org.geysermc.connector.utils.MessageUtils;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
import java.util.ArrayList;
import java.util.List;
@@ -168,6 +169,17 @@ public class PlayerEntity extends LivingEntity {
movePlayerPacket.setRotation(getBedrockRotation());
movePlayerPacket.setOnGround(isOnGround);
movePlayerPacket.setMode(MovePlayerPacket.Mode.NORMAL);
+ // If the player is moved while sleeping, we have to adjust their y, so it appears
+ // correctly on Bedrock. This fixes GSit's lay.
+ if (metadata.getFlags().getFlag(EntityFlag.SLEEPING)) {
+ Vector3i bedPosition = metadata.getPos(EntityData.BED_POSITION);
+ if (bedPosition != null && (bedPosition.getY() == 0 || bedPosition.distanceSquared(position.toInt()) > 4)) {
+ // Force the player movement by using a teleport
+ movePlayerPacket.setPosition(Vector3f.from(position.getX(), position.getY() - entityType.getOffset() + 0.2f, position.getZ()));
+ movePlayerPacket.setMode(MovePlayerPacket.Mode.TELEPORT);
+ movePlayerPacket.setTeleportationCause(MovePlayerPacket.TeleportationCause.UNKNOWN);
+ }
+ }
session.sendUpstreamPacket(movePlayerPacket);
if (leftParrot != null) {
leftParrot.moveRelative(session, relX, relY, relZ, rotation, true);
@@ -231,22 +243,16 @@ public class PlayerEntity extends LivingEntity {
String username = this.username;
TextMessage name = (TextMessage) entityMetadata.getValue();
if (name != null) {
- username = MessageUtils.getBedrockMessage(name);
+ username = MessageTranslator.convertMessage(name.toString());
}
Team team = session.getWorldCache().getScoreboard().getTeamFor(username);
if (team != null) {
- // Cover different visibility settings
- if (team.getNameTagVisibility() == NameTagVisibility.NEVER) {
- metadata.put(EntityData.NAMETAG, "");
- } else if (team.getNameTagVisibility() == NameTagVisibility.HIDE_FOR_OTHER_TEAMS &&
- !team.getEntities().contains(session.getPlayerEntity().getUsername())) {
- metadata.put(EntityData.NAMETAG, "");
- } else if (team.getNameTagVisibility() == NameTagVisibility.HIDE_FOR_OWN_TEAM &&
- team.getEntities().contains(session.getPlayerEntity().getUsername())) {
- metadata.put(EntityData.NAMETAG, "");
- } else {
- metadata.put(EntityData.NAMETAG, team.getPrefix() + MessageUtils.toChatColor(team.getColor()) + username + team.getSuffix());
+ String displayName = "";
+ if (team.isVisibleFor(session.getPlayerEntity().getUsername())) {
+ displayName = MessageTranslator.toChatColor(team.getColor()) + username;
+ displayName = team.getCurrentData().getDisplayName(displayName);
}
+ metadata.put(EntityData.NAMETAG, displayName);
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/ThrowableEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ThrowableEntity.java
index b3632606b..5b7ba5c03 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/ThrowableEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/ThrowableEntity.java
@@ -31,14 +31,23 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
+/**
+ * Used as a class for any object-like entity that moves as a projectile
+ */
public class ThrowableEntity extends Entity {
private Vector3f lastPosition;
- private ScheduledFuture> positionUpdater;
+ /**
+ * Updates the position for the Bedrock client.
+ *
+ * Java clients assume the next positions of moving items. Bedrock needs to be explicitly told positions
+ */
+ protected ScheduledFuture> positionUpdater;
public ThrowableEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
super(entityId, geyserId, entityType, position, motion, rotation);
@@ -49,20 +58,86 @@ public class ThrowableEntity extends Entity {
public void spawnEntity(GeyserSession session) {
super.spawnEntity(session);
positionUpdater = session.getConnector().getGeneralThreadPool().scheduleAtFixedRate(() -> {
- super.moveRelative(session, motion.getX(), motion.getY(), motion.getZ(), rotation, onGround);
-
- if (metadata.getFlags().getFlag(EntityFlag.HAS_GRAVITY)) {
- float gravity = 0.03f; // Snowball, Egg, and Ender Pearl
- if (entityType == EntityType.THROWN_POTION || entityType == EntityType.LINGERING_POTION) {
- gravity = 0.05f;
- } else if (entityType == EntityType.THROWN_EXP_BOTTLE) {
- gravity = 0.07f;
- }
- motion = motion.down(gravity);
+ if (session.isClosed()) {
+ positionUpdater.cancel(true);
+ return;
}
+ updatePosition(session);
}, 0, 50, TimeUnit.MILLISECONDS);
}
+ protected void moveAbsoluteImmediate(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
+ super.moveAbsolute(session, position, rotation, isOnGround, teleported);
+ }
+
+ protected void updatePosition(GeyserSession session) {
+ super.moveRelative(session, motion.getX(), motion.getY(), motion.getZ(), rotation, onGround);
+ float drag = getDrag(session);
+ float gravity = getGravity();
+ motion = motion.mul(drag).down(gravity);
+ }
+
+ /**
+ * Get the gravity of this entity type. Used for applying gravity while the entity is in motion.
+ *
+ * @return the amount of gravity to apply to this entity while in motion.
+ */
+ protected float getGravity() {
+ if (metadata.getFlags().getFlag(EntityFlag.HAS_GRAVITY)) {
+ switch (entityType) {
+ case THROWN_POTION:
+ case LINGERING_POTION:
+ return 0.05f;
+ case THROWN_EXP_BOTTLE:
+ return 0.07f;
+ case FIREBALL:
+ return 0;
+ case SNOWBALL:
+ case THROWN_EGG:
+ case THROWN_ENDERPEARL:
+ return 0.03f;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * @param session the session of the Bedrock client.
+ * @return the drag that should be multiplied to the entity's motion
+ */
+ protected float getDrag(GeyserSession session) {
+ if (isInWater(session)) {
+ return 0.8f;
+ } else {
+ switch (entityType) {
+ case THROWN_POTION:
+ case LINGERING_POTION:
+ case THROWN_EXP_BOTTLE:
+ case SNOWBALL:
+ case THROWN_EGG:
+ case THROWN_ENDERPEARL:
+ return 0.99f;
+ case FIREBALL:
+ case SMALL_FIREBALL:
+ case DRAGON_FIREBALL:
+ return 0.95f;
+ }
+ }
+ return 1;
+ }
+
+ /**
+ * @param session the session of the Bedrock client.
+ * @return true if this entity is currently in water.
+ */
+ protected boolean isInWater(GeyserSession session) {
+ if (session.getConnector().getConfig().isCacheChunks()) {
+ int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
+ return block == BlockTranslator.BEDROCK_WATER_ID;
+ }
+ return false;
+ }
+
@Override
public boolean despawnEntity(GeyserSession session) {
positionUpdater.cancel(true);
diff --git a/connector/src/main/java/org/geysermc/connector/entity/WitherSkullEntity.java b/connector/src/main/java/org/geysermc/connector/entity/WitherSkullEntity.java
new file mode 100644
index 000000000..99b3df3d0
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/entity/WitherSkullEntity.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.entity;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
+import com.nukkitx.math.vector.Vector3f;
+import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+
+public class WitherSkullEntity extends ItemedFireballEntity {
+ private boolean isCharged;
+
+ public WitherSkullEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
+ super(entityId, geyserId, entityType, position, motion, rotation);
+ }
+
+ @Override
+ protected float getDrag(GeyserSession session) {
+ return isCharged ? 0.73f : super.getDrag(session);
+ }
+
+ @Override
+ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 7) {
+ boolean newIsCharged = (boolean) entityMetadata.getValue();
+ if (newIsCharged != isCharged) {
+ isCharged = newIsCharged;
+ entityType = isCharged ? EntityType.WITHER_SKULL_DANGEROUS : EntityType.WITHER_SKULL;
+ despawnEntity(session);
+ spawnEntity(session);
+ }
+ }
+ super.updateBedrockMetadata(entityMetadata, session);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java
index 07496093f..b61aeda92 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java
@@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
+import lombok.Getter;
import org.geysermc.connector.entity.LivingEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
@@ -36,6 +37,7 @@ import org.geysermc.connector.network.session.GeyserSession;
public class ArmorStandEntity extends LivingEntity {
// These are used to store the state of the armour stand for use when handling invisibility
+ @Getter
private boolean isMarker = false;
private boolean isInvisible = false;
private boolean isSmall = false;
@@ -47,7 +49,7 @@ public class ArmorStandEntity extends LivingEntity {
@Override
public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
// Fake the height to be above where it is so the nametag appears in the right location for invisible non-marker armour stands
- if (!isMarker && isInvisible) {
+ if (!isMarker && isInvisible && passengers.isEmpty()) {
position = position.add(0d, entityType.getHeight() * (isSmall ? 0.55d : 1d), 0d);
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/BatEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/BatEntity.java
new file mode 100644
index 000000000..b7b7534c8
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/BatEntity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.entity.living;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
+import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+
+public class BatEntity extends AmbientEntity {
+
+ public BatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
+ super(entityId, geyserId, entityType, position, motion, rotation);
+ }
+
+ @Override
+ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 15) {
+ byte xd = (byte) entityMetadata.getValue();
+ metadata.getFlags().setFlag(EntityFlag.RESTING, (xd & 0x01) == 0x01);
+ }
+ super.updateBedrockMetadata(entityMetadata, session);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/SnowGolemEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/SnowGolemEntity.java
new file mode 100644
index 000000000..2f75e6458
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/SnowGolemEntity.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.entity.living;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
+import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+
+public class SnowGolemEntity extends GolemEntity {
+
+ public SnowGolemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
+ super(entityId, geyserId, entityType, position, motion, rotation);
+ }
+
+ @Override
+ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 15) {
+ byte xd = (byte) entityMetadata.getValue();
+ // Handle the visibility of the pumpkin
+ metadata.getFlags().setFlag(EntityFlag.SHEARED, (xd & 0x10) != 0x10);
+ }
+ super.updateBedrockMetadata(entityMetadata, session);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java
index c46f00fe8..ee17e2a2c 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/BeeEntity.java
@@ -27,7 +27,10 @@ package org.geysermc.connector.entity.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityData;
+import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
@@ -41,10 +44,23 @@ public class BeeEntity extends AnimalEntity {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
byte xd = (byte) entityMetadata.getValue();
- metadata.getFlags().setFlag(EntityFlag.ANGRY, (xd & 0x02) == 0x02);
+ // Bee is performing sting attack; trigger animation
+ if ((xd & 0x02) == 0x02) {
+ EntityEventPacket packet = new EntityEventPacket();
+ packet.setRuntimeEntityId(geyserId);
+ packet.setType(EntityEventType.ATTACK_START);
+ packet.setData(0);
+ session.sendUpstreamPacket(packet);
+ }
+ // If the bee has stung
+ metadata.put(EntityData.MARK_VARIANT, (xd & 0x04) == 0x04 ? 1 : 0);
// If the bee has nectar or not
metadata.getFlags().setFlag(EntityFlag.POWERED, (xd & 0x08) == 0x08);
}
+ if (entityMetadata.getId() == 17) {
+ // Converting "anger time" to a boolean
+ metadata.getFlags().setFlag(EntityFlag.ANGRY, (int) entityMetadata.getValue() > 0);
+ }
super.updateBedrockMetadata(entityMetadata, session);
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java
index 88c30cbfa..bbc2d7def 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/FoxEntity.java
@@ -41,12 +41,13 @@ public class FoxEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
- metadata.put(EntityData.VARIANT, (int) entityMetadata.getValue());
+ metadata.put(EntityData.VARIANT, entityMetadata.getValue());
}
if (entityMetadata.getId() == 17) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01);
metadata.getFlags().setFlag(EntityFlag.SNEAKING, (xd & 0x04) == 0x04);
+ metadata.getFlags().setFlag(EntityFlag.INTERESTED, (xd & 0x08) == 0x08);
metadata.getFlags().setFlag(EntityFlag.SLEEPING, (xd & 0x20) == 0x20);
}
super.updateBedrockMetadata(entityMetadata, session);
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java
new file mode 100644
index 000000000..3fd291724
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/HoglinEntity.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.entity.living.animal;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
+import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.utils.DimensionUtils;
+
+public class HoglinEntity extends AnimalEntity {
+
+ public HoglinEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
+ super(entityId, geyserId, entityType, position, motion, rotation);
+ }
+
+ @Override
+ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 16) {
+ // Immune to zombification?
+ // Apply shaking effect if not in the nether and zombification is possible
+ metadata.getFlags().setFlag(EntityFlag.SHAKING, !((boolean) entityMetadata.getValue()) && !session.getDimension().equals(DimensionUtils.NETHER));
+ }
+ super.updateBedrockMetadata(entityMetadata, session);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/MooshroomEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/MooshroomEntity.java
new file mode 100644
index 000000000..69fb55fb4
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/MooshroomEntity.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.entity.living.animal;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
+import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityData;
+import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+
+public class MooshroomEntity extends AnimalEntity {
+
+ public MooshroomEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
+ super(entityId, geyserId, entityType, position, motion, rotation);
+ }
+
+ @Override
+ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 16) {
+ metadata.put(EntityData.VARIANT, entityMetadata.getValue().equals("brown") ? 1 : 0);
+ }
+ super.updateBedrockMetadata(entityMetadata, session);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java
index 7e5551226..ed3ed80b7 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PandaEntity.java
@@ -27,23 +27,75 @@ package org.geysermc.connector.entity.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityData;
+import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemRegistry;
public class PandaEntity extends AnimalEntity {
+ private int mainGene;
+ private int hiddenGene;
+
public PandaEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
super(entityId, geyserId, entityType, position, motion, rotation);
}
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 18) {
+ metadata.getFlags().setFlag(EntityFlag.EATING, (int) entityMetadata.getValue() > 0);
+ metadata.put(EntityData.EATING_COUNTER, entityMetadata.getValue());
+ if ((int) entityMetadata.getValue() != 0) {
+ // Particles and sound
+ EntityEventPacket packet = new EntityEventPacket();
+ packet.setRuntimeEntityId(geyserId);
+ packet.setType(EntityEventType.EATING_ITEM);
+ packet.setData(ItemRegistry.BAMBOO.getBedrockId() << 16);
+ session.sendUpstreamPacket(packet);
+ }
+ }
+ if (entityMetadata.getId() == 19) {
+ mainGene = (int) (byte) entityMetadata.getValue();
+ updateAppearance();
+ }
+ if (entityMetadata.getId() == 20) {
+ hiddenGene = (int) (byte) entityMetadata.getValue();
+ updateAppearance();
+ }
if (entityMetadata.getId() == 21) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.SNEEZING, (xd & 0x02) == 0x02);
- metadata.getFlags().setFlag(EntityFlag.EATING, (xd & 0x04) == 0x04);
+ metadata.getFlags().setFlag(EntityFlag.ROLLING, (xd & 0x04) == 0x04);
+ metadata.getFlags().setFlag(EntityFlag.SITTING, (xd & 0x08) == 0x08);
+ // Required to put these both for sitting to actually show
+ metadata.put(EntityData.SITTING_AMOUNT, (xd & 0x08) == 0x08 ? 1f : 0f);
+ metadata.put(EntityData.SITTING_AMOUNT_PREVIOUS, (xd & 0x08) == 0x08 ? 1f : 0f);
+ metadata.getFlags().setFlag(EntityFlag.LAYING_DOWN, (xd & 0x10) == 0x10);
}
super.updateBedrockMetadata(entityMetadata, session);
}
+
+ /**
+ * Update the panda's appearance, and take into consideration the recessive brown and weak traits that only show up
+ * when both main and hidden genes match
+ */
+ private void updateAppearance() {
+ if (mainGene == 4 || mainGene == 5) {
+ // Main gene is a recessive trait
+ if (mainGene == hiddenGene) {
+ // Main and hidden genes match; this is what the panda looks like.
+ metadata.put(EntityData.VARIANT, mainGene);
+ } else {
+ // Genes have no effect on appearance
+ metadata.put(EntityData.VARIANT, 0);
+ }
+ } else {
+ // No need to worry about hidden gene
+ metadata.put(EntityData.VARIANT, mainGene);
+ }
+ }
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java
index 0b61713aa..792027926 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/RabbitEntity.java
@@ -48,6 +48,15 @@ public class RabbitEntity extends AnimalEntity {
metadata.put(EntityData.SCALE, .35f);
metadata.getFlags().setFlag(EntityFlag.BABY, true);
}
+ } else if (entityMetadata.getId() == 16) {
+ int variant = (int) entityMetadata.getValue();
+
+ // Change the killer bunny to display as white since it only exists on Java Edition
+ if (variant == 99) {
+ variant = 1;
+ }
+
+ metadata.put(EntityData.VARIANT, variant);
}
}
}
\ No newline at end of file
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java
new file mode 100644
index 000000000..555e22684
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TurtleEntity.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.entity.living.animal;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
+import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+
+public class TurtleEntity extends AnimalEntity {
+
+ public TurtleEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
+ super(entityId, geyserId, entityType, position, motion, rotation);
+ }
+
+ @Override
+ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 17) {
+ metadata.getFlags().setFlag(EntityFlag.IS_PREGNANT, (boolean) entityMetadata.getValue());
+ } else if (entityMetadata.getId() == 18) {
+ metadata.getFlags().setFlag(EntityFlag.LAYING_EGG, (boolean) entityMetadata.getValue());
+ }
+ super.updateBedrockMetadata(entityMetadata, session);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java
index e08f9adf0..cf9f84b42 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/AbstractHorseEntity.java
@@ -27,10 +27,14 @@ package org.geysermc.connector.entity.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityData;
+import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import org.geysermc.connector.entity.living.animal.AnimalEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.item.ItemRegistry;
public class AbstractHorseEntity extends AnimalEntity {
@@ -47,6 +51,30 @@ public class AbstractHorseEntity extends AnimalEntity {
metadata.getFlags().setFlag(EntityFlag.SADDLED, (xd & 0x04) == 0x04);
metadata.getFlags().setFlag(EntityFlag.EATING, (xd & 0x10) == 0x10);
metadata.getFlags().setFlag(EntityFlag.STANDING, (xd & 0x20) == 0x20);
+
+ // HorseFlags
+ // Bred 0x10
+ // Eating 0x20
+ // Open mouth 0x80
+ int horseFlags = 0x0;
+ horseFlags = (xd & 0x40) == 0x40 ? horseFlags | 0x80 : horseFlags;
+
+ // Only set eating when we don't have mouth open so a player interaction doesn't trigger the eating animation
+ horseFlags = (xd & 0x10) == 0x10 && (xd & 0x40) != 0x40 ? horseFlags | 0x20 : horseFlags;
+
+ // Set the flags into the display item
+ metadata.put(EntityData.DISPLAY_ITEM, horseFlags);
+
+ // Send the eating particles
+ // We use the wheat metadata as static particles since Java
+ // doesn't send over what item was used to feed the horse
+ if ((xd & 0x40) == 0x40) {
+ EntityEventPacket entityEventPacket = new EntityEventPacket();
+ entityEventPacket.setRuntimeEntityId(geyserId);
+ entityEventPacket.setType(EntityEventType.EATING_ITEM);
+ entityEventPacket.setData(ItemRegistry.WHEAT.getBedrockId() << 16);
+ session.sendUpstreamPacket(entityEventPacket);
+ }
}
// Needed to control horses
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/HorseEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/HorseEntity.java
index da3ff3493..349da5e05 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/HorseEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/HorseEntity.java
@@ -28,7 +28,6 @@ package org.geysermc.connector.entity.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
-import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
@@ -41,7 +40,7 @@ public class HorseEntity extends AbstractHorseEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 18) {
- metadata.put(EntityData.VARIANT, (int) entityMetadata.getValue());
+ metadata.put(EntityData.VARIANT, entityMetadata.getValue());
metadata.put(EntityData.MARK_VARIANT, (((int) entityMetadata.getValue()) >> 8) % 5);
}
super.updateBedrockMetadata(entityMetadata, session);
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java
index 067a360cf..5c5de5466 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java
@@ -34,6 +34,8 @@ import org.geysermc.connector.network.session.GeyserSession;
public class CatEntity extends TameableEntity {
+ private byte collarColor;
+
public CatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
super(entityId, geyserId, entityType, position, motion, rotation);
}
@@ -45,6 +47,13 @@ public class CatEntity extends TameableEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ super.updateBedrockMetadata(entityMetadata, session);
+ if (entityMetadata.getId() == 16) {
+ // Update collar color if tamed
+ if (metadata.getFlags().getFlag(EntityFlag.TAMED)) {
+ metadata.put(EntityData.COLOR, collarColor);
+ }
+ }
if (entityMetadata.getId() == 18) {
// Different colors in Java and Bedrock for some reason
int variantColor;
@@ -67,11 +76,11 @@ public class CatEntity extends TameableEntity {
metadata.put(EntityData.VARIANT, variantColor);
}
if (entityMetadata.getId() == 21) {
+ collarColor = (byte) (int) entityMetadata.getValue();
// Needed or else wild cats are a red color
if (metadata.getFlags().getFlag(EntityFlag.TAMED)) {
- metadata.put(EntityData.COLOR, (byte) (int) entityMetadata.getValue());
+ metadata.put(EntityData.COLOR, collarColor);
}
}
- super.updateBedrockMetadata(entityMetadata, session);
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/TameableEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/TameableEntity.java
index 2e8ab816c..9e73ebe57 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/TameableEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/TameableEntity.java
@@ -29,10 +29,13 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.living.animal.AnimalEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
+import java.util.UUID;
+
public class TameableEntity extends AnimalEntity {
public TameableEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
@@ -46,11 +49,22 @@ public class TameableEntity extends AnimalEntity {
metadata.getFlags().setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01);
metadata.getFlags().setFlag(EntityFlag.ANGRY, (xd & 0x02) == 0x02);
metadata.getFlags().setFlag(EntityFlag.TAMED, (xd & 0x04) == 0x04);
- // Must be set for wolf collar color to work
- // Extending it to all entities to prevent future bugs
- if (metadata.getFlags().getFlag(EntityFlag.TAMED)) {
- metadata.put(EntityData.OWNER_EID, session.getPlayerEntity().getGeyserId());
- } // Can't de-tame an entity so no resetting the owner ID
+ }
+
+ // Note: Must be set for wolf collar color to work
+ if (entityMetadata.getId() == 17) {
+ if (entityMetadata.getValue() != null) {
+ // Owner UUID of entity
+ Entity entity = session.getEntityCache().getPlayerEntity((UUID) entityMetadata.getValue());
+ // Used as both a check since the player isn't in the entity cache and a normal fallback
+ if (entity == null) {
+ entity = session.getPlayerEntity();
+ }
+ // Translate to entity ID
+ metadata.put(EntityData.OWNER_EID, entity.getGeyserId());
+ } else {
+ metadata.put(EntityData.OWNER_EID, 0L); // Reset
+ }
}
super.updateBedrockMetadata(entityMetadata, session);
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java
index 7ada302c2..028d18312 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/merchant/VillagerEntity.java
@@ -26,26 +26,32 @@
package org.geysermc.connector.entity.living.merchant;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
-import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData;
import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
-import com.nukkitx.protocol.bedrock.data.entity.EntityFlags;
-import com.nukkitx.protocol.bedrock.packet.*;
+import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.world.WorldManager;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
+
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class VillagerEntity extends AbstractMerchantEntity {
+ /**
+ * A map of Java profession IDs to Bedrock IDs
+ */
private static final Int2IntMap VILLAGER_VARIANTS = new Int2IntOpenHashMap();
- private static final Int2IntMap VILLAGER_REGIONS = new Int2IntOpenHashMap();
+ /**
+ * A map of all Java region IDs (plains, savanna...) to Bedrock
+ */
+ public static final Int2IntMap VILLAGER_REGIONS = new Int2IntOpenHashMap();
static {
// Java villager profession IDs -> Bedrock
@@ -99,9 +105,9 @@ public class VillagerEntity extends AbstractMerchantEntity {
int bedId = 0;
float bedPositionSubtractorW = 0;
float bedPositionSubtractorN = 0;
- if (session.getConnector().getConfig().isCacheChunks()) {
- Position bedLocation = new Position((int) position.getFloorX(), (int) position.getFloorY(), (int) position.getFloorZ());
- bedId = session.getConnector().getWorldManager().getBlockAt(session, bedLocation);
+ Vector3i bedPosition = metadata.getPos(EntityData.BED_POSITION);
+ if (session.getConnector().getConfig().isCacheChunks() && bedPosition != null) {
+ bedId = session.getConnector().getWorldManager().getBlockAt(session, bedPosition);
}
String bedRotationZ = BlockTranslator.getJavaIdBlockMap().inverse().get(bedId);
setRotation(rotation);
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/BasePiglinEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/BasePiglinEntity.java
index 830c7ea3d..b83a2ca73 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/BasePiglinEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/BasePiglinEntity.java
@@ -1,11 +1,25 @@
package org.geysermc.connector.entity.living.monster;
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.utils.DimensionUtils;
public class BasePiglinEntity extends MonsterEntity {
public BasePiglinEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
super(entityId, geyserId, entityType, position, motion, rotation);
}
-}
\ No newline at end of file
+
+ @Override
+ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 15) {
+ // Immune to zombification?
+ // Apply shaking effect if not in the nether and zombification is possible
+ metadata.getFlags().setFlag(EntityFlag.SHAKING, !((boolean) entityMetadata.getValue()) && !session.getDimension().equals(DimensionUtils.NETHER));
+ }
+ super.updateBedrockMetadata(entityMetadata, session);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/CreeperEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/CreeperEntity.java
index 3c3a76bd7..f4931861c 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/CreeperEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/CreeperEntity.java
@@ -33,6 +33,12 @@ import org.geysermc.connector.network.session.GeyserSession;
public class CreeperEntity extends MonsterEntity {
+ /**
+ * Whether the creeper has been ignited and is using ID 17.
+ * In this instance we ignore ID 15 since it's sending us -1 which confuses poor Bedrock.
+ */
+ private boolean ignitedByFlintAndSteel = false;
+
public CreeperEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
super(entityId, geyserId, entityType, position, motion, rotation);
}
@@ -40,13 +46,16 @@ public class CreeperEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
- metadata.getFlags().setFlag(EntityFlag.IGNITED, (int) entityMetadata.getValue() == 1);
+ if (!ignitedByFlintAndSteel) {
+ metadata.getFlags().setFlag(EntityFlag.IGNITED, (int) entityMetadata.getValue() == 1);
+ }
}
if (entityMetadata.getId() == 16) {
metadata.getFlags().setFlag(EntityFlag.POWERED, (boolean) entityMetadata.getValue());
}
if (entityMetadata.getId() == 17) {
- metadata.getFlags().setFlag(EntityFlag.IGNITED, (boolean) entityMetadata.getValue());
+ ignitedByFlintAndSteel = (boolean) entityMetadata.getValue();
+ metadata.getFlags().setFlag(EntityFlag.IGNITED, ignitedByFlintAndSteel);
}
super.updateBedrockMetadata(entityMetadata, session);
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/GhastEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GhastEntity.java
new file mode 100644
index 000000000..3d3be87ce
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GhastEntity.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.entity.living.monster;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
+import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityData;
+import org.geysermc.connector.entity.living.FlyingEntity;
+import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+
+public class GhastEntity extends FlyingEntity {
+
+ public GhastEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
+ super(entityId, geyserId, entityType, position, motion, rotation);
+ }
+
+ @Override
+ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 15) {
+ // If the ghast is attacking
+ metadata.put(EntityData.CHARGE_AMOUNT, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0));
+ }
+ super.updateBedrockMetadata(entityMetadata, session);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java
index 7b0d71e17..e0b443d3b 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java
@@ -41,7 +41,7 @@ public class PiglinEntity extends BasePiglinEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
- if (entityMetadata.getId() == 15) {
+ if (entityMetadata.getId() == 16) {
boolean isBaby = (boolean) entityMetadata.getValue();
if (isBaby) {
metadata.put(EntityData.SCALE, .55f);
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/VexEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/VexEntity.java
new file mode 100644
index 000000000..70e413298
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/VexEntity.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.entity.living.monster;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
+import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityData;
+import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+
+public class VexEntity extends MonsterEntity {
+
+ public VexEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
+ super(entityId, geyserId, entityType, position, motion, rotation);
+ }
+
+ @Override
+ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 15) {
+ byte xd = (byte) entityMetadata.getValue();
+ // Set the target to the player to force the attack animation
+ // even if the player isn't the target as we dont get the target on Java
+ metadata.put(EntityData.TARGET_EID, (xd & 0x01) == 0x01 ? session.getPlayerEntity().getGeyserId() : 0);
+ }
+ super.updateBedrockMetadata(entityMetadata, session);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieVillagerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieVillagerEntity.java
new file mode 100644
index 000000000..b8a628170
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieVillagerEntity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.entity.living.monster;
+
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
+import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData;
+import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.data.entity.EntityData;
+import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import org.geysermc.connector.entity.living.merchant.VillagerEntity;
+import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+
+public class ZombieVillagerEntity extends ZombieEntity {
+
+ public ZombieVillagerEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
+ super(entityId, geyserId, entityType, position, motion, rotation);
+ }
+
+ @Override
+ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
+ if (entityMetadata.getId() == 18) {
+ metadata.getFlags().setFlag(EntityFlag.IS_TRANSFORMING, (boolean) entityMetadata.getValue());
+ metadata.getFlags().setFlag(EntityFlag.SHAKING, (boolean) entityMetadata.getValue());
+ }
+ if (entityMetadata.getId() == 19) {
+ VillagerData villagerData = (VillagerData) entityMetadata.getValue();
+ // Region - only one used on Bedrock
+ metadata.put(EntityData.MARK_VARIANT, VillagerEntity.VILLAGER_REGIONS.get(villagerData.getType()));
+ }
+ super.updateBedrockMetadata(entityMetadata, session);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java
index fddab5a42..05447760d 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java
@@ -47,12 +47,12 @@ public enum EntityType {
SHEEP(SheepEntity.class, 13, 1.3f, 0.9f),
WOLF(WolfEntity.class, 14, 0.85f, 0.6f),
VILLAGER(VillagerEntity.class, 15, 1.8f, 0.6f, 0.6f, 1.62f, "minecraft:villager_v2"),
- MOOSHROOM(AnimalEntity.class, 16, 1.4f, 0.9f),
+ MOOSHROOM(MooshroomEntity.class, 16, 1.4f, 0.9f),
SQUID(SquidEntity.class, 17, 0.8f),
RABBIT(RabbitEntity.class, 18, 0.5f, 0.4f),
- BAT(AmbientEntity.class, 19, 0.9f, 0.5f),
+ BAT(BatEntity.class, 19, 0.9f, 0.5f),
IRON_GOLEM(GolemEntity.class, 20, 2.7f, 1.4f),
- SNOW_GOLEM(GolemEntity.class, 21, 1.9f, 0.7f),
+ SNOW_GOLEM(SnowGolemEntity.class, 21, 1.9f, 0.7f),
OCELOT(OcelotEntity.class, 22, 0.35f, 0.3f),
HORSE(HorseEntity.class, 23, 1.6f, 1.3965f),
DONKEY(ChestedHorseEntity.class, 24, 1.6f, 1.3965f),
@@ -74,10 +74,10 @@ public enum EntityType {
ENDERMAN(EndermanEntity.class, 38, 2.9f, 0.6f),
SILVERFISH(MonsterEntity.class, 39, 0.3f, 0.4f),
CAVE_SPIDER(MonsterEntity.class, 40, 0.5f, 0.7f),
- GHAST(FlyingEntity.class, 41, 4.0f),
+ GHAST(GhastEntity.class, 41, 4.0f),
MAGMA_CUBE(MagmaCubeEntity.class, 42, 0.51f),
BLAZE(BlazeEntity.class, 43, 1.8f, 0.6f),
- ZOMBIE_VILLAGER(ZombieEntity.class, 44, 1.8f, 0.6f, 0.6f, 1.62f),
+ ZOMBIE_VILLAGER(ZombieVillagerEntity.class, 44, 1.8f, 0.6f, 0.6f, 1.62f, "minecraft:zombie_villager_v2"),
WITCH(RaidParticipantEntity.class, 45, 1.8f, 0.6f, 0.6f, 1.62f),
STRAY(AbstractSkeletonEntity.class, 46, 1.8f, 0.6f, 0.6f, 1.62f),
HUSK(ZombieEntity.class, 47, 1.8f, 0.6f, 0.6f, 1.62f),
@@ -109,7 +109,7 @@ public enum EntityType {
END_CRYSTAL(EnderCrystalEntity.class, 71, 2.0f, 2.0f, 2.0f, 0f, "minecraft:ender_crystal"),
FIREWORK_ROCKET(FireworkEntity.class, 72, 0.25f, 0.25f, 0.25f, 0f, "minecraft:fireworks_rocket"),
TRIDENT(TridentEntity.class, 73, 0f, 0f, 0f, 0f, "minecraft:thrown_trident"),
- TURTLE(AnimalEntity.class, 74, 0.4f, 1.2f),
+ TURTLE(TurtleEntity.class, 74, 0.4f, 1.2f),
CAT(CatEntity.class, 75, 0.35f, 0.3f),
SHULKER_BULLET(Entity.class, 76, 0.3125f),
FISHING_BOBBER(FishingHookEntity.class, 77, 0f, 0f, 0f, 0f, "minecraft:fishing_hook"),
@@ -125,9 +125,9 @@ public enum EntityType {
THROWN_POTION(ThrowableEntity.class, 86, 0.25f, 0.25f, 0.25f, 0f, "minecraft:splash_potion"),
THROWN_ENDERPEARL(ThrowableEntity.class, 87, 0.25f, 0.25f, 0.25f, 0f, "minecraft:ender_pearl"),
LEASH_KNOT(LeashKnotEntity.class, 88, 0.5f, 0.375f),
- WITHER_SKULL(Entity.class, 89, 0.3125f),
+ WITHER_SKULL(WitherSkullEntity.class, 89, 0.3125f),
BOAT(BoatEntity.class, 90, 0.7f, 1.6f, 1.6f, 0.35f),
- WITHER_SKULL_DANGEROUS(Entity.class, 91, 0f),
+ WITHER_SKULL_DANGEROUS(WitherSkullEntity.class, 91, 0f),
LIGHTNING_BOLT(Entity.class, 93, 0f),
SMALL_FIREBALL(ItemedFireballEntity.class, 94, 0.3125f),
AREA_EFFECT_CLOUD(AreaEffectCloudEntity.class, 95, 0.5f, 1.0f),
@@ -141,7 +141,7 @@ public enum EntityType {
LLAMA_SPIT(Entity.class, 102, 0.25f),
EVOKER_FANGS(Entity.class, 103, 0.8f, 0.5f, 0.5f, 0f, "minecraft:evocation_fang"),
EVOKER(SpellcasterIllagerEntity.class, 104, 1.95f, 0.6f, 0.6f, 0f, "minecraft:evocation_illager"),
- VEX(MonsterEntity.class, 105, 0.8f, 0.4f),
+ VEX(VexEntity.class, 105, 0.8f, 0.4f),
ICE_BOMB(Entity.class, 106, 0f),
BALLOON(Entity.class, 107, 0f), //TODO
PUFFERFISH(PufferFishEntity.class, 108, 0.7f, 0.7f),
@@ -153,7 +153,7 @@ public enum EntityType {
FOX(FoxEntity.class, 121, 0.5f, 1.25f),
BEE(BeeEntity.class, 122, 0.6f, 0.6f),
STRIDER(StriderEntity.class, 125, 1.7f, 0.9f, 0f, 0f, "minecraft:strider"),
- HOGLIN(AnimalEntity.class, 124, 1.4f, 1.3965f, 1.3965f, 0f, "minecraft:hoglin"),
+ HOGLIN(HoglinEntity.class, 124, 1.4f, 1.3965f, 1.3965f, 0f, "minecraft:hoglin"),
ZOGLIN(ZoglinEntity.class, 126, 1.4f, 1.3965f, 1.3965f, 0f, "minecraft:zoglin"),
PIGLIN(PiglinEntity.class, 123, 1.95f, 0.6f, 0.6f, 0f, "minecraft:piglin"),
PIGLIN_BRUTE(BasePiglinEntity.class, 127, 1.95f, 0.6f, 0.6f, 0f, "minecraft:piglin_brute"),
diff --git a/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java b/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java
index 5d4462b45..85043d378 100644
--- a/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java
+++ b/connector/src/main/java/org/geysermc/connector/network/BedrockProtocol.java
@@ -26,8 +26,7 @@
package org.geysermc.connector.network;
import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
-import com.nukkitx.protocol.bedrock.v407.Bedrock_v407;
-import com.nukkitx.protocol.bedrock.v408.Bedrock_v408;
+import com.nukkitx.protocol.bedrock.v419.Bedrock_v419;
import java.util.ArrayList;
import java.util.List;
@@ -40,14 +39,13 @@ public class BedrockProtocol {
* Default Bedrock codec that should act as a fallback. Should represent the latest available
* release of the game that Geyser supports.
*/
- public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v408.V408_CODEC;
+ public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v419.V419_CODEC;
/**
* A list of all supported Bedrock versions that can join Geyser
*/
public static final List SUPPORTED_BEDROCK_CODECS = new ArrayList<>();
static {
- SUPPORTED_BEDROCK_CODECS.add(Bedrock_v407.V407_CODEC);
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java
index 9fb4ad9e1..150d298c7 100644
--- a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java
+++ b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java
@@ -25,7 +25,6 @@
package org.geysermc.connector.network;
-import com.github.steveice10.mc.protocol.data.message.MessageSerializer;
import com.nukkitx.protocol.bedrock.BedrockPong;
import com.nukkitx.protocol.bedrock.BedrockServerEventHandler;
import com.nukkitx.protocol.bedrock.BedrockServerSession;
@@ -36,7 +35,7 @@ import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.ping.IGeyserPingPassthrough;
-import org.geysermc.connector.utils.MessageUtils;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
import org.geysermc.connector.utils.LanguageUtils;
import java.net.InetSocketAddress;
@@ -76,7 +75,7 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
pong.setIpv4Port(config.getBedrock().getPort());
if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) {
- String[] motd = MessageUtils.getBedrockMessage(MessageSerializer.fromString(pingInfo.getDescription())).split("\n");
+ String[] motd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n");
String mainMotd = motd[0]; // First line of the motd.
String subMotd = (motd.length != 1) ? motd[1] : ""; // Second line of the motd if present, otherwise blank.
diff --git a/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java
index 7faf36bdd..510bba2d2 100644
--- a/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java
+++ b/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java
@@ -25,12 +25,11 @@
package org.geysermc.connector.network;
-import com.github.steveice10.mc.protocol.data.message.MessageSerializer;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import org.geysermc.connector.common.ping.GeyserPingInfo;
import org.geysermc.connector.GeyserConnector;
-import org.geysermc.connector.utils.MessageUtils;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -148,7 +147,7 @@ public class QueryPacketHandler {
}
if (connector.getConfig().isPassthroughMotd() && pingInfo != null) {
- String[] javaMotd = MessageUtils.getBedrockMessage(MessageSerializer.fromString(pingInfo.getDescription())).split("\n");
+ String[] javaMotd = MessageTranslator.convertMessageLenient(pingInfo.getDescription()).split("\n");
motd = javaMotd[0].trim(); // First line of the motd.
} else {
motd = connector.getConfig().getBedrock().getMotd1();
diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
index 20d2bb9e7..4ff6fcba6 100644
--- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
+++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
@@ -59,9 +59,11 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
if (packetCodec == null) {
if (loginPacket.getProtocolVersion() > BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) {
// Too early to determine session locale
+ session.getConnector().getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.outdated.server", BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()));
session.disconnect(LanguageUtils.getLocaleStringLog("geyser.network.outdated.server", BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()));
return true;
} else if (loginPacket.getProtocolVersion() < BedrockProtocol.DEFAULT_BEDROCK_CODEC.getProtocolVersion()) {
+ session.getConnector().getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.outdated.client", BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()));
session.disconnect(LanguageUtils.getLocaleStringLog("geyser.network.outdated.client", BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion()));
return true;
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java
index 99aada2a5..d3bb2436f 100644
--- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java
+++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java
@@ -34,7 +34,6 @@ import com.github.steveice10.mc.protocol.data.SubProtocol;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.statistic.Statistic;
import com.github.steveice10.mc.protocol.data.game.window.VillagerTrade;
-import com.github.steveice10.mc.protocol.data.message.MessageSerializer;
import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket;
@@ -65,6 +64,7 @@ import org.geysermc.connector.common.AuthType;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.PlayerEntity;
import org.geysermc.connector.inventory.PlayerInventory;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
import org.geysermc.connector.network.remote.RemoteServer;
import org.geysermc.connector.network.session.auth.AuthData;
import org.geysermc.connector.network.session.auth.BedrockClientData;
@@ -74,7 +74,6 @@ import org.geysermc.connector.network.translators.EntityIdentifierRegistry;
import org.geysermc.connector.network.translators.PacketTranslatorRegistry;
import org.geysermc.connector.network.translators.inventory.EnchantmentInventoryTranslator;
import org.geysermc.connector.network.translators.item.ItemRegistry;
-import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.utils.*;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.floodgate.util.BedrockData;
@@ -142,6 +141,13 @@ public class GeyserSession implements CommandSender {
@Setter
private boolean jumping;
+ /**
+ * The dimension of the player.
+ * As all entities are in the same world, this can be safely applied to all other entities.
+ */
+ @Setter
+ private String dimension = DimensionUtils.OVERWORLD;
+
@Setter
private int breakingBlock;
@@ -217,6 +223,12 @@ public class GeyserSession implements CommandSender {
@Setter
private ScheduledFuture> bucketScheduledFuture;
+ /**
+ * Sends a movement packet every three seconds if the player hasn't moved. Prevents timeouts when AFK in certain instances.
+ */
+ @Setter
+ private ScheduledFuture> movementSendIfIdle;
+
private boolean reducedDebugInfo = false;
/**
@@ -471,7 +483,7 @@ public class GeyserSession implements CommandSender {
event.getCause().printStackTrace();
}
- upstream.disconnect(MessageUtils.getBedrockMessage(MessageSerializer.fromString(event.getReason())));
+ upstream.disconnect(MessageTranslator.convertMessageLenient(event.getReason()));
}
@Override
@@ -611,12 +623,12 @@ public class GeyserSession implements CommandSender {
startGamePacket.setRotation(Vector2f.from(1, 1));
startGamePacket.setSeed(-1);
- startGamePacket.setDimensionId(DimensionUtils.javaToBedrock(playerEntity.getDimension()));
+ startGamePacket.setDimensionId(DimensionUtils.javaToBedrock(dimension));
startGamePacket.setGeneratorId(1);
startGamePacket.setLevelGameType(GameType.SURVIVAL);
startGamePacket.setDifficulty(1);
startGamePacket.setDefaultSpawn(Vector3i.ZERO);
- startGamePacket.setAchievementsDisabled(true);
+ startGamePacket.setAchievementsDisabled(!connector.getConfig().isXboxAchievementsEnabled());
startGamePacket.setCurrentTick(-1);
startGamePacket.setEduEditionOffers(0);
startGamePacket.setEduFeaturesEnabled(false);
@@ -627,7 +639,7 @@ public class GeyserSession implements CommandSender {
startGamePacket.getGamerules().add(new GameRuleData<>("showcoordinates", true));
startGamePacket.setPlatformBroadcastMode(GamePublishSetting.PUBLIC);
startGamePacket.setXblBroadcastMode(GamePublishSetting.PUBLIC);
- startGamePacket.setCommandsEnabled(true);
+ startGamePacket.setCommandsEnabled(!connector.getConfig().isXboxAchievementsEnabled());
startGamePacket.setTexturePacksRequired(false);
startGamePacket.setBonusChestEnabled(false);
startGamePacket.setStartingWithMap(false);
@@ -649,7 +661,6 @@ public class GeyserSession implements CommandSender {
// startGamePacket.setCurrentTick(0);
startGamePacket.setEnchantmentSeed(0);
startGamePacket.setMultiplayerCorrelationId("");
- startGamePacket.setBlockPalette(BlockTranslator.BLOCKS);
startGamePacket.setItemEntries(ItemRegistry.ITEMS);
startGamePacket.setVanillaVersion("*");
startGamePacket.setAuthoritativeMovementMode(AuthoritativeMovementMode.CLIENT);
diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java
index fdc609ab9..7eadb7942 100644
--- a/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java
+++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java
@@ -33,7 +33,7 @@ import com.nukkitx.protocol.bedrock.packet.BossEventPacket;
import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket;
import lombok.AllArgsConstructor;
import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.utils.MessageUtils;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
@AllArgsConstructor
public class BossBar {
@@ -58,7 +58,7 @@ public class BossBar {
BossEventPacket bossEventPacket = new BossEventPacket();
bossEventPacket.setBossUniqueEntityId(entityId);
bossEventPacket.setAction(BossEventPacket.Action.CREATE);
- bossEventPacket.setTitle(MessageUtils.getTranslatedBedrockMessage(title, session.getLocale()));
+ bossEventPacket.setTitle(MessageTranslator.convertMessage(title.toString(), session.getLocale()));
bossEventPacket.setHealthPercentage(health);
bossEventPacket.setColor(color); //ignored by client
bossEventPacket.setOverlay(overlay);
@@ -72,7 +72,7 @@ public class BossBar {
BossEventPacket bossEventPacket = new BossEventPacket();
bossEventPacket.setBossUniqueEntityId(entityId);
bossEventPacket.setAction(BossEventPacket.Action.UPDATE_NAME);
- bossEventPacket.setTitle(MessageUtils.getTranslatedBedrockMessage(title, session.getLocale()));
+ bossEventPacket.setTitle(MessageTranslator.convertMessage(title.toString(), session.getLocale()));
session.sendUpstreamPacket(bossEventPacket);
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java
index 7bf84b8db..cbf3721f7 100644
--- a/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java
+++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/ChunkCache.java
@@ -94,12 +94,12 @@ public class ChunkCache {
public int getBlockAt(int x, int y, int z) {
if (!cache) {
- return BlockTranslator.AIR;
+ return BlockTranslator.JAVA_AIR_ID;
}
Column column = this.getChunk(x >> 4, z >> 4);
if (column == null) {
- return BlockTranslator.AIR;
+ return BlockTranslator.JAVA_AIR_ID;
}
Chunk chunk = column.getChunks()[y >> 4];
@@ -107,7 +107,7 @@ public class ChunkCache {
return chunk.get(x & 0xF, y & 0xF, z & 0xF);
}
- return BlockTranslator.AIR;
+ return BlockTranslator.JAVA_AIR_ID;
}
public void removeChunk(int chunkX, int chunkZ) {
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java
index 023a83afe..3e40ddd6f 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestTranslator.java
@@ -42,7 +42,7 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator {
@@ -48,7 +48,7 @@ public class BedrockCommandRequestTranslator extends PacketTranslator {
@@ -40,7 +40,7 @@ public class BedrockTextTranslator extends PacketTranslator {
public void translate(TextPacket packet, GeyserSession session) {
String message = packet.getMessage().replaceAll("^\\.", "/").trim();
- if (MessageUtils.isTooLong(message, session)) {
+ if (MessageTranslator.isTooLong(message, session)) {
return;
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockInteractTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockInteractTranslator.java
index c5d6f2dda..6c03cd033 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockInteractTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockInteractTranslator.java
@@ -25,27 +25,65 @@
package org.geysermc.connector.network.translators.bedrock.entity.player;
-import com.nukkitx.protocol.bedrock.data.entity.EntityData;
-import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap;
-import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
-import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
-import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
-import org.geysermc.connector.entity.Entity;
-import org.geysermc.connector.network.session.GeyserSession;
-import org.geysermc.connector.network.translators.PacketTranslator;
-import org.geysermc.connector.network.translators.Translator;
-
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket;
+import com.nukkitx.protocol.bedrock.data.entity.EntityData;
+import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap;
+import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
+import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
import com.nukkitx.protocol.bedrock.packet.InteractPacket;
+import lombok.Getter;
+import org.geysermc.connector.entity.Entity;
+import org.geysermc.connector.entity.type.EntityType;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.PacketTranslator;
+import org.geysermc.connector.network.translators.Translator;
+import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ItemRegistry;
+import java.util.Arrays;
+import java.util.List;
+
@Translator(packet = InteractPacket.class)
public class BedrockInteractTranslator extends PacketTranslator {
+ /**
+ * A list of all foods a horse/donkey can eat on Java Edition.
+ * Used to display interactive tag if needed.
+ */
+ private static final List DONKEY_AND_HORSE_FOODS = Arrays.asList("golden_apple", "enchanted_golden_apple",
+ "golden_carrot", "sugar", "apple", "wheat", "hay_block");
+
+ /**
+ * A list of all flowers. Used for feeding bees.
+ */
+ private static final List FLOWERS = Arrays.asList("dandelion", "poppy", "blue_orchid", "allium", "azure_bluet",
+ "red_tulip", "pink_tulip", "white_tulip", "orange_tulip", "cornflower", "lily_of_the_valley", "wither_rose",
+ "sunflower", "lilac", "rose_bush", "peony");
+
+ /**
+ * All entity types that can be leashed on Java Edition
+ */
+ private static final List LEASHABLE_MOB_TYPES = Arrays.asList(EntityType.BEE, EntityType.CAT, EntityType.CHICKEN,
+ EntityType.COW, EntityType.DOLPHIN, EntityType.DONKEY, EntityType.FOX, EntityType.HOGLIN, EntityType.HORSE, EntityType.SKELETON_HORSE,
+ EntityType.ZOMBIE_HORSE, EntityType.IRON_GOLEM, EntityType.LLAMA, EntityType.TRADER_LLAMA, EntityType.MOOSHROOM,
+ EntityType.MULE, EntityType.OCELOT, EntityType.PARROT, EntityType.PIG, EntityType.POLAR_BEAR, EntityType.RABBIT,
+ EntityType.SHEEP, EntityType.SNOW_GOLEM, EntityType.STRIDER, EntityType.WOLF, EntityType.ZOGLIN);
+
+ private static final List SADDLEABLE_WHEN_TAMED_MOB_TYPES = Arrays.asList(EntityType.DONKEY, EntityType.HORSE,
+ EntityType.ZOMBIE_HORSE, EntityType.MULE);
+ /**
+ * A list of all foods a wolf can eat on Java Edition.
+ * Used to display interactive tag if needed.
+ */
+ private static final List WOLF_FOODS = Arrays.asList("pufferfish", "tropical_fish", "chicken", "cooked_chicken",
+ "porkchop", "beef", "rabbit", "cooked_porkchop", "cooked_beef", "rotten_flesh", "mutton", "cooked_mutton",
+ "cooked_rabbit");
+
@Override
public void translate(InteractPacket packet, GeyserSession session) {
Entity entity;
@@ -84,50 +122,232 @@ public class BedrockInteractTranslator extends PacketTranslator
if (interactEntity == null)
return;
EntityDataMap entityMetadata = interactEntity.getMetadata();
+ ItemEntry itemEntry = session.getInventory().getItemInHand() == null ? ItemEntry.AIR : ItemRegistry.getItem(session.getInventory().getItemInHand());
+ String javaIdentifierStripped = itemEntry.getJavaIdentifier().replace("minecraft:", "");
- String interactiveTag;
- switch (interactEntity.getEntityType()) {
- case BOAT:
- interactiveTag = "action.interact.ride.boat";
- break;
- case DONKEY:
- case HORSE:
- case LLAMA:
- case MULE:
- case SKELETON_HORSE:
- case TRADER_LLAMA:
- case ZOMBIE_HORSE:
- if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED)) {
- interactiveTag = "action.interact.ride.horse";
- } else {
- interactiveTag = "action.interact.mount";
- }
- break;
- case MINECART:
- interactiveTag = "action.interact.ride.minecart";
- break;
- case PIG:
- if (entityMetadata.getFlags().getFlag(EntityFlag.SADDLED)) {
- interactiveTag = "action.interact.mount";
- } else interactiveTag = "";
- break;
- case VILLAGER:
- if (entityMetadata.getInt(EntityData.VARIANT) != 14 && entityMetadata.getInt(EntityData.VARIANT) != 0
- && entityMetadata.getFloat(EntityData.SCALE) >= 0.75f) { // Not a nitwit, has a profession and is not a baby
- interactiveTag = "action.interact.trade";
- } else interactiveTag = "";
- break;
- case WANDERING_TRADER:
- interactiveTag = "action.interact.trade"; // Since you can always trade with a wandering villager, presumably.
- break;
- default:
- return; // No need to process any further since there is no interactive tag
+ // TODO - in the future, update these in the metadata? So the client doesn't have to wiggle their cursor around for it to happen
+ // TODO - also, might be good to abstract out the eating thing. I know there will need to be food tracked for https://github.com/GeyserMC/Geyser/issues/1005 but not all food is breeding food
+ InteractiveTag interactiveTag = InteractiveTag.NONE;
+ if (entityMetadata.getLong(EntityData.LEASH_HOLDER_EID) == session.getPlayerEntity().getGeyserId()) {
+ // Unleash the entity
+ interactiveTag = InteractiveTag.REMOVE_LEASH;
+ } else if (javaIdentifierStripped.equals("saddle") && !entityMetadata.getFlags().getFlag(EntityFlag.SADDLED) &&
+ ((SADDLEABLE_WHEN_TAMED_MOB_TYPES.contains(interactEntity.getEntityType()) && entityMetadata.getFlags().getFlag(EntityFlag.TAMED)) ||
+ interactEntity.getEntityType() == EntityType.PIG || interactEntity.getEntityType() == EntityType.STRIDER)) {
+ // Entity can be saddled and the conditions meet (entity can be saddled and, if needed, is tamed)
+ interactiveTag = InteractiveTag.SADDLE;
+ } else if (javaIdentifierStripped.equals("name_tag") && session.getInventory().getItemInHand().getNbt() != null &&
+ session.getInventory().getItemInHand().getNbt().contains("display")) {
+ // Holding a named name tag
+ interactiveTag = InteractiveTag.NAME;
+ } else if (javaIdentifierStripped.equals("lead") && LEASHABLE_MOB_TYPES.contains(interactEntity.getEntityType()) &&
+ entityMetadata.getLong(EntityData.LEASH_HOLDER_EID) == -1L) {
+ // Holding a leash and the mob is leashable for sure
+ // (Plugins can change this behavior so that's something to look into in the far far future)
+ interactiveTag = InteractiveTag.LEASH;
+ } else {
+ switch (interactEntity.getEntityType()) {
+ case BEE:
+ if (FLOWERS.contains(javaIdentifierStripped)) {
+ interactiveTag = InteractiveTag.FEED;
+ }
+ break;
+ case BOAT:
+ interactiveTag = InteractiveTag.BOARD_BOAT;
+ break;
+ case CAT:
+ if (javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon")) {
+ interactiveTag = InteractiveTag.FEED;
+ } else if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED) &&
+ entityMetadata.getLong(EntityData.OWNER_EID) == session.getPlayerEntity().getGeyserId()) {
+ // Tamed and owned by player - can sit/stand
+ interactiveTag = entityMetadata.getFlags().getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
+ break;
+ }
+ break;
+ case CHICKEN:
+ if (javaIdentifierStripped.contains("seeds")) {
+ interactiveTag = InteractiveTag.FEED;
+ }
+ break;
+ case MOOSHROOM:
+ // Shear the mooshroom
+ if (javaIdentifierStripped.equals("shears")) {
+ interactiveTag = InteractiveTag.MOOSHROOM_SHEAR;
+ break;
+ }
+ // Bowls are acceptable here
+ else if (javaIdentifierStripped.equals("bowl")) {
+ interactiveTag = InteractiveTag.MOOSHROOM_MILK_STEW;
+ break;
+ }
+ // Fall down to COW as this works on mooshrooms
+ case COW:
+ if (javaIdentifierStripped.equals("wheat")) {
+ interactiveTag = InteractiveTag.FEED;
+ } else if (javaIdentifierStripped.equals("bucket")) {
+ // Milk the cow
+ interactiveTag = InteractiveTag.MILK;
+ }
+ break;
+ case CREEPER:
+ if (javaIdentifierStripped.equals("flint_and_steel")) {
+ // Today I learned that you can ignite a creeper with flint and steel! Huh.
+ interactiveTag = InteractiveTag.IGNITE_CREEPER;
+ }
+ break;
+ case DONKEY:
+ case LLAMA:
+ case MULE:
+ if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED) && !entityMetadata.getFlags().getFlag(EntityFlag.CHESTED)
+ && javaIdentifierStripped.equals("chest")) {
+ // Can attach a chest
+ interactiveTag = InteractiveTag.ATTACH_CHEST;
+ break;
+ }
+ // Intentional fall-through
+ case HORSE:
+ case SKELETON_HORSE:
+ case TRADER_LLAMA:
+ case ZOMBIE_HORSE:
+ // have another switch statement as, while these share mount attributes they don't share food
+ switch (interactEntity.getEntityType()) {
+ case LLAMA:
+ case TRADER_LLAMA:
+ if (javaIdentifierStripped.equals("wheat") || javaIdentifierStripped.equals("hay_block")) {
+ interactiveTag = InteractiveTag.FEED;
+ break;
+ }
+ case DONKEY:
+ case HORSE:
+ // Undead can't eat
+ if (DONKEY_AND_HORSE_FOODS.contains(javaIdentifierStripped)) {
+ interactiveTag = InteractiveTag.FEED;
+ break;
+ }
+ }
+ if (!entityMetadata.getFlags().getFlag(EntityFlag.BABY)) {
+ // Can't ride a baby
+ if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED)) {
+ interactiveTag = InteractiveTag.RIDE_HORSE;
+ } else if (!entityMetadata.getFlags().getFlag(EntityFlag.TAMED) && itemEntry.equals(ItemEntry.AIR)) {
+ // Can't hide an untamed entity without having your hand empty
+ interactiveTag = InteractiveTag.MOUNT;
+ }
+ }
+ break;
+ case FOX:
+ if (javaIdentifierStripped.equals("sweet_berries")) {
+ interactiveTag = InteractiveTag.FEED;
+ }
+ break;
+ case HOGLIN:
+ if (javaIdentifierStripped.equals("crimson_fungus")) {
+ interactiveTag = InteractiveTag.FEED;
+ }
+ break;
+ case MINECART:
+ interactiveTag = InteractiveTag.RIDE_MINECART;
+ break;
+ case MINECART_CHEST:
+ case MINECART_COMMAND_BLOCK:
+ case MINECART_HOPPER:
+ interactiveTag = InteractiveTag.OPEN_CONTAINER;
+ break;
+ case OCELOT:
+ if (javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon")) {
+ interactiveTag = InteractiveTag.FEED;
+ }
+ break;
+ case PANDA:
+ if (javaIdentifierStripped.equals("bamboo")) {
+ interactiveTag = InteractiveTag.FEED;
+ }
+ break;
+ case PARROT:
+ if (javaIdentifierStripped.contains("seeds") || javaIdentifierStripped.equals("cookie")) {
+ interactiveTag = InteractiveTag.FEED;
+ }
+ break;
+ case PIG:
+ if (javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("potato") || javaIdentifierStripped.equals("beetroot")) {
+ interactiveTag = InteractiveTag.FEED;
+ } else if (entityMetadata.getFlags().getFlag(EntityFlag.SADDLED)) {
+ interactiveTag = InteractiveTag.MOUNT;
+ }
+ break;
+ case PIGLIN:
+ if (!entityMetadata.getFlags().getFlag(EntityFlag.BABY) && javaIdentifierStripped.equals("gold_ingot")) {
+ interactiveTag = InteractiveTag.BARTER;
+ }
+ break;
+ case RABBIT:
+ if (javaIdentifierStripped.equals("dandelion") || javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("golden_carrot")) {
+ interactiveTag = InteractiveTag.FEED;
+ }
+ break;
+ case SHEEP:
+ if (javaIdentifierStripped.equals("wheat")) {
+ interactiveTag = InteractiveTag.FEED;
+ } else if (!entityMetadata.getFlags().getFlag(EntityFlag.SHEARED)) {
+ if (javaIdentifierStripped.equals("shears")) {
+ // Shear the sheep
+ interactiveTag = InteractiveTag.SHEAR;
+ } else if (javaIdentifierStripped.contains("_dye")) {
+ // Dye the sheep
+ interactiveTag = InteractiveTag.DYE;
+ }
+ }
+ break;
+ case STRIDER:
+ if (javaIdentifierStripped.equals("warped_fungus")) {
+ interactiveTag = InteractiveTag.FEED;
+ } else if (entityMetadata.getFlags().getFlag(EntityFlag.SADDLED)) {
+ interactiveTag = InteractiveTag.RIDE_STRIDER;
+ }
+ break;
+ case TURTLE:
+ if (javaIdentifierStripped.equals("seagrass")) {
+ interactiveTag = InteractiveTag.FEED;
+ }
+ break;
+ case VILLAGER:
+ if (entityMetadata.getInt(EntityData.VARIANT) != 14 && entityMetadata.getInt(EntityData.VARIANT) != 0
+ && entityMetadata.getFloat(EntityData.SCALE) >= 0.75f) { // Not a nitwit, has a profession and is not a baby
+ interactiveTag = InteractiveTag.TRADE;
+ }
+ break;
+ case WANDERING_TRADER:
+ interactiveTag = InteractiveTag.TRADE; // Since you can always trade with a wandering villager, presumably.
+ break;
+ case WOLF:
+ if (javaIdentifierStripped.equals("bone") && !entityMetadata.getFlags().getFlag(EntityFlag.TAMED)) {
+ // Bone and untamed - can tame
+ interactiveTag = InteractiveTag.TAME;
+ } else if (WOLF_FOODS.contains(javaIdentifierStripped)) {
+ // Compatible food in hand - feed
+ // Sometimes just sits/stands when the wolf isn't hungry - there doesn't appear to be a way to fix this
+ interactiveTag = InteractiveTag.FEED;
+ } else if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED) &&
+ entityMetadata.getLong(EntityData.OWNER_EID) == session.getPlayerEntity().getGeyserId()) {
+ // Tamed and owned by player - can sit/stand
+ interactiveTag = entityMetadata.getFlags().getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
+ }
+ break;
+ case ZOMBIE_VILLAGER:
+ // We can't guarantee the existence of the weakness effect so we just always show it.
+ if (javaIdentifierStripped.equals("golden_apple")) {
+ interactiveTag = InteractiveTag.CURE;
+ }
+ break;
+ default:
+ break;
+ }
}
- session.getPlayerEntity().getMetadata().put(EntityData.INTERACTIVE_TAG, interactiveTag);
+ session.getPlayerEntity().getMetadata().put(EntityData.INTERACTIVE_TAG, interactiveTag.getValue());
session.getPlayerEntity().updateBedrockMetadata(session);
} else {
- if (!(session.getPlayerEntity().getMetadata().get(EntityData.INTERACTIVE_TAG) == null) ||
- !(session.getPlayerEntity().getMetadata().get(EntityData.INTERACTIVE_TAG) == "")) {
+ if (!session.getPlayerEntity().getMetadata().getString(EntityData.INTERACTIVE_TAG).isEmpty()) {
// No interactive tag should be sent
session.getPlayerEntity().getMetadata().remove(EntityData.INTERACTIVE_TAG);
session.getPlayerEntity().updateBedrockMetadata(session);
@@ -147,4 +367,65 @@ public class BedrockInteractTranslator extends PacketTranslator
break;
}
}
+
+ /**
+ * All interactive tags in enum form. For potential API usage.
+ */
+ public enum InteractiveTag {
+ NONE(true),
+ IGNITE_CREEPER("creeper"),
+ EDIT,
+ LEAVE_BOAT("exit.boat"),
+ FEED,
+ FISH("fishing"),
+ MILK,
+ MOOSHROOM_SHEAR("mooshear"),
+ MOOSHROOM_MILK_STEW("moostew"),
+ BOARD_BOAT("ride.boat"),
+ RIDE_MINECART("ride.minecart"),
+ RIDE_HORSE("ride.horse"),
+ RIDE_STRIDER("ride.strider"),
+ SHEAR,
+ SIT,
+ STAND,
+ TALK,
+ TAME,
+ DYE,
+ CURE,
+ OPEN_CONTAINER("opencontainer"),
+ CREATE_MAP("createMap"),
+ TAKE_PICTURE("takepicture"),
+ SADDLE,
+ MOUNT,
+ BOOST,
+ WRITE,
+ LEASH,
+ REMOVE_LEASH("unleash"),
+ NAME,
+ ATTACH_CHEST("attachchest"),
+ TRADE,
+ POSE_ARMOR_STAND("armorstand.pose"),
+ EQUIP_ARMOR_STAND("armorstand.equip"),
+ READ,
+ WAKE_VILLAGER("wakevillager"),
+ BARTER;
+
+ /**
+ * The full string that should be passed on to the client.
+ */
+ @Getter
+ private final String value;
+
+ InteractiveTag(boolean isNone) {
+ this.value = "";
+ }
+
+ InteractiveTag(String value) {
+ this.value = "action.interact." + value;
+ }
+
+ InteractiveTag() {
+ this.value = "action.interact." + name().toLowerCase();
+ }
+ }
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java
index 8809941b9..c5988bf0b 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/entity/player/BedrockMovePlayerTranslator.java
@@ -25,7 +25,13 @@
package org.geysermc.connector.network.translators.bedrock.entity.player;
+import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionPacket;
+import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket;
import com.nukkitx.math.vector.Vector3d;
+import com.nukkitx.math.vector.Vector3f;
+import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
+import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
+import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.entity.PlayerEntity;
@@ -34,11 +40,7 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
-import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket;
-import com.nukkitx.math.vector.Vector3f;
-import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
-import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
-import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
+import java.util.concurrent.TimeUnit;
@Translator(packet = MovePlayerPacket.class)
public class BedrockMovePlayerTranslator extends PacketTranslator {
@@ -59,13 +61,11 @@ public class BedrockMovePlayerTranslator extends PacketTranslator sendPositionIfIdle(session),
+ 3, TimeUnit.SECONDS));
+ }
+
+ /**
+ * Adjust the Bedrock position before sending to the Java server to account for inaccuracies in movement between
+ * the two versions.
+ *
+ * @param position the current Bedrock position of the client
+ * @param onGround whether the Bedrock player is on the ground
+ * @return the position to send to the Java server.
+ */
+ private Vector3d adjustBedrockPosition(Vector3f position, boolean onGround) {
+ // We need to parse the float as a string since casting a float to a double causes us to
+ // lose precision and thus, causes players to get stuck when walking near walls
+ double javaY = position.getY() - EntityType.PLAYER.getOffset();
+ if (onGround) javaY = Math.ceil(javaY * 2) / 2;
+
+ return Vector3d.from(Double.parseDouble(Float.toString(position.getX())), javaY,
+ Double.parseDouble(Float.toString(position.getZ())));
}
public boolean isValidMove(GeyserSession session, MovePlayerPacket.Mode mode, Vector3f currentPosition, Vector3f newPosition) {
@@ -147,4 +169,16 @@ public class BedrockMovePlayerTranslator extends PacketTranslator sendPositionIfIdle(session),
+ 3, TimeUnit.SECONDS));
+ }
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/chat/MessageTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/chat/MessageTranslator.java
new file mode 100644
index 000000000..be01362fa
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/chat/MessageTranslator.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.network.translators.chat;
+
+import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor;
+import com.github.steveice10.mc.protocol.data.message.style.ChatColor;
+import com.github.steveice10.mc.protocol.data.message.style.ChatFormat;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.renderer.TranslatableComponentRenderer;
+import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
+import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
+import net.kyori.adventure.translation.TranslationRegistry;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.utils.LanguageUtils;
+
+import java.util.*;
+
+public class MessageTranslator {
+
+ // These are used for handling the translations of the messages
+ private static final TranslationRegistry REGISTRY = new MinecraftTranslationRegistry();
+ private static final TranslatableComponentRenderer RENDERER = TranslatableComponentRenderer.usingTranslationSource(REGISTRY);
+
+ // Store team colors for player names
+ private static final Map TEAM_COLORS = new HashMap<>();
+
+ static {
+ TEAM_COLORS.put(TeamColor.BLACK, getColor(ChatColor.BLACK));
+ TEAM_COLORS.put(TeamColor.DARK_BLUE, getColor(ChatColor.DARK_BLUE));
+ TEAM_COLORS.put(TeamColor.DARK_GREEN, getColor(ChatColor.DARK_GREEN));
+ TEAM_COLORS.put(TeamColor.DARK_AQUA, getColor(ChatColor.DARK_AQUA));
+ TEAM_COLORS.put(TeamColor.DARK_RED, getColor(ChatColor.DARK_RED));
+ TEAM_COLORS.put(TeamColor.DARK_PURPLE, getColor(ChatColor.DARK_PURPLE));
+ TEAM_COLORS.put(TeamColor.GOLD, getColor(ChatColor.GOLD));
+ TEAM_COLORS.put(TeamColor.GRAY, getColor(ChatColor.GRAY));
+ TEAM_COLORS.put(TeamColor.DARK_GRAY, getColor(ChatColor.DARK_GRAY));
+ TEAM_COLORS.put(TeamColor.BLUE, getColor(ChatColor.BLUE));
+ TEAM_COLORS.put(TeamColor.GREEN, getColor(ChatColor.GREEN));
+ TEAM_COLORS.put(TeamColor.AQUA, getColor(ChatColor.AQUA));
+ TEAM_COLORS.put(TeamColor.RED, getColor(ChatColor.RED));
+ TEAM_COLORS.put(TeamColor.LIGHT_PURPLE, getColor(ChatColor.LIGHT_PURPLE));
+ TEAM_COLORS.put(TeamColor.YELLOW, getColor(ChatColor.YELLOW));
+ TEAM_COLORS.put(TeamColor.WHITE, getColor(ChatColor.WHITE));
+ TEAM_COLORS.put(TeamColor.OBFUSCATED, getFormat(ChatFormat.OBFUSCATED));
+ TEAM_COLORS.put(TeamColor.BOLD, getFormat(ChatFormat.BOLD));
+ TEAM_COLORS.put(TeamColor.STRIKETHROUGH, getFormat(ChatFormat.STRIKETHROUGH));
+ TEAM_COLORS.put(TeamColor.ITALIC, getFormat(ChatFormat.ITALIC));
+ }
+
+ /**
+ * Convert a Java message to the legacy format ready for bedrock
+ *
+ * @param message Java message
+ * @param locale Locale to use for translation strings
+ * @return Parsed and formatted message for bedrock
+ */
+ public static String convertMessage(String message, String locale) {
+ Component component = GsonComponentSerializer.gson().deserialize(message);
+
+ // Get a Locale from the given locale string
+ Locale localeCode = Locale.forLanguageTag(locale.replace('_', '-'));
+ component = RENDERER.render(component, localeCode);
+
+ return LegacyComponentSerializer.legacySection().serialize(component);
+ }
+
+ public static String convertMessage(String message) {
+ return convertMessage(message, LanguageUtils.getDefaultLocale());
+ }
+
+ /**
+ * Verifies the message is valid JSON in case it's plaintext. Works around GsonComponentSeraializer not using lenient mode.
+ * See https://wiki.vg/Chat for messages sent in lenient mode, and for a description on leniency.
+ *
+ * @param message Potentially lenient JSON message
+ * @param locale Locale to use for translation strings
+ * @return Bedrock formatted message
+ */
+ public static String convertMessageLenient(String message, String locale) {
+ if (isMessage(message)) {
+ return convertMessage(message, locale);
+ } else {
+ String convertedMessage = convertMessage(convertToJavaMessage(message), locale);
+
+ // We have to do this since Adventure strips the starting reset character
+ if (message.startsWith(getColor(ChatColor.RESET))) {
+ convertedMessage = getColor(ChatColor.RESET) + convertedMessage;
+ }
+
+ return convertedMessage;
+ }
+ }
+
+ public static String convertMessageLenient(String message) {
+ return convertMessageLenient(message, LanguageUtils.getDefaultLocale());
+ }
+
+ /**
+ * Convert a Bedrock message string back to a format Java can understand
+ *
+ * @param message Message to convert
+ * @return The formatted JSON string
+ */
+ public static String convertToJavaMessage(String message) {
+ Component component = LegacyComponentSerializer.legacySection().deserialize(message);
+ return GsonComponentSerializer.gson().serialize(component);
+ }
+
+ /**
+ * Checks if the given text string is a JSON message
+ *
+ * @param text String to test
+ * @return True if its a valid message JSON string, false if not
+ */
+ public static boolean isMessage(String text) {
+ if (text.trim().isEmpty()) {
+ return false;
+ }
+
+ try {
+ GsonComponentSerializer.gson().deserialize(text);
+ } catch (Exception ex) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Convert a {@link ChatColor} into a string for inserting into messages
+ *
+ * @param color {@link ChatColor} to convert
+ * @return The converted color string
+ */
+ private static String getColor(String color) {
+ String base = "\u00a7";
+ switch (color) {
+ case ChatColor.BLACK:
+ base += "0";
+ break;
+ case ChatColor.DARK_BLUE:
+ base += "1";
+ break;
+ case ChatColor.DARK_GREEN:
+ base += "2";
+ break;
+ case ChatColor.DARK_AQUA:
+ base += "3";
+ break;
+ case ChatColor.DARK_RED:
+ base += "4";
+ break;
+ case ChatColor.DARK_PURPLE:
+ base += "5";
+ break;
+ case ChatColor.GOLD:
+ base += "6";
+ break;
+ case ChatColor.GRAY:
+ base += "7";
+ break;
+ case ChatColor.DARK_GRAY:
+ base += "8";
+ break;
+ case ChatColor.BLUE:
+ base += "9";
+ break;
+ case ChatColor.GREEN:
+ base += "a";
+ break;
+ case ChatColor.AQUA:
+ base += "b";
+ break;
+ case ChatColor.RED:
+ base += "c";
+ break;
+ case ChatColor.LIGHT_PURPLE:
+ base += "d";
+ break;
+ case ChatColor.YELLOW:
+ base += "e";
+ break;
+ case ChatColor.WHITE:
+ base += "f";
+ break;
+ case ChatColor.RESET:
+ base += "r";
+ break;
+ default:
+ return "";
+ }
+
+ return base;
+ }
+
+ /**
+ * Convert a {@link ChatFormat} into a string for inserting into messages
+ *
+ * @param format {@link ChatFormat} to convert
+ * @return The converted chat formatting string
+ */
+ private static String getFormat(ChatFormat format) {
+ StringBuilder str = new StringBuilder();
+ String base = "\u00a7";
+ switch (format) {
+ case OBFUSCATED:
+ base += "k";
+ break;
+ case BOLD:
+ base += "l";
+ break;
+ case STRIKETHROUGH:
+ base += "m";
+ break;
+ case UNDERLINED:
+ base += "n";
+ break;
+ case ITALIC:
+ base += "o";
+ break;
+ default:
+ return "";
+ }
+
+ str.append(base);
+
+ return str.toString();
+ }
+
+ /**
+ * Convert a team color to a chat color
+ *
+ * @param teamColor
+ * @return The chat color character
+ */
+ public static String toChatColor(TeamColor teamColor) {
+ return TEAM_COLORS.getOrDefault(teamColor, "");
+ }
+
+ /**
+ * Checks if the given message is over 256 characters (Java edition server chat limit) and sends a message to the user if it is
+ *
+ * @param message Message to check
+ * @param session {@link GeyserSession} for the user
+ * @return True if the message is too long, false if not
+ */
+ public static boolean isTooLong(String message, GeyserSession session) {
+ if (message.length() > 256) {
+ session.sendMessage(LanguageUtils.getPlayerLocaleString("geyser.chat.too_long", session.getLocale(), message.length()));
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/chat/MinecraftTranslationRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/chat/MinecraftTranslationRegistry.java
new file mode 100644
index 000000000..a23167ac2
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/chat/MinecraftTranslationRegistry.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.network.translators.chat;
+
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.translation.TranslationRegistry;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.geysermc.connector.utils.LocaleUtils;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This class is used for mapping a translation key with the already loaded Java locale data
+ * Used in MessageTranslator.java as part of the KyoriPowered/Adventure library
+ */
+public class MinecraftTranslationRegistry implements TranslationRegistry {
+ @Override
+ public @NonNull Key name() {
+ return Key.key("", "");
+ }
+
+ @Override
+ public @Nullable MessageFormat translate(@NonNull String key, @NonNull Locale locale) {
+ // Get the locale string
+ String localeString = LocaleUtils.getLocaleString(key, locale.toString());
+
+ // Replace the `%s` with numbered inserts `{0}`
+ Pattern p = Pattern.compile("%s");
+ Matcher m = p.matcher(localeString);
+ StringBuffer sb = new StringBuffer();
+ int i = 0;
+ while (m.find()) {
+ m.appendReplacement(sb, "{" + (i++) + "}");
+ }
+ m.appendTail(sb);
+
+ return new MessageFormat(sb.toString(), locale);
+ }
+
+ @Override
+ public void defaultLocale(@NonNull Locale locale) {
+
+ }
+
+ @Override
+ public void register(@NonNull String key, @NonNull Locale locale, @NonNull MessageFormat format) {
+
+ }
+
+ @Override
+ public void unregister(@NonNull String key) {
+
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java
index 8aa91b360..20a47fd02 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/EnchantmentInventoryTranslator.java
@@ -42,6 +42,7 @@ import org.geysermc.connector.common.ChatColor;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater;
+import org.geysermc.connector.network.translators.item.ItemRegistry;
import org.geysermc.connector.network.translators.item.ItemTranslator;
import org.geysermc.connector.utils.InventoryUtils;
import org.geysermc.connector.utils.LocaleUtils;
@@ -57,9 +58,8 @@ import java.util.List;
*/
public class EnchantmentInventoryTranslator extends BlockInventoryTranslator {
- private static final int DYE_ID = 351;
- private static final short LAPIS_DAMAGE = 4;
- private static final int ENCHANTED_BOOK_ID = 403;
+ private static final int DYE_ID = ItemRegistry.getItemEntry("minecraft:lapis_lazuli").getBedrockId();
+ private static final int ENCHANTED_BOOK_ID = ItemRegistry.getItemEntry("minecraft:enchanted_book").getBedrockId();
public EnchantmentInventoryTranslator(InventoryUpdater updater) {
super(2, "minecraft:hopper[enabled=false,facing=down]", ContainerType.HOPPER, updater);
@@ -73,8 +73,7 @@ public class EnchantmentInventoryTranslator extends BlockInventoryTranslator {
switch (action.getSlot()) {
case 1:
// Don't allow the slot to be put through if the item isn't lapis
- if ((action.getToItem().getId() != DYE_ID
- && action.getToItem().getDamage() != LAPIS_DAMAGE) && action.getToItem() != ItemData.AIR) {
+ if ((action.getToItem().getId() != DYE_ID) && action.getToItem() != ItemData.AIR) {
updateInventory(session, inventory);
InventoryUtils.updateCursor(session);
return;
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java
index e44e4bd0b..3016871f0 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/InventoryTranslator.java
@@ -53,9 +53,9 @@ public abstract class InventoryTranslator {
put(WindowType.BREWING_STAND, new BrewingInventoryTranslator());
put(WindowType.ANVIL, new AnvilInventoryTranslator());
put(WindowType.CRAFTING, new CraftingInventoryTranslator());
- put(WindowType.GRINDSTONE, new GrindstoneInventoryTranslator());
+ //put(WindowType.GRINDSTONE, new GrindstoneInventoryTranslator()); //FIXME
put(WindowType.MERCHANT, new MerchantInventoryTranslator());
- put(WindowType.SMITHING, new SmithingInventoryTranslator());
+ //put(WindowType.SMITHING, new SmithingInventoryTranslator()); //TODO for server authoritative inventories
InventoryTranslator furnace = new FurnaceInventoryTranslator();
put(WindowType.FURNACE, furnace);
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java
index 19f83cd96..3fcae17db 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemEntry.java
@@ -34,9 +34,10 @@ import lombok.ToString;
@ToString
public class ItemEntry {
- public static ItemEntry AIR = new ItemEntry("minecraft:air", 0, 0, 0, false);
+ public static ItemEntry AIR = new ItemEntry("minecraft:air", "minecraft:air", 0, 0, 0, false);
private final String javaIdentifier;
+ private final String bedrockIdentifier;
private final int javaId;
private final int bedrockId;
private final int bedrockData;
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java
index 597c87b26..a4a2fb750 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemRegistry.java
@@ -34,6 +34,8 @@ import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.ints.IntArrayList;
+import it.unimi.dsi.fastutil.ints.IntList;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.utils.FileUtils;
import org.geysermc.connector.utils.LanguageUtils;
@@ -56,13 +58,21 @@ public class ItemRegistry {
public static final Int2ObjectMap ITEM_ENTRIES = new Int2ObjectOpenHashMap<>();
/**
- * Boat item entry, used in BedrockInventoryTransactionTranslator.java
+ * Bamboo item entry, used in PandaEntity.java
*/
- public static ItemEntry BOAT;
+ public static ItemEntry BAMBOO;
/**
- * Bucket item entry, used in BedrockInventoryTransactionTranslator.java
+ * Boat item entries, used in BedrockInventoryTransactionTranslator.java
*/
- public static ItemEntry BUCKET;
+ public static IntList BOATS = new IntArrayList();
+ /**
+ * Bucket item entries (excluding the milk bucket), used in BedrockInventoryTransactionTranslator.java
+ */
+ public static IntList BUCKETS = new IntArrayList();
+ /**
+ * Empty item bucket, used in BedrockInventoryTransactionTranslator.java
+ */
+ public static ItemEntry MILK_BUCKET;
/**
* Egg item entry, used in JavaEntityStatusTranslator.java
*/
@@ -75,6 +85,10 @@ public class ItemRegistry {
* Shield item entry, used in Entity.java and LivingEntity.java
*/
public static ItemEntry SHIELD;
+ /**
+ * Wheat item entry, used in AbstractHorseEntity.java
+ */
+ public static ItemEntry WHEAT;
public static int BARRIER_INDEX = 0;
@@ -84,11 +98,14 @@ public class ItemRegistry {
static {
/* Load item palette */
- InputStream stream = FileUtils.getResource("bedrock/items.json");
+ InputStream stream = FileUtils.getResource("bedrock/runtime_item_states.json");
TypeReference> itemEntriesType = new TypeReference>() {
};
+ // Used to get the Bedrock namespaced ID (in instances where there are small differences)
+ Int2ObjectMap bedrockIdToIdentifier = new Int2ObjectOpenHashMap<>();
+
List itemEntries;
try {
itemEntries = GeyserConnector.JSON_MAPPER.readValue(stream, itemEntriesType);
@@ -96,8 +113,14 @@ public class ItemRegistry {
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_bedrock"), e);
}
+ int lodestoneCompassId = 0;
+
for (JsonNode entry : itemEntries) {
ITEMS.add(new StartGamePacket.ItemEntry(entry.get("name").textValue(), (short) entry.get("id").intValue()));
+ bedrockIdToIdentifier.put(entry.get("id").intValue(), entry.get("name").textValue());
+ if (entry.get("name").textValue().equals("minecraft:lodestone_compass")) {
+ lodestoneCompassId = entry.get("id").intValue();
+ }
}
stream = FileUtils.getResource("mappings/items.json");
@@ -113,28 +136,29 @@ public class ItemRegistry {
Iterator> iterator = items.fields();
while (iterator.hasNext()) {
Map.Entry entry = iterator.next();
+ int bedrockId = entry.getValue().get("bedrock_id").intValue();
+ String bedrockIdentifier = bedrockIdToIdentifier.get(bedrockId);
+ if (bedrockIdentifier == null) {
+ throw new RuntimeException("Missing Bedrock ID in mappings!: " + bedrockId);
+ }
if (entry.getValue().has("tool_type")) {
if (entry.getValue().has("tool_tier")) {
ITEM_ENTRIES.put(itemIndex, new ToolItemEntry(
- entry.getKey(), itemIndex,
- entry.getValue().get("bedrock_id").intValue(),
+ entry.getKey(), bedrockIdentifier, itemIndex, bedrockId,
entry.getValue().get("bedrock_data").intValue(),
entry.getValue().get("tool_type").textValue(),
entry.getValue().get("tool_tier").textValue(),
entry.getValue().get("is_block") != null && entry.getValue().get("is_block").booleanValue()));
} else {
ITEM_ENTRIES.put(itemIndex, new ToolItemEntry(
- entry.getKey(), itemIndex,
- entry.getValue().get("bedrock_id").intValue(),
+ entry.getKey(), bedrockIdentifier, itemIndex, bedrockId,
entry.getValue().get("bedrock_data").intValue(),
entry.getValue().get("tool_type").textValue(),
- "",
- entry.getValue().get("is_block").booleanValue()));
+ "", entry.getValue().get("is_block").booleanValue()));
}
} else {
ITEM_ENTRIES.put(itemIndex, new ItemEntry(
- entry.getKey(), itemIndex,
- entry.getValue().get("bedrock_id").intValue(),
+ entry.getKey(), bedrockIdentifier, itemIndex, bedrockId,
entry.getValue().get("bedrock_data").intValue(),
entry.getValue().get("is_block") != null && entry.getValue().get("is_block").booleanValue()));
}
@@ -142,8 +166,8 @@ public class ItemRegistry {
case "minecraft:barrier":
BARRIER_INDEX = itemIndex;
break;
- case "minecraft:oak_boat":
- BOAT = ITEM_ENTRIES.get(itemIndex);
+ case "minecraft:bamboo":
+ BAMBOO = ITEM_ENTRIES.get(itemIndex);
break;
case "minecraft:egg":
EGG = ITEM_ENTRIES.get(itemIndex);
@@ -154,18 +178,32 @@ public class ItemRegistry {
case "minecraft:shield":
SHIELD = ITEM_ENTRIES.get(itemIndex);
break;
- case "minecraft:bucket":
- BUCKET = ITEM_ENTRIES.get(itemIndex);
+ case "minecraft:milk_bucket":
+ MILK_BUCKET = ITEM_ENTRIES.get(itemIndex);
+ break;
+ case "minecraft:wheat":
+ WHEAT = ITEM_ENTRIES.get(itemIndex);
break;
default:
break;
}
+ if (entry.getKey().contains("boat")) {
+ BOATS.add(entry.getValue().get("bedrock_id").intValue());
+ } else if (entry.getKey().contains("bucket") && !entry.getKey().contains("milk")) {
+ BUCKETS.add(entry.getValue().get("bedrock_id").intValue());
+ }
+
itemIndex++;
}
- // Add the loadstonecompass since it doesn't exist on java but we need it for item conversion
- ITEM_ENTRIES.put(itemIndex, new ItemEntry("minecraft:lodestonecompass", itemIndex, 741, 0, false));
+ if (lodestoneCompassId == 0) {
+ throw new RuntimeException("Lodestone compass not found in item palette!");
+ }
+
+ // Add the loadstone compass since it doesn't exist on java but we need it for item conversion
+ ITEM_ENTRIES.put(itemIndex, new ItemEntry("minecraft:lodestone_compass", "minecraft:lodestone_compass", itemIndex,
+ lodestoneCompassId, 0, false));
/* Load creative items */
stream = FileUtils.getResource("bedrock/creative_items.json");
@@ -226,25 +264,14 @@ public class ItemRegistry {
* @return an item entry from the given java edition identifier
*/
public static ItemEntry getItemEntry(String javaIdentifier) {
- return JAVA_IDENTIFIER_MAP.computeIfAbsent(javaIdentifier, key -> ITEM_ENTRIES.values()
- .stream().filter(itemEntry -> itemEntry.getJavaIdentifier().equals(key)).findFirst().orElse(null));
- }
-
- /**
- * Finds the Bedrock string identifier of an ItemEntry
- *
- * @param entry the ItemEntry to search for
- * @return the Bedrock identifier
- */
- public static String getBedrockIdentifer(ItemEntry entry) {
- String blockName = "";
- for (StartGamePacket.ItemEntry startGamePacketItemEntry : ItemRegistry.ITEMS) {
- if (startGamePacketItemEntry.getId() == (short) entry.getBedrockId()) {
- blockName = startGamePacketItemEntry.getIdentifier(); // Find the Bedrock string name
- break;
+ return JAVA_IDENTIFIER_MAP.computeIfAbsent(javaIdentifier, key -> {
+ for (ItemEntry entry : ITEM_ENTRIES.values()) {
+ if (entry.getJavaIdentifier().equals(key)) {
+ return entry;
+ }
}
- }
- return blockName;
+ return null;
+ });
}
/**
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java
index f95a0ccc6..0df179cf4 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java
@@ -26,7 +26,6 @@
package org.geysermc.connector.network.translators.item;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
-import com.github.steveice10.mc.protocol.data.message.MessageSerializer;
import com.github.steveice10.opennbt.tag.builtin.*;
import com.nukkitx.nbt.NbtList;
import com.nukkitx.nbt.NbtMap;
@@ -35,23 +34,19 @@ import com.nukkitx.nbt.NbtType;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
-import net.kyori.adventure.text.Component;
-import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
-import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.ItemRemapper;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.utils.FileUtils;
import org.geysermc.connector.utils.LanguageUtils;
-import org.geysermc.connector.utils.MessageUtils;
import org.reflections.Reflections;
import java.util.*;
import java.util.stream.Collectors;
public abstract class ItemTranslator {
-
private static final Int2ObjectMap ITEM_STACK_TRANSLATORS = new Int2ObjectOpenHashMap<>();
private static final List NBT_TRANSLATORS;
@@ -220,7 +215,7 @@ public abstract class ItemTranslator {
public abstract List getAppliedItems();
public NbtMap translateNbtToBedrock(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag) {
- Map javaValue = new HashMap<>();
+ NbtMapBuilder builder = NbtMap.builder();
if (tag.getValue() != null && !tag.getValue().isEmpty()) {
for (String str : tag.getValue().keySet()) {
com.github.steveice10.opennbt.tag.builtin.Tag javaTag = tag.get(str);
@@ -228,11 +223,9 @@ public abstract class ItemTranslator {
if (translatedTag == null)
continue;
- javaValue.put(javaTag.getName(), translatedTag);
+ builder.put(javaTag.getName(), translatedTag);
}
}
- NbtMapBuilder builder = NbtMap.builder();
- javaValue.forEach(builder::put);
return builder.build();
}
@@ -388,26 +381,17 @@ public abstract class ItemTranslator {
public static void translateDisplayProperties(GeyserSession session, CompoundTag tag) {
if (tag != null) {
CompoundTag display = tag.get("display");
- if (display != null && !display.isEmpty() && display.contains("Name")) {
+ if (display != null && display.contains("Name")) {
String name = ((StringTag) display.get("Name")).getValue();
- // If its not a message convert it
- if (!MessageUtils.isMessage(name)) {
- Component component = LegacyComponentSerializer.legacySection().deserialize(name);
- name = GsonComponentSerializer.gson().serialize(component);
- }
+ // Get the translated name and prefix it with a reset char
+ name = MessageTranslator.convertMessageLenient(name, session.getLocale());
- // Check if its a message to translate
- if (MessageUtils.isMessage(name)) {
- // Get the translated name
- name = MessageUtils.getTranslatedBedrockMessage(MessageSerializer.fromString(name), session.getLocale());
+ // Add the new name tag
+ display.put(new StringTag("Name", name));
- // Add the new name tag
- display.put(new StringTag("Name", name));
-
- // Add to the new root tag
- tag.put(display);
- }
+ // Add to the new root tag
+ tag.put(display);
}
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java
index 10edcdec8..dde577005 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ToolItemEntry.java
@@ -32,8 +32,8 @@ public class ToolItemEntry extends ItemEntry {
private final String toolType;
private final String toolTier;
- public ToolItemEntry(String javaIdentifier, int javaId, int bedrockId, int bedrockData, String toolType, String toolTier, boolean isBlock) {
- super(javaIdentifier, javaId, bedrockId, bedrockData, isBlock);
+ public ToolItemEntry(String javaIdentifier, String bedrockIdentifier, int javaId, int bedrockId, int bedrockData, String toolType, String toolTier, boolean isBlock) {
+ super(javaIdentifier, bedrockIdentifier, javaId, bedrockId, bedrockData, isBlock);
this.toolType = toolType;
this.toolTier = toolTier;
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java
index f4bfdfb64..14b934362 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/BannerTranslator.java
@@ -26,20 +26,16 @@
package org.geysermc.connector.network.translators.item.translators;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
-import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
-import com.github.steveice10.opennbt.tag.builtin.IntTag;
-import com.github.steveice10.opennbt.tag.builtin.ListTag;
-import com.github.steveice10.opennbt.tag.builtin.StringTag;
-import com.github.steveice10.opennbt.tag.builtin.Tag;
+import com.github.steveice10.opennbt.tag.builtin.*;
import com.nukkitx.nbt.NbtList;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.connector.network.translators.ItemRemapper;
+import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ItemRegistry;
import org.geysermc.connector.network.translators.item.ItemTranslator;
-import org.geysermc.connector.network.translators.item.ItemEntry;
import java.util.ArrayList;
import java.util.HashMap;
@@ -49,54 +45,13 @@ import java.util.stream.Collectors;
@ItemRemapper
public class BannerTranslator extends ItemTranslator {
-
private final List appliedItems;
public BannerTranslator() {
- appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("banner")).collect(Collectors.toList());
- }
-
- @Override
- public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) {
- if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, itemEntry);
-
- ItemData itemData = super.translateToBedrock(itemStack, itemEntry);
-
- CompoundTag blockEntityTag = itemStack.getNbt().get("BlockEntityTag");
- if (blockEntityTag.contains("Patterns")) {
- ListTag patterns = blockEntityTag.get("Patterns");
-
- NbtMapBuilder builder = itemData.getTag().toBuilder();
- builder.put("Patterns", convertBannerPattern(patterns));
-
- itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.build());
- }
-
- return itemData;
- }
-
- @Override
- public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) {
- if (itemData.getTag() == null) return super.translateToJava(itemData, itemEntry);
-
- ItemStack itemStack = super.translateToJava(itemData, itemEntry);
-
- NbtMap nbtTag = itemData.getTag();
- if (nbtTag.containsKey("Patterns", NbtType.COMPOUND)) {
- List patterns = nbtTag.getList("Patterns", NbtType.COMPOUND);
-
- CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag");
- blockEntityTag.put(convertBannerPattern(patterns));
-
- itemStack.getNbt().put(blockEntityTag);
- }
-
- return itemStack;
- }
-
- @Override
- public List getAppliedItems() {
- return appliedItems;
+ appliedItems = ItemRegistry.ITEM_ENTRIES.values()
+ .stream()
+ .filter(entry -> entry.getJavaIdentifier().endsWith("banner"))
+ .collect(Collectors.toList());
}
/**
@@ -133,7 +88,6 @@ public class BannerTranslator extends ItemTranslator {
return NbtMap.builder()
.putInt("Color", 15 - (int) pattern.get("Color").getValue())
- .putString("Pattern", (String) pattern.get("Pattern").getValue())
.putString("Pattern", patternName)
.build();
}
@@ -147,8 +101,7 @@ public class BannerTranslator extends ItemTranslator {
public static ListTag convertBannerPattern(List patterns) {
List tagsList = new ArrayList<>();
for (Object patternTag : patterns) {
- CompoundTag newPatternTag = getJavaBannerPattern((NbtMap) patternTag);
- tagsList.add(newPatternTag);
+ tagsList.add(getJavaBannerPattern((NbtMap) patternTag));
}
return new ListTag("Patterns", tagsList);
@@ -167,4 +120,51 @@ public class BannerTranslator extends ItemTranslator {
return new CompoundTag("", tags);
}
+
+ @Override
+ public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) {
+ if (itemStack.getNbt() == null) {
+ return super.translateToBedrock(itemStack, itemEntry);
+ }
+
+ ItemData itemData = super.translateToBedrock(itemStack, itemEntry);
+
+ CompoundTag blockEntityTag = itemStack.getNbt().get("BlockEntityTag");
+ if (blockEntityTag != null && blockEntityTag.contains("Patterns")) {
+ ListTag patterns = blockEntityTag.get("Patterns");
+
+ NbtMapBuilder builder = itemData.getTag().toBuilder();
+ builder.put("Patterns", convertBannerPattern(patterns));
+
+ itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.build());
+ }
+
+ return itemData;
+ }
+
+ @Override
+ public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) {
+ if (itemData.getTag() == null) {
+ return super.translateToJava(itemData, itemEntry);
+ }
+
+ ItemStack itemStack = super.translateToJava(itemData, itemEntry);
+
+ NbtMap nbtTag = itemData.getTag();
+ if (nbtTag.containsKey("Patterns", NbtType.COMPOUND)) {
+ List patterns = nbtTag.getList("Patterns", NbtType.COMPOUND);
+
+ CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag");
+ blockEntityTag.put(convertBannerPattern(patterns));
+
+ itemStack.getNbt().put(blockEntityTag);
+ }
+
+ return itemStack;
+ }
+
+ @Override
+ public List getAppliedItems() {
+ return appliedItems;
+ }
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/CompassTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/CompassTranslator.java
index 159b9ab49..92ec67dd4 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/CompassTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/CompassTranslator.java
@@ -53,7 +53,7 @@ public class CompassTranslator extends ItemTranslator {
Tag lodestoneTag = itemStack.getNbt().get("LodestoneTracked");
if (lodestoneTag instanceof ByteTag) {
// Get the fake lodestonecompass entry
- itemEntry = ItemRegistry.getItemEntry("minecraft:lodestonecompass");
+ itemEntry = ItemRegistry.getItemEntry("minecraft:lodestone_compass");
// Get the loadstone pos
CompoundTag loadstonePos = itemStack.getNbt().get("LodestonePos");
@@ -83,7 +83,7 @@ public class CompassTranslator extends ItemTranslator {
@Override
public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) {
boolean isLoadstone = false;
- if (itemEntry.getJavaIdentifier().equals("minecraft:lodestonecompass")) {
+ if (itemEntry.getBedrockIdentifier().equals("minecraft:lodestone_compass")) {
// Revert the entry back to the compass
itemEntry = ItemRegistry.getItemEntry("minecraft:compass");
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java
index 1d21bbfb7..3fd9df8a0 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BasicItemTranslator.java
@@ -37,7 +37,6 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.ItemRemapper;
import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.NbtItemStackTranslator;
-import org.geysermc.connector.utils.MessageUtils;
import java.util.ArrayList;
import java.util.List;
@@ -108,7 +107,7 @@ public class BasicItemTranslator extends NbtItemStackTranslator {
private String toBedrockMessage(StringTag tag) {
String message = tag.getValue();
if (message == null) return null;
- TextComponent component = (TextComponent) MessageUtils.phraseJavaMessage(message);
+ TextComponent component = (TextComponent) GsonComponentSerializer.gson().deserialize(message);
String legacy = LegacyComponentSerializer.legacySection().serialize(component);
if (hasFormatting(LegacyComponentSerializer.legacySection().deserialize(legacy))) {
return "§r" + legacy;
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java
index 41ee4fbca..294dd81ed 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/BookPagesTranslator.java
@@ -33,7 +33,7 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.ItemRemapper;
import org.geysermc.connector.network.translators.item.NbtItemStackTranslator;
import org.geysermc.connector.network.translators.item.ItemEntry;
-import org.geysermc.connector.utils.MessageUtils;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
import java.util.ArrayList;
import java.util.List;
@@ -56,7 +56,7 @@ public class BookPagesTranslator extends NbtItemStackTranslator {
CompoundTag pageTag = new CompoundTag("");
pageTag.put(new StringTag("photoname", ""));
- pageTag.put(new StringTag("text", MessageUtils.getBedrockMessageLenient(textTag.getValue())));
+ pageTag.put(new StringTag("text", MessageTranslator.convertMessageLenient(textTag.getValue())));
pages.add(pageTag);
}
@@ -78,7 +78,7 @@ public class BookPagesTranslator extends NbtItemStackTranslator {
CompoundTag pageTag = (CompoundTag) tag;
StringTag textTag = pageTag.get("text");
- pages.add(new StringTag(MessageUtils.getJavaMessage(textTag.getValue())));
+ pages.add(new StringTag(MessageTranslator.convertToJavaMessage(textTag.getValue())));
}
itemTag.remove("pages");
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java
index 67f137ff9..97da86696 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/CrossbowTranslator.java
@@ -45,15 +45,15 @@ public class CrossbowTranslator extends NbtItemStackTranslator {
if (!chargedProjectiles.getValue().isEmpty()) {
CompoundTag projectile = (CompoundTag) chargedProjectiles.getValue().get(0);
- ItemEntry entry = ItemRegistry.getItemEntry((String) projectile.get("id").getValue());
- if (entry == null) return;
+ ItemEntry projectileEntry = ItemRegistry.getItemEntry((String) projectile.get("id").getValue());
+ if (projectileEntry == null) return;
CompoundTag tag = projectile.get("tag");
ItemStack itemStack = new ItemStack(itemEntry.getJavaId(), (byte) projectile.get("Count").getValue(), tag);
ItemData itemData = ItemTranslator.translateToBedrock(session, itemStack);
CompoundTag newProjectile = new CompoundTag("chargedItem");
newProjectile.put(new ByteTag("Count", (byte) itemData.getCount()));
- newProjectile.put(new StringTag("Name", ItemRegistry.getBedrockIdentifer(entry)));
+ newProjectile.put(new StringTag("Name", projectileEntry.getBedrockIdentifier()));
newProjectile.put(new ShortTag("Damage", itemData.getDamage()));
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java
index c9b49efd4..d325af486 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java
@@ -25,10 +25,7 @@
package org.geysermc.connector.network.translators.item.translators.nbt;
-import com.github.steveice10.opennbt.tag.builtin.ByteTag;
-import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
-import com.github.steveice10.opennbt.tag.builtin.IntTag;
-import com.github.steveice10.opennbt.tag.builtin.LongTag;
+import com.github.steveice10.opennbt.tag.builtin.*;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.ItemRemapper;
import org.geysermc.connector.network.translators.item.ItemEntry;
@@ -39,14 +36,22 @@ public class MapItemTranslator extends NbtItemStackTranslator {
@Override
public void translateToBedrock(GeyserSession session, CompoundTag itemTag, ItemEntry itemEntry) {
- IntTag mapId = itemTag.get("map");
+ // Can be either an IntTag or ShortTag
+ Tag mapId = itemTag.get("map");
+ if (mapId == null) return;
- if (mapId != null) {
- itemTag.put(new LongTag("map_uuid", mapId.getValue()));
- itemTag.put(new IntTag("map_name_index", mapId.getValue()));
- itemTag.put(new ByteTag("map_display_players", (byte) 1));
- itemTag.remove("map");
+ int mapValue;
+ if (mapId.getValue() instanceof Short) {
+ // Convert to int if necessary
+ mapValue = (int) (short) mapId.getValue();
+ } else {
+ mapValue = (int) mapId.getValue();
}
+
+ itemTag.put(new LongTag("map_uuid", mapValue));
+ itemTag.put(new IntTag("map_name_index", mapValue));
+ itemTag.put(new ByteTag("map_display_players", (byte) 1));
+ itemTag.remove("map");
}
@Override
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/ShulkerBoxItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/ShulkerBoxItemTranslator.java
index a9930f698..126d2e1f5 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/ShulkerBoxItemTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/ShulkerBoxItemTranslator.java
@@ -50,9 +50,8 @@ public class ShulkerBoxItemTranslator extends NbtItemStackTranslator {
boxItemTag.put(new ByteTag("WasPickedUp", (byte) 0)); // ???
ItemEntry boxItemEntry = ItemRegistry.getItemEntry(((StringTag) itemData.get("id")).getValue());
- String blockName = ItemRegistry.getBedrockIdentifer(boxItemEntry);
- boxItemTag.put(new StringTag("Name", blockName));
+ boxItemTag.put(new StringTag("Name", boxItemEntry.getBedrockIdentifier()));
boxItemTag.put(new ShortTag("Damage", (short) boxItemEntry.getBedrockData()));
boxItemTag.put(new ByteTag("Count", ((ByteTag) itemData.get("Count")).getValue()));
if (itemData.contains("tag")) {
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java
index 186aaf660..f5128ed6f 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaChatTranslator.java
@@ -25,15 +25,12 @@
package org.geysermc.connector.network.translators.java;
-import com.github.steveice10.mc.protocol.data.message.TranslationMessage;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerChatPacket;
import com.nukkitx.protocol.bedrock.packet.TextPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
-import org.geysermc.connector.utils.MessageUtils;
-
-import java.util.List;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
@Translator(packet = ServerChatPacket.class)
public class JavaChatTranslator extends PacketTranslator {
@@ -59,21 +56,8 @@ public class JavaChatTranslator extends PacketTranslator {
break;
}
- String locale = session.getLocale();
-
- if (packet.getMessage() instanceof TranslationMessage) {
- textPacket.setType(TextPacket.Type.TRANSLATION);
- textPacket.setNeedsTranslation(true);
-
- List paramsTranslated = MessageUtils.getTranslationParams(((TranslationMessage) packet.getMessage()).getWith(), locale, packet.getMessage());
- textPacket.setParameters(paramsTranslated);
-
- textPacket.setMessage(MessageUtils.insertParams(MessageUtils.getTranslatedBedrockMessage(packet.getMessage(), locale, true, packet.getMessage()), paramsTranslated));
- } else {
- textPacket.setNeedsTranslation(false);
-
- textPacket.setMessage(MessageUtils.getTranslatedBedrockMessage(packet.getMessage(), locale, false, packet.getMessage()));
- }
+ textPacket.setNeedsTranslation(false);
+ textPacket.setMessage(MessageTranslator.convertMessage(packet.getMessage().toString(), session.getLocale()));
session.sendUpstreamPacket(textPacket);
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDisconnectPacket.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDisconnectPacket.java
index f36da367b..1945a8e10 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDisconnectPacket.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDisconnectPacket.java
@@ -29,13 +29,13 @@ import com.github.steveice10.mc.protocol.packet.ingame.server.ServerDisconnectPa
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
-import org.geysermc.connector.utils.MessageUtils;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
@Translator(packet = ServerDisconnectPacket.class)
public class JavaDisconnectPacket extends PacketTranslator {
@Override
public void translate(ServerDisconnectPacket packet, GeyserSession session) {
- session.disconnect(MessageUtils.getTranslatedBedrockMessage(packet.getReason(), session.getLocale(), true));
+ session.disconnect(MessageTranslator.convertMessage(packet.getReason().toString(), session.getLocale()));
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java
index c0207841d..6f489979c 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java
@@ -55,7 +55,7 @@ public class JavaJoinGameTranslator extends PacketTranslator {
@@ -37,6 +37,6 @@ public class JavaLoginDisconnectTranslator extends PacketTranslator
}
String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
- if (!entity.getDimension().equals(newDimension)) {
+ if (!session.getDimension().equals(newDimension)) {
DimensionUtils.switchDimension(session, newDimension);
} else {
if (session.isManyDimPackets()) { //reloading world
- String fakeDim = entity.getDimension().equals(DimensionUtils.OVERWORLD) ? DimensionUtils.NETHER : DimensionUtils.OVERWORLD;
+ String fakeDim = session.getDimension().equals(DimensionUtils.OVERWORLD) ? DimensionUtils.NETHER : DimensionUtils.OVERWORLD;
DimensionUtils.switchDimension(session, fakeDim);
DimensionUtils.switchDimension(session, newDimension);
} else {
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaTitleTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaTitleTranslator.java
index 12ef10d0a..7fe4d7b31 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaTitleTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaTitleTranslator.java
@@ -28,7 +28,7 @@ package org.geysermc.connector.network.translators.java;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
-import org.geysermc.connector.utils.MessageUtils;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerTitlePacket;
import com.nukkitx.protocol.bedrock.packet.SetTitlePacket;
@@ -41,14 +41,21 @@ public class JavaTitleTranslator extends PacketTranslator {
SetTitlePacket titlePacket = new SetTitlePacket();
String locale = session.getLocale();
+ String text;
+ if (packet.getTitle() == null) {
+ text = " ";
+ } else {
+ text = MessageTranslator.convertMessage(packet.getTitle().toString(), locale);
+ }
+
switch (packet.getAction()) {
case TITLE:
titlePacket.setType(SetTitlePacket.Type.TITLE);
- titlePacket.setText(MessageUtils.getTranslatedBedrockMessage(packet.getTitle(), locale));
+ titlePacket.setText(text);
break;
case SUBTITLE:
titlePacket.setType(SetTitlePacket.Type.SUBTITLE);
- titlePacket.setText(MessageUtils.getTranslatedBedrockMessage(packet.getTitle(), locale));
+ titlePacket.setText(text);
break;
case CLEAR:
case RESET:
@@ -57,9 +64,10 @@ public class JavaTitleTranslator extends PacketTranslator {
break;
case ACTION_BAR:
titlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
- titlePacket.setText(MessageUtils.getTranslatedBedrockMessage(packet.getTitle(), locale));
+ titlePacket.setText(text);
break;
case TIMES:
+ titlePacket.setType(SetTitlePacket.Type.TIMES);
titlePacket.setFadeInTime(packet.getFadeIn());
titlePacket.setFadeOutTime(packet.getFadeOut());
titlePacket.setStayTime(packet.getStay());
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAttachTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAttachTranslator.java
index b642a75ba..1a6630efa 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAttachTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityAttachTranslator.java
@@ -62,7 +62,7 @@ public class JavaEntityAttachTranslator extends PacketTranslator {
@@ -141,9 +137,15 @@ public class JavaEntityStatusTranslator extends PacketTranslator {
switch (packet.getAction()) {
case CREATE:
scoreboard.registerNewTeam(packet.getTeamName(), toPlayerSet(packet.getPlayers()))
- .setName(MessageUtils.getBedrockMessage(packet.getDisplayName()))
+ .setName(MessageTranslator.convertMessage(packet.getDisplayName().toString()))
.setColor(packet.getColor())
.setNameTagVisibility(packet.getNameTagVisibility())
- .setPrefix(MessageUtils.getTranslatedBedrockMessage(packet.getPrefix(), session.getLocale()))
- .setSuffix(MessageUtils.getTranslatedBedrockMessage(packet.getSuffix(), session.getLocale()));
+ .setPrefix(MessageTranslator.convertMessage(packet.getPrefix().toString(), session.getLocale()))
+ .setSuffix(MessageTranslator.convertMessage(packet.getSuffix().toString(), session.getLocale()));
break;
case UPDATE:
if (team == null) {
@@ -74,11 +74,11 @@ public class JavaTeamTranslator extends PacketTranslator {
return;
}
- team.setName(MessageUtils.getBedrockMessage(packet.getDisplayName()))
+ team.setName(MessageTranslator.convertMessage(packet.getDisplayName().toString()))
.setColor(packet.getColor())
.setNameTagVisibility(packet.getNameTagVisibility())
- .setPrefix(MessageUtils.getTranslatedBedrockMessage(packet.getPrefix(), session.getLocale()))
- .setSuffix(MessageUtils.getTranslatedBedrockMessage(packet.getSuffix(), session.getLocale()))
+ .setPrefix(MessageTranslator.convertMessage(packet.getPrefix().toString(), session.getLocale()))
+ .setSuffix(MessageTranslator.convertMessage(packet.getSuffix().toString(), session.getLocale()))
.setUpdateType(UpdateType.UPDATE);
break;
case ADD_PLAYER:
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java
index 2c10ded60..1fb088717 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/window/JavaOpenWindowTranslator.java
@@ -25,7 +25,6 @@
package org.geysermc.connector.network.translators.java.window;
-import com.github.steveice10.mc.protocol.data.message.MessageSerializer;
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCloseWindowPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.window.ServerOpenWindowPacket;
import org.geysermc.connector.inventory.Inventory;
@@ -35,7 +34,7 @@ import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
import org.geysermc.connector.utils.InventoryUtils;
import org.geysermc.connector.utils.LocaleUtils;
-import org.geysermc.connector.utils.MessageUtils;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
@Translator(packet = ServerOpenWindowPacket.class)
public class JavaOpenWindowTranslator extends PacketTranslator {
@@ -57,8 +56,7 @@ public class JavaOpenWindowTranslator extends PacketTranslator 0 ? 1 : 0);
session.sendUpstreamPacket(blockEventPacket);
- }
- if (packet.getValue() instanceof EndGatewayValue) {
+ } else if (packet.getValue() instanceof EndGatewayValue) {
blockEventPacket.setEventType(1);
session.sendUpstreamPacket(blockEventPacket);
- }
- if (packet.getValue() instanceof NoteBlockValue) {
+ } else if (packet.getValue() instanceof NoteBlockValue) {
NoteblockBlockEntityTranslator.translate(session, packet.getPosition());
- return;
- }
- if (packet.getValue() instanceof PistonValue) {
+ } else if (packet.getValue() instanceof PistonValue) {
PistonValueType type = (PistonValueType) packet.getType();
// Unlike everything else, pistons need a block entity packet to convey motion
@@ -73,14 +70,46 @@ public class JavaBlockValueTranslator extends PacketTranslator {
-
/**
* Determines if we should process non-full chunks
*/
- private final boolean isCacheChunks;
+ private final boolean cacheChunks;
public JavaChunkDataTranslator() {
- isCacheChunks = GeyserConnector.getInstance().getConfig().isCacheChunks();
+ cacheChunks = GeyserConnector.getInstance().getConfig().isCacheChunks();
}
@Override
@@ -61,7 +60,7 @@ public class JavaChunkDataTranslator extends PacketTranslator
boolean shouldStore = false;
mapItemDataPacket.setUniqueMapId(packet.getMapId());
- mapItemDataPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getPlayerEntity().getDimension()));
+ mapItemDataPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
mapItemDataPacket.setLocked(packet.isLocked());
mapItemDataPacket.setScale(packet.getScale());
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java
index 1e102a606..26ecb1e1f 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaNotifyClientTranslator.java
@@ -103,13 +103,13 @@ public class JavaNotifyClientTranslator extends PacketTranslator {
+ private final boolean cacheChunks;
+
+ public JavaUpdateTileEntityTranslator() {
+ cacheChunks = GeyserConnector.getInstance().getConfig().isCacheChunks();
+ }
@Override
public void translate(ServerUpdateTileEntityPacket packet, GeyserSession session) {
@@ -48,16 +54,17 @@ public class JavaUpdateTileEntityTranslator extends PacketTranslator= 2 &&
session.getGameMode() == GameMode.CREATIVE && packet.getNbt().size() > 5) {
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/WorldManager.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/WorldManager.java
index fec3bb33a..aaafe2fe9 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/WorldManager.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/WorldManager.java
@@ -43,7 +43,7 @@ import org.geysermc.connector.utils.GameRule;
public abstract class WorldManager {
/**
- * Gets the block state at the specified location
+ * Gets the Java block state at the specified location
*
* @param session the session
* @param position the position
@@ -54,7 +54,7 @@ public abstract class WorldManager {
}
/**
- * Gets the block state at the specified location
+ * Gets the Java block state at the specified location
*
* @param session the session
* @param vector the position
@@ -65,7 +65,7 @@ public abstract class WorldManager {
}
/**
- * Gets the block state at the specified location
+ * Gets the Java block state at the specified location
*
* @param session the session
* @param x the x coordinate to get the block at
@@ -97,7 +97,7 @@ public abstract class WorldManager {
public abstract boolean hasMoreBlockDataThanChunkCache();
/**
- * Gets the biome data for the specified chunk.
+ * Gets the Java biome data for the specified chunk.
*
* @param session the session of the player
* @param x the chunk's X coordinate
@@ -116,7 +116,7 @@ public abstract class WorldManager {
public abstract void setGameRule(GeyserSession session, String name, Object value);
/**
- * Get a gamerule value as a boolean
+ * Gets a gamerule value as a boolean
*
* @param session The session of the user that requested the value
* @param gameRule The gamerule to fetch the value of
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java
index 305118e6f..bfd59cc7c 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockStateValues.java
@@ -36,7 +36,6 @@ import java.util.Map;
* Used for block entities if the Java block state contains Bedrock block information.
*/
public class BlockStateValues {
-
private static final Int2IntMap BANNER_COLORS = new Int2IntOpenHashMap();
private static final Int2ByteMap BED_COLORS = new Int2ByteOpenHashMap();
private static final Int2ByteMap COMMAND_BLOCK_VALUES = new Int2ByteOpenHashMap();
@@ -52,7 +51,8 @@ public class BlockStateValues {
/**
* Determines if the block state contains Bedrock block information
- * @param entry The String to JsonNode map used in BlockTranslator
+ *
+ * @param entry The String to JsonNode map used in BlockTranslator
* @param javaBlockState the Java Block State of the block
*/
public static void storeBlockStateValues(Map.Entry entry, int javaBlockState) {
@@ -101,7 +101,7 @@ public class BlockStateValues {
}
JsonNode skullVariation = entry.getValue().get("variation");
- if(skullVariation != null) {
+ if (skullVariation != null) {
SKULL_VARIANTS.put(javaBlockState, (byte) skullVariation.intValue());
}
@@ -124,10 +124,7 @@ public class BlockStateValues {
* @return Banner color integer or -1 if no color
*/
public static int getBannerColor(int state) {
- if (BANNER_COLORS.containsKey(state)) {
- return BANNER_COLORS.get(state);
- }
- return -1;
+ return BANNER_COLORS.getOrDefault(state, -1);
}
/**
@@ -138,10 +135,7 @@ public class BlockStateValues {
* @return Bed color byte or -1 if no color
*/
public static byte getBedColor(int state) {
- if (BED_COLORS.containsKey(state)) {
- return BED_COLORS.get(state);
- }
- return -1;
+ return BED_COLORS.getOrDefault(state, (byte) -1);
}
/**
@@ -157,6 +151,7 @@ public class BlockStateValues {
/**
* All double chest values are part of the block state in Java and part of the block entity tag in Bedrock.
* This gives the DoubleChestValue that can be calculated into the final tag.
+ *
* @return The map of all DoubleChestValues.
*/
public static Int2ObjectMap getDoubleChestValues() {
@@ -165,6 +160,7 @@ public class BlockStateValues {
/**
* Get the Int2ObjectMap of flower pot block states to containing plant
+ *
* @return Int2ObjectMap of flower pot values
*/
public static Int2ObjectMap getFlowerPotValues() {
@@ -173,6 +169,7 @@ public class BlockStateValues {
/**
* Get the map of contained flower pot plants to Bedrock CompoundTag
+ *
* @return Map of flower pot blocks.
*/
public static Map getFlowerPotBlocks() {
@@ -182,18 +179,17 @@ public class BlockStateValues {
/**
* The note that noteblocks output when hit is part of the block state in Java but sent as a BlockEventPacket in Bedrock.
* This gives an integer pitch that Bedrock can use.
+ *
* @param state BlockState of the block
* @return note block note integer or -1 if not present
*/
public static int getNoteblockPitch(int state) {
- if (NOTEBLOCK_PITCHES.containsKey(state)) {
- return NOTEBLOCK_PITCHES.get(state);
- }
- return -1;
+ return NOTEBLOCK_PITCHES.getOrDefault(state, -1);
}
/**
* Get the Int2BooleanMap showing if a piston block state is extended or not.
+ *
* @return the Int2BooleanMap of piston extensions.
*/
public static Int2BooleanMap getPistonValues() {
@@ -212,10 +208,7 @@ public class BlockStateValues {
* @return Skull variant byte or -1 if no variant
*/
public static byte getSkullVariant(int state) {
- if (SKULL_VARIANTS.containsKey(state)) {
- return SKULL_VARIANTS.get(state);
- }
- return -1;
+ return SKULL_VARIANTS.getOrDefault(state, (byte) -1);
}
/**
@@ -226,10 +219,7 @@ public class BlockStateValues {
* @return Skull rotation value or -1 if no value
*/
public static byte getSkullRotation(int state) {
- if (SKULL_ROTATIONS.containsKey(state)) {
- return SKULL_ROTATIONS.get(state);
- }
- return -1;
+ return SKULL_ROTATIONS.getOrDefault(state, (byte) -1);
}
@@ -241,9 +231,6 @@ public class BlockStateValues {
* @return Shulker direction value or -1 if no value
*/
public static byte getShulkerBoxDirection(int state) {
- if (SHULKERBOX_DIRECTIONS.containsKey(state)) {
- return SHULKERBOX_DIRECTIONS.get(state);
- }
- return -1;
+ return SHULKERBOX_DIRECTIONS.getOrDefault(state, (byte) -1);
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java
index 5314292a1..eb09d63e3 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/BlockTranslator.java
@@ -30,21 +30,25 @@ import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.nukkitx.nbt.*;
import it.unimi.dsi.fastutil.ints.*;
-import it.unimi.dsi.fastutil.objects.Object2IntMap;
-import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
-import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
-import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
+import it.unimi.dsi.fastutil.objects.*;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.translators.world.block.entity.BlockEntity;
import org.geysermc.connector.utils.FileUtils;
import org.reflections.Reflections;
+import java.io.DataInputStream;
import java.io.InputStream;
import java.util.*;
public class BlockTranslator {
- public static final NbtList BLOCKS;
- public static final int AIR = 0;
+ /**
+ * The Java block runtime ID of air
+ */
+ public static final int JAVA_AIR_ID = 0;
+ /**
+ * The Bedrock block runtime ID of air
+ */
+ public static final int BEDROCK_AIR_ID;
public static final int BEDROCK_WATER_ID;
private static final Int2IntMap JAVA_TO_BEDROCK_BLOCK_MAP = new Int2IntOpenHashMap();
@@ -86,25 +90,31 @@ public class BlockTranslator {
public static final int JAVA_RUNTIME_SPAWNER_ID;
- private static final int BLOCK_STATE_VERSION = 17825806;
+ private static final int BLOCK_STATE_VERSION = 17825808;
static {
/* Load block palette */
- InputStream stream = FileUtils.getResource("bedrock/runtime_block_states.dat");
+ InputStream stream = FileUtils.getResource("bedrock/blockpalette.nbt");
NbtList blocksTag;
- try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) {
- blocksTag = (NbtList) nbtInputStream.readTag();
+ try (NBTInputStream nbtInputStream = new NBTInputStream(new DataInputStream(stream))) {
+ NbtMap blockPalette = (NbtMap) nbtInputStream.readTag();
+ blocksTag = (NbtList) blockPalette.getList("blocks", NbtType.COMPOUND);
} catch (Exception e) {
throw new AssertionError("Unable to get blocks from runtime block states", e);
}
- Map blockStateMap = new HashMap<>();
+ // New since 1.16.100 - find the block runtime ID by the order given to us in the block palette,
+ // as we no longer send a block palette
+ Object2IntMap blockStateOrderedMap = new Object2IntOpenHashMap<>(blocksTag.size());
- for (NbtMap tag : blocksTag) {
- if (blockStateMap.putIfAbsent(tag.getCompound("block"), tag) != null) {
+ for (int i = 0; i < blocksTag.size(); i++) {
+ NbtMap tag = blocksTag.get(i);
+ NbtMap blockTag = tag.getCompound("block");
+ if (blockStateOrderedMap.containsKey(blockTag)) {
throw new AssertionError("Duplicate block states in Bedrock palette");
}
+ blockStateOrderedMap.put(blockTag, i);
}
stream = FileUtils.getResource("mappings/blocks.json");
@@ -114,16 +124,13 @@ public class BlockTranslator {
} catch (Exception e) {
throw new AssertionError("Unable to load Java block mappings", e);
}
- Object2IntMap addedStatesMap = new Object2IntOpenHashMap<>();
- addedStatesMap.defaultReturnValue(-1);
- List paletteList = new ArrayList<>();
- Reflections ref = GeyserConnector.getInstance().useXmlReflections() ? FileUtils.getReflections("org.geysermc.connector.network.translators.world.block.entity") : new Reflections("org.geysermc.connector.network.translators.world.block.entity");
- ref.getTypesAnnotatedWith(BlockEntity.class);
+ Reflections ref = GeyserConnector.getInstance().useXmlReflections() ? FileUtils.getReflections("org.geysermc.connector.network.translators.world.block.entity")
+ : new Reflections("org.geysermc.connector.network.translators.world.block.entity");
int waterRuntimeId = -1;
int javaRuntimeId = -1;
- int bedrockRuntimeId = 0;
+ int airRuntimeId = -1;
int cobwebRuntimeId = -1;
int commandBlockRuntimeId = -1;
int furnaceRuntimeId = -1;
@@ -136,6 +143,10 @@ public class BlockTranslator {
Map.Entry entry = blocksIterator.next();
String javaId = entry.getKey();
NbtMap blockTag = buildBedrockState(entry.getValue());
+ int bedrockRuntimeId = blockStateOrderedMap.getOrDefault(blockTag, -1);
+ if (bedrockRuntimeId == -1) {
+ throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID!");
+ }
// TODO fix this, (no block should have a null hardness)
JsonNode hardnessNode = entry.getValue().get("block_hardness");
@@ -199,22 +210,12 @@ public class BlockTranslator {
BEDROCK_TO_JAVA_BLOCK_MAP.putIfAbsent(bedrockRuntimeId, javaRuntimeId);
}
- NbtMap runtimeTag = blockStateMap.remove(blockTag);
- if (runtimeTag != null) {
- addedStatesMap.put(blockTag, bedrockRuntimeId);
- paletteList.add(runtimeTag);
- } else {
- int duplicateRuntimeId = addedStatesMap.getOrDefault(blockTag, -1);
- if (duplicateRuntimeId == -1) {
- GeyserConnector.getInstance().getLogger().debug("Mapping " + javaId + " was not found for bedrock edition!");
- } else {
- JAVA_TO_BEDROCK_BLOCK_MAP.put(javaRuntimeId, duplicateRuntimeId);
- }
- continue;
- }
JAVA_TO_BEDROCK_BLOCK_MAP.put(javaRuntimeId, bedrockRuntimeId);
- if (javaId.contains("wool")) {
+ if (bedrockIdentifier.equals("minecraft:air")) {
+ airRuntimeId = bedrockRuntimeId;
+
+ } else if (javaId.contains("wool")) {
JAVA_RUNTIME_WOOL_IDS.add(javaRuntimeId);
} else if (javaId.contains("cobweb")) {
@@ -233,8 +234,6 @@ public class BlockTranslator {
} else if (javaId.startsWith("minecraft:spawner")) {
spawnerRuntimeId = javaRuntimeId;
}
-
- bedrockRuntimeId++;
}
if (cobwebRuntimeId == -1) {
@@ -267,19 +266,17 @@ public class BlockTranslator {
}
BEDROCK_WATER_ID = waterRuntimeId;
- paletteList.addAll(blockStateMap.values()); // Add any missing mappings that could crash the client
+ if (airRuntimeId == -1) {
+ throw new AssertionError("Unable to find air in palette");
+ }
+ BEDROCK_AIR_ID = airRuntimeId;
// Loop around again to find all item frame runtime IDs
- int frameRuntimeId = 0;
- for (NbtMap tag : paletteList) {
- NbtMap blockTag = tag.getCompound("block");
- if (blockTag.getString("name").equals("minecraft:frame")) {
- ITEM_FRAMES.put(tag, frameRuntimeId);
+ for (Object2IntMap.Entry entry : blockStateOrderedMap.object2IntEntrySet()) {
+ if (entry.getKey().getString("name").equals("minecraft:frame")) {
+ ITEM_FRAMES.put(entry.getKey(), entry.getIntValue());
}
- frameRuntimeId++;
}
-
- BLOCKS = new NbtList<>(NbtType.COMPOUND, paletteList);
}
private BlockTranslator() {
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java
index 57393a6c5..f5e1d5948 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BannerBlockEntityTranslator.java
@@ -27,39 +27,31 @@ package org.geysermc.connector.network.translators.world.block.entity;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag;
+import com.nukkitx.nbt.NbtMapBuilder;
import org.geysermc.connector.network.translators.item.translators.BannerTranslator;
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
-import java.util.HashMap;
-import java.util.Map;
-
@BlockEntity(name = "Banner", regex = "banner")
public class BannerBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
-
@Override
public boolean isBlock(int blockState) {
return BlockStateValues.getBannerColor(blockState) != -1;
}
@Override
- public Map translateTag(CompoundTag tag, int blockState) {
- Map tags = new HashMap<>();
-
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
int bannerColor = BlockStateValues.getBannerColor(blockState);
if (bannerColor != -1) {
- tags.put("Base", 15 - bannerColor);
+ builder.put("Base", 15 - bannerColor);
}
if (tag.contains("Patterns")) {
ListTag patterns = tag.get("Patterns");
- tags.put("Patterns", BannerTranslator.convertBannerPattern(patterns));
+ builder.put("Patterns", BannerTranslator.convertBannerPattern(patterns));
}
if (tag.contains("CustomName")) {
- tags.put("CustomName", tag.get("CustomName").getValue());
+ builder.put("CustomName", tag.get("CustomName").getValue());
}
-
- return tags;
}
-
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java
index 080bdc3b2..0067cc41f 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedBlockEntityTranslator.java
@@ -26,27 +26,23 @@
package org.geysermc.connector.network.translators.world.block.entity;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
+import com.nukkitx.nbt.NbtMapBuilder;
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
-import java.util.HashMap;
-import java.util.Map;
-
@BlockEntity(name = "Bed", regex = "bed")
public class BedBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
-
@Override
public boolean isBlock(int blockState) {
return BlockStateValues.getBedColor(blockState) != -1;
}
@Override
- public Map translateTag(CompoundTag tag, int blockState) {
- Map tags = new HashMap<>();
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
byte bedcolor = BlockStateValues.getBedColor(blockState);
// Just in case...
- if (bedcolor == -1) bedcolor = 0;
- tags.put("color", bedcolor);
- return tags;
+ if (bedcolor == -1) {
+ bedcolor = 0;
+ }
+ builder.put("color", bedcolor);
}
-
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedrockOnlyBlockEntity.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedrockOnlyBlockEntity.java
index d2e4537f5..646929f32 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedrockOnlyBlockEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BedrockOnlyBlockEntity.java
@@ -33,7 +33,6 @@ import org.geysermc.connector.network.session.GeyserSession;
* Implemented only if a block is a block entity in Bedrock and not Java Edition.
*/
public interface BedrockOnlyBlockEntity {
-
/**
* Update the block on Bedrock Edition.
* @param session GeyserSession.
@@ -49,7 +48,7 @@ public interface BedrockOnlyBlockEntity {
* @return Bedrock tag, or null if not a Bedrock-only Block Entity
*/
static NbtMap getTag(Vector3i position, int blockState) {
- if (new FlowerPotBlockEntityTranslator().isBlock(blockState)) {
+ if (FlowerPotBlockEntityTranslator.isFlowerBlock(blockState)) {
return FlowerPotBlockEntityTranslator.getTag(blockState, position);
} else if (PistonBlockEntityTranslator.isBlock(blockState)) {
return PistonBlockEntityTranslator.getTag(blockState, position);
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java
index 4df4fd95e..679636524 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/BlockEntityTranslator.java
@@ -41,10 +41,16 @@ import org.reflections.Reflections;
import java.util.HashMap;
import java.util.Map;
+/**
+ * The class that all block entities (on both Java and Bedrock) should translate with
+ */
public abstract class BlockEntityTranslator {
-
public static final Map BLOCK_ENTITY_TRANSLATORS = new HashMap<>();
- public static ObjectArrayList REQUIRES_BLOCK_STATE_LIST = new ObjectArrayList<>();
+ /**
+ * A list of all block entities that require the Java block state in order to fill out their block entity information.
+ * This list will be smaller with cache chunks on as we don't need to double-cache data
+ */
+ public static final ObjectArrayList REQUIRES_BLOCK_STATE_LIST = new ObjectArrayList<>();
/**
* Contains a list of irregular block entity name translations that can't be fit into the regex
@@ -78,27 +84,33 @@ public abstract class BlockEntityTranslator {
GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.block_entity.failed", clazz.getCanonicalName()));
}
}
+ boolean cacheChunks = GeyserConnector.getInstance().getConfig().isCacheChunks();
for (Class> clazz : ref.getSubTypesOf(RequiresBlockState.class)) {
GeyserConnector.getInstance().getLogger().debug("Found block entity that requires block state: " + clazz.getCanonicalName());
try {
- REQUIRES_BLOCK_STATE_LIST.add((RequiresBlockState) clazz.newInstance());
+ RequiresBlockState requiresBlockState = (RequiresBlockState) clazz.newInstance();
+ if (cacheChunks && !(requiresBlockState instanceof BedrockOnlyBlockEntity)) {
+ // Not needed to put this one in the map; cache chunks takes care of that for us
+ GeyserConnector.getInstance().getLogger().debug("Not adding because cache chunks is enabled.");
+ continue;
+ }
+ REQUIRES_BLOCK_STATE_LIST.add(requiresBlockState);
} catch (InstantiationException | IllegalAccessException e) {
GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.block_state.failed", clazz.getCanonicalName()));
}
}
}
- public abstract Map translateTag(CompoundTag tag, int blockState);
+ public abstract void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState);
public NbtMap getBlockEntityTag(String id, CompoundTag tag, int blockState) {
- int x = Integer.parseInt(String.valueOf(tag.getValue().get("x").getValue()));
- int y = Integer.parseInt(String.valueOf(tag.getValue().get("y").getValue()));
- int z = Integer.parseInt(String.valueOf(tag.getValue().get("z").getValue()));
+ int x = ((IntTag) tag.getValue().get("x")).getValue();
+ int y = ((IntTag) tag.getValue().get("y")).getValue();
+ int z = ((IntTag) tag.getValue().get("z")).getValue();
NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(id), x, y, z).toBuilder();
- Map translatedTags = translateTag(tag, blockState);
- translatedTags.forEach(tagBuilder::put);
+ translateTag(tagBuilder, tag, blockState);
return tagBuilder.build();
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java
index d6ac0281b..3e4f9fb90 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CampfireBlockEntityTranslator.java
@@ -32,22 +32,16 @@ import com.nukkitx.nbt.NbtMapBuilder;
import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ItemRegistry;
-import java.util.HashMap;
-import java.util.Map;
-
@BlockEntity(name = "Campfire", regex = "campfire")
public class CampfireBlockEntityTranslator extends BlockEntityTranslator {
-
@Override
- public Map translateTag(CompoundTag tag, int blockState) {
- Map tags = new HashMap<>();
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
ListTag items = tag.get("Items");
int i = 1;
for (com.github.steveice10.opennbt.tag.builtin.Tag itemTag : items.getValue()) {
- tags.put("Item" + i, getItem((CompoundTag) itemTag));
+ builder.put("Item" + i, getItem((CompoundTag) itemTag));
i++;
}
- return tags;
}
protected NbtMap getItem(CompoundTag tag) {
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CommandBlockBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CommandBlockBlockEntityTranslator.java
index 6bc940adb..1eb50ffe7 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CommandBlockBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/CommandBlockBlockEntityTranslator.java
@@ -26,38 +26,33 @@
package org.geysermc.connector.network.translators.world.block.entity;
import com.github.steveice10.opennbt.tag.builtin.*;
+import com.nukkitx.nbt.NbtMapBuilder;
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
-import org.geysermc.connector.utils.MessageUtils;
-
-import java.util.HashMap;
-import java.util.Map;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
@BlockEntity(name = "CommandBlock", regex = "command_block")
public class CommandBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
-
@Override
- public Map translateTag(CompoundTag tag, int blockState) {
- Map map = new HashMap<>();
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
if (tag.size() < 5) {
- return map; // These values aren't here
+ return; // These values aren't here
}
// Java infers from the block state, but Bedrock needs it in the tag
- map.put("conditionalMode", BlockStateValues.getCommandBlockValues().getOrDefault(blockState, (byte) 0));
+ builder.put("conditionalMode", BlockStateValues.getCommandBlockValues().getOrDefault(blockState, (byte) 0));
// Java and Bedrock values
- map.put("conditionMet", ((ByteTag) tag.get("conditionMet")).getValue());
- map.put("auto", ((ByteTag) tag.get("auto")).getValue());
- map.put("CustomName", MessageUtils.getBedrockMessage(((StringTag) tag.get("CustomName")).getValue()));
- map.put("powered", ((ByteTag) tag.get("powered")).getValue());
- map.put("Command", ((StringTag) tag.get("Command")).getValue());
- map.put("SuccessCount", ((IntTag) tag.get("SuccessCount")).getValue());
- map.put("TrackOutput", ((ByteTag) tag.get("TrackOutput")).getValue());
- map.put("UpdateLastExecution", ((ByteTag) tag.get("UpdateLastExecution")).getValue());
+ builder.put("conditionMet", ((ByteTag) tag.get("conditionMet")).getValue());
+ builder.put("auto", ((ByteTag) tag.get("auto")).getValue());
+ builder.put("CustomName", MessageTranslator.convertMessage(((StringTag) tag.get("CustomName")).getValue()));
+ builder.put("powered", ((ByteTag) tag.get("powered")).getValue());
+ builder.put("Command", ((StringTag) tag.get("Command")).getValue());
+ builder.put("SuccessCount", ((IntTag) tag.get("SuccessCount")).getValue());
+ builder.put("TrackOutput", ((ByteTag) tag.get("TrackOutput")).getValue());
+ builder.put("UpdateLastExecution", ((ByteTag) tag.get("UpdateLastExecution")).getValue());
if (tag.get("LastExecution") != null) {
- map.put("LastExecution", ((LongTag) tag.get("LastExecution")).getValue());
+ builder.put("LastExecution", ((LongTag) tag.get("LastExecution")).getValue());
} else {
- map.put("LastExecution", (long) 0);
+ builder.put("LastExecution", (long) 0);
}
- return map;
}
@Override
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java
index 5b59420e0..47bcf4897 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/DoubleChestBlockEntityTranslator.java
@@ -33,15 +33,11 @@ import org.geysermc.connector.network.translators.world.block.BlockStateValues;
import org.geysermc.connector.network.translators.world.block.DoubleChestValue;
import org.geysermc.connector.utils.BlockEntityUtils;
-import java.util.HashMap;
-import java.util.Map;
-
/**
* Chests have more block entity properties in Bedrock, which is solved by implementing the BedrockOnlyBlockEntity
*/
@BlockEntity(name = "Chest", regex = "chest")
public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator implements BedrockOnlyBlockEntity, RequiresBlockState {
-
@Override
public boolean isBlock(int blockState) {
return BlockStateValues.getDoubleChestValues().containsKey(blockState);
@@ -51,44 +47,39 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl
public void updateBlock(GeyserSession session, int blockState, Vector3i position) {
CompoundTag javaTag = getConstantJavaTag("chest", position.getX(), position.getY(), position.getZ());
NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId("chest"), position.getX(), position.getY(), position.getZ()).toBuilder();
- translateTag(javaTag, blockState).forEach(tagBuilder::put);
+ translateTag(tagBuilder, javaTag, blockState);
BlockEntityUtils.updateBlockEntity(session, tagBuilder.build(), position);
}
@Override
- public Map translateTag(CompoundTag tag, int blockState) {
- Map tags = new HashMap<>();
- if (BlockStateValues.getDoubleChestValues().containsKey(blockState)) {
- DoubleChestValue chestValues = BlockStateValues.getDoubleChestValues().get(blockState);
- if (chestValues != null) {
- int x = (int) tag.getValue().get("x").getValue();
- int z = (int) tag.getValue().get("z").getValue();
- // Calculate the position of the other chest based on the Java block state
- if (chestValues.isFacingEast) {
- if (chestValues.isDirectionPositive) {
- // East
- z = z + (chestValues.isLeft ? 1 : -1);
- } else {
- // West
- z = z + (chestValues.isLeft ? -1 : 1);
- }
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
+ DoubleChestValue chestValues = BlockStateValues.getDoubleChestValues().getOrDefault(blockState, null);
+ if (chestValues != null) {
+ int x = (int) tag.getValue().get("x").getValue();
+ int z = (int) tag.getValue().get("z").getValue();
+ // Calculate the position of the other chest based on the Java block state
+ if (chestValues.isFacingEast) {
+ if (chestValues.isDirectionPositive) {
+ // East
+ z = z + (chestValues.isLeft ? 1 : -1);
} else {
- if (chestValues.isDirectionPositive) {
- // South
- x = x + (chestValues.isLeft ? -1 : 1);
- } else {
- // North
- x = x + (chestValues.isLeft ? 1 : -1);
- }
+ // West
+ z = z + (chestValues.isLeft ? -1 : 1);
}
- tags.put("pairx", x);
- tags.put("pairz", z);
- if (!chestValues.isLeft) {
- tags.put("pairlead", (byte) 1);
+ } else {
+ if (chestValues.isDirectionPositive) {
+ // South
+ x = x + (chestValues.isLeft ? -1 : 1);
+ } else {
+ // North
+ x = x + (chestValues.isLeft ? 1 : -1);
}
}
+ builder.put("pairx", x);
+ builder.put("pairz", z);
+ if (!chestValues.isLeft) {
+ builder.put("pairlead", (byte) 1);
+ }
}
- return tags;
}
-
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java
index e9715bd32..3926b8664 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EmptyBlockEntityTranslator.java
@@ -26,16 +26,11 @@
package org.geysermc.connector.network.translators.world.block.entity;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
-
-import java.util.HashMap;
-import java.util.Map;
+import com.nukkitx.nbt.NbtMapBuilder;
@BlockEntity(name = "Empty", regex = "")
public class EmptyBlockEntityTranslator extends BlockEntityTranslator {
-
@Override
- public Map translateTag(CompoundTag tag, int blockState) {
- return new HashMap<>();
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
}
-
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java
index af94c560d..0bf588226 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/EndGatewayBlockEntityTranslator.java
@@ -28,21 +28,18 @@ package org.geysermc.connector.network.translators.world.block.entity;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.nukkitx.nbt.NbtList;
+import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
-import java.util.HashMap;
import java.util.LinkedHashMap;
-import java.util.Map;
@BlockEntity(name = "EndGateway", regex = "end_gateway")
public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator {
-
@Override
- public Map translateTag(CompoundTag tag, int blockState) {
- Map tags = new HashMap<>();
- tags.put("Age", (int) ((long) tag.get("Age").getValue()));
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
+ builder.put("Age", (int) ((long) tag.get("Age").getValue()));
// Java sometimes does not provide this tag, but Bedrock crashes if it doesn't exist
// Linked coordinates
IntList tagsList = new IntArrayList();
@@ -50,8 +47,7 @@ public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator {
tagsList.add(getExitPortalCoordinate(tag, "X"));
tagsList.add(getExitPortalCoordinate(tag, "Y"));
tagsList.add(getExitPortalCoordinate(tag, "Z"));
- tags.put("ExitPortal", new NbtList<>(NbtType.INT, tagsList));
- return tags;
+ builder.put("ExitPortal", new NbtList<>(NbtType.INT, tagsList));
}
private int getExitPortalCoordinate(CompoundTag tag, String axis) {
@@ -60,6 +56,7 @@ public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator {
LinkedHashMap, ?> compoundTag = (LinkedHashMap, ?>) tag.get("ExitPortal").getValue();
IntTag intTag = (IntTag) compoundTag.get(axis);
return intTag.getValue();
- } return 0;
+ }
+ return 0;
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java
index 7bfcc7ee9..f64474ae1 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/FlowerPotBlockEntityTranslator.java
@@ -35,30 +35,19 @@ import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.utils.BlockEntityUtils;
public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity, RequiresBlockState {
-
- @Override
- public boolean isBlock(int blockState) {
- return (BlockStateValues.getFlowerPotValues().containsKey(blockState));
- }
-
- @Override
- public void updateBlock(GeyserSession session, int blockState, Vector3i position) {
- BlockEntityUtils.updateBlockEntity(session, getTag(blockState, position), position);
- UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
- updateBlockPacket.setDataLayer(0);
- updateBlockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(blockState));
- updateBlockPacket.setBlockPosition(position);
- updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
- updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
- updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
- session.sendUpstreamPacket(updateBlockPacket);
- BlockEntityUtils.updateBlockEntity(session, getTag(blockState, position), position);
+ /**
+ * @param blockState the Java block state of a potential flower pot block
+ * @return true if the block is a flower pot
+ */
+ public static boolean isFlowerBlock(int blockState) {
+ return BlockStateValues.getFlowerPotValues().containsKey(blockState);
}
/**
* Get the Nukkit CompoundTag of the flower pot.
+ *
* @param blockState Java block state of flower pot.
- * @param position Bedrock position of flower pot.
+ * @param position Bedrock position of flower pot.
* @return Bedrock tag of flower pot.
*/
public static NbtMap getTag(int blockState, Vector3i position) {
@@ -80,4 +69,23 @@ public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity, R
}
return tagBuilder.build();
}
+
+ @Override
+ public boolean isBlock(int blockState) {
+ return isFlowerBlock(blockState);
+ }
+
+ @Override
+ public void updateBlock(GeyserSession session, int blockState, Vector3i position) {
+ BlockEntityUtils.updateBlockEntity(session, getTag(blockState, position), position);
+ UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
+ updateBlockPacket.setDataLayer(0);
+ updateBlockPacket.setRuntimeId(BlockTranslator.getBedrockBlockId(blockState));
+ updateBlockPacket.setBlockPosition(position);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
+ updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
+ session.sendUpstreamPacket(updateBlockPacket);
+ BlockEntityUtils.updateBlockEntity(session, getTag(blockState, position), position);
+ }
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/JigsawBlockBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/JigsawBlockBlockEntityTranslator.java
index 43ac1a96f..4fcdfe54d 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/JigsawBlockBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/JigsawBlockBlockEntityTranslator.java
@@ -27,21 +27,16 @@ package org.geysermc.connector.network.translators.world.block.entity;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
-
-import java.util.HashMap;
-import java.util.Map;
+import com.nukkitx.nbt.NbtMapBuilder;
@BlockEntity(name = "JigsawBlock", regex = "jigsaw")
public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator {
-
@Override
- public Map translateTag(CompoundTag tag, int blockState) {
- Map map = new HashMap<>();
- map.put("joint", ((StringTag) tag.get("joint")).getValue());
- map.put("name", ((StringTag) tag.get("name")).getValue());
- map.put("target_pool", ((StringTag) tag.get("pool")).getValue());
- map.put("final_state", ((StringTag) tag.get("final_state")).getValue());
- map.put("target", ((StringTag) tag.get("target")).getValue());
- return map;
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
+ builder.put("joint", ((StringTag) tag.get("joint")).getValue());
+ builder.put("name", ((StringTag) tag.get("name")).getValue());
+ builder.put("target_pool", ((StringTag) tag.get("pool")).getValue());
+ builder.put("final_state", ((StringTag) tag.get("final_state")).getValue());
+ builder.put("target", ((StringTag) tag.get("target")).getValue());
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/NoteblockBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/NoteblockBlockEntityTranslator.java
index f3e430090..fce0a0561 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/NoteblockBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/NoteblockBlockEntityTranslator.java
@@ -36,21 +36,20 @@ import org.geysermc.connector.utils.ChunkUtils;
* Does not implement BlockEntityTranslator because it's only a block entity in Bedrock
*/
public class NoteblockBlockEntityTranslator implements RequiresBlockState {
-
@Override
public boolean isBlock(int blockState) {
return BlockStateValues.getNoteblockPitch(blockState) != -1;
}
public static void translate(GeyserSession session, Position position) {
- int blockState = ChunkUtils.CACHED_BLOCK_ENTITIES.getOrDefault(position, 0);
+ int blockState = session.getConnector().getConfig().isCacheChunks() ?
+ session.getConnector().getWorldManager().getBlockAt(session, position) :
+ ChunkUtils.CACHED_BLOCK_ENTITIES.removeInt(position);
BlockEventPacket blockEventPacket = new BlockEventPacket();
blockEventPacket.setBlockPosition(Vector3i.from(position.getX(), position.getY(), position.getZ()));
blockEventPacket.setEventType(0);
blockEventPacket.setEventData(BlockStateValues.getNoteblockPitch(blockState));
session.sendUpstreamPacket(blockEventPacket);
-
- ChunkUtils.CACHED_BLOCK_ENTITIES.remove(position);
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/PistonBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/PistonBlockEntityTranslator.java
index 54feacbeb..c8a6e868f 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/PistonBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/PistonBlockEntityTranslator.java
@@ -34,9 +34,9 @@ import org.geysermc.connector.network.translators.world.block.BlockStateValues;
* Pistons are a special case where they are only a block entity on Bedrock.
*/
public class PistonBlockEntityTranslator {
-
/**
* Used in ChunkUtils to determine if the block is a piston.
+ *
* @param blockState Java BlockState of block.
* @return if block is a piston or not.
*/
@@ -46,8 +46,9 @@ public class PistonBlockEntityTranslator {
/**
* Calculates the Nukkit CompoundTag to send to the client on chunk
+ *
* @param blockState Java block state of block.
- * @param position Bedrock position of piston.
+ * @param position Bedrock position of piston.
* @return Bedrock tag of piston.
*/
public static NbtMap getTag(int blockState, Vector3i position) {
@@ -57,14 +58,13 @@ public class PistonBlockEntityTranslator {
.putInt("z", position.getZ())
.putByte("isMovable", (byte) 1)
.putString("id", "PistonArm");
- if (BlockStateValues.getPistonValues().containsKey(blockState)) {
- boolean extended = BlockStateValues.getPistonValues().get(blockState);
- // 1f if extended, otherwise 0f
- tagBuilder.putFloat("Progress", (extended) ? 1.0f : 0.0f);
- // 1 if sticky, 0 if not
- tagBuilder.putByte("Sticky", (byte)((BlockStateValues.isStickyPiston(blockState)) ? 1 : 0));
- }
+
+ boolean extended = BlockStateValues.getPistonValues().get(blockState);
+ // 1f if extended, otherwise 0f
+ tagBuilder.putFloat("Progress", (extended) ? 1.0f : 0.0f);
+ // 1 if sticky, 0 if not
+ tagBuilder.putByte("Sticky", (byte) ((BlockStateValues.isStickyPiston(blockState)) ? 1 : 0));
+
return tagBuilder.build();
}
-
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/ShulkerBoxBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/ShulkerBoxBlockEntityTranslator.java
index 08e3abaab..69fa10845 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/ShulkerBoxBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/ShulkerBoxBlockEntityTranslator.java
@@ -26,23 +26,18 @@
package org.geysermc.connector.network.translators.world.block.entity;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
+import com.nukkitx.nbt.NbtMapBuilder;
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
-import java.util.HashMap;
-import java.util.Map;
-
@BlockEntity(name = "ShulkerBox", regex = "shulker_box")
public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator {
-
@Override
- public Map translateTag(CompoundTag tag, int blockState) {
- Map tags = new HashMap<>();
-
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
byte direction = BlockStateValues.getShulkerBoxDirection(blockState);
// Just in case...
- if (direction == -1) direction = 1;
- tags.put("facing", direction);
- return tags;
+ if (direction == -1) {
+ direction = 1;
+ }
+ builder.put("facing", direction);
}
-
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java
index b40ed42c9..a9641d772 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SignBlockEntityTranslator.java
@@ -25,62 +25,22 @@
package org.geysermc.connector.network.translators.world.block.entity;
-import com.github.steveice10.mc.protocol.data.message.MessageSerializer;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
-import org.geysermc.connector.utils.MessageUtils;
+import com.nukkitx.nbt.NbtMapBuilder;
+import org.geysermc.connector.network.translators.chat.MessageTranslator;
import org.geysermc.connector.utils.SignUtils;
-import java.util.HashMap;
-import java.util.Map;
-
@BlockEntity(name = "Sign", regex = "sign")
public class SignBlockEntityTranslator extends BlockEntityTranslator {
-
- @Override
- public Map translateTag(CompoundTag tag, int blockState) {
- Map tags = new HashMap<>();
-
- StringBuilder signText = new StringBuilder();
- for(int i = 0; i < 4; i++) {
- int currentLine = i+1;
- String signLine = getOrDefault(tag.getValue().get("Text" + currentLine), "");
- signLine = MessageUtils.getBedrockMessage(MessageSerializer.fromString(signLine));
-
- // Check the character width on the sign to ensure there is no overflow that is usually hidden
- // to Java Edition clients but will appear to Bedrock clients
- int signWidth = 0;
- StringBuilder finalSignLine = new StringBuilder();
- for (char c : signLine.toCharArray()) {
- signWidth += SignUtils.getCharacterWidth(c);
- if (signWidth <= SignUtils.BEDROCK_CHARACTER_WIDTH_MAX) {
- finalSignLine.append(c);
- } else {
- break;
- }
- }
-
- // Java Edition 1.14 added the ability to change the text color of the whole sign using dye
- if (tag.contains("Color")) {
- signText.append(getBedrockSignColor(tag.get("Color").getValue().toString()));
- }
-
- signText.append(finalSignLine.toString());
- signText.append("\n");
- }
-
- tags.put("Text", MessageUtils.getBedrockMessage(MessageSerializer.fromString(signText.toString())));
- return tags;
- }
-
/**
* Maps a color stored in a sign's Color tag to a Bedrock Edition formatting code.
*
- * The color names correspond to dye names, because of this we can't use {@link MessageUtils#getColor(String)}.
+ * The color names correspond to dye names, because of this we can't use {@link MessageTranslator#getColor(String)}.
*
* @param javaColor The dye color stored in the sign's Color tag.
* @return A Bedrock Edition formatting code for valid dye colors, otherwise an empty string.
*/
- private static String getBedrockSignColor(String javaColor) {
+ private String getBedrockSignColor(String javaColor) {
String base = "\u00a7";
switch (javaColor) {
case "white":
@@ -133,4 +93,41 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator {
return base;
}
+ @Override
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
+ StringBuilder signText = new StringBuilder();
+ for (int i = 0; i < 4; i++) {
+ int currentLine = i + 1;
+ String signLine = getOrDefault(tag.getValue().get("Text" + currentLine), "");
+ signLine = MessageTranslator.convertMessageLenient(signLine);
+
+ // Trim any trailing formatting codes
+ if (signLine.length() > 2 && signLine.toCharArray()[signLine.length() - 2] == '\u00a7') {
+ signLine = signLine.substring(0, signLine.length() - 2);
+ }
+
+ // Check the character width on the sign to ensure there is no overflow that is usually hidden
+ // to Java Edition clients but will appear to Bedrock clients
+ int signWidth = 0;
+ StringBuilder finalSignLine = new StringBuilder();
+ for (char c : signLine.toCharArray()) {
+ signWidth += SignUtils.getCharacterWidth(c);
+ if (signWidth <= SignUtils.BEDROCK_CHARACTER_WIDTH_MAX) {
+ finalSignLine.append(c);
+ } else {
+ break;
+ }
+ }
+
+ // Java Edition 1.14 added the ability to change the text color of the whole sign using dye
+ if (tag.contains("Color")) {
+ signText.append(getBedrockSignColor(tag.get("Color").getValue().toString()));
+ }
+
+ signText.append(finalSignLine.toString());
+ signText.append("\n");
+ }
+
+ builder.put("Text", signText.toString());
+ }
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java
index 6d350c0cc..c5f479948 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SkullBlockEntityTranslator.java
@@ -25,29 +25,26 @@
package org.geysermc.connector.network.translators.world.block.entity;
+import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
+import com.nukkitx.nbt.NbtMapBuilder;
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
-import java.util.HashMap;
-import java.util.Map;
-
@BlockEntity(name = "Skull", regex = "skull")
public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
-
@Override
public boolean isBlock(int blockState) {
return BlockStateValues.getSkullVariant(blockState) != -1;
}
@Override
- public Map translateTag(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag, int blockState) {
- Map tags = new HashMap<>();
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
byte skullVariant = BlockStateValues.getSkullVariant(blockState);
float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f;
// Just in case...
- if (skullVariant == -1) skullVariant = 0;
- tags.put("Rotation", rotation);
- tags.put("SkullType", skullVariant);
- return tags;
+ if (skullVariant == -1) {
+ skullVariant = 0;
+ }
+ builder.put("Rotation", rotation);
+ builder.put("SkullType", skullVariant);
}
-
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SpawnerBlockEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SpawnerBlockEntityTranslator.java
index 2601e3de9..38507f54a 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SpawnerBlockEntityTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/SpawnerBlockEntityTranslator.java
@@ -26,63 +26,58 @@
package org.geysermc.connector.network.translators.world.block.entity;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
+import com.github.steveice10.opennbt.tag.builtin.Tag;
+import com.nukkitx.nbt.NbtMapBuilder;
import org.geysermc.connector.entity.type.EntityType;
-import java.util.HashMap;
-import java.util.Map;
-
@BlockEntity(name = "MobSpawner", regex = "mob_spawner")
public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
-
@Override
- public Map translateTag(CompoundTag tag, int blockState) {
- Map tags = new HashMap<>();
+ public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
+ Tag current;
- if (tag.get("MaxNearbyEntities") != null) {
- tags.put("MaxNearbyEntities", (short) tag.get("MaxNearbyEntities").getValue());
+ if ((current = tag.get("MaxNearbyEntities")) != null) {
+ builder.put("MaxNearbyEntities", current.getValue());
}
- if (tag.get("RequiredPlayerRange") != null) {
- tags.put("RequiredPlayerRange", (short) tag.get("RequiredPlayerRange").getValue());
+ if ((current = tag.get("RequiredPlayerRange")) != null) {
+ builder.put("RequiredPlayerRange", current.getValue());
}
- if (tag.get("SpawnCount") != null) {
- tags.put("SpawnCount", (short) tag.get("SpawnCount").getValue());
+ if ((current = tag.get("SpawnCount")) != null) {
+ builder.put("SpawnCount", current.getValue());
}
- if (tag.get("MaxSpawnDelay") != null) {
- tags.put("MaxSpawnDelay", (short) tag.get("MaxSpawnDelay").getValue());
+ if ((current = tag.get("MaxSpawnDelay")) != null) {
+ builder.put("MaxSpawnDelay", current.getValue());
}
- if (tag.get("Delay") != null) {
- tags.put("Delay", (short) tag.get("Delay").getValue());
+ if ((current = tag.get("Delay")) != null) {
+ builder.put("Delay", current.getValue());
}
- if (tag.get("SpawnRange") != null) {
- tags.put("SpawnRange", (short) tag.get("SpawnRange").getValue());
+ if ((current = tag.get("SpawnRange")) != null) {
+ builder.put("SpawnRange", current.getValue());
}
- if (tag.get("MinSpawnDelay") != null) {
- tags.put("MinSpawnDelay", (short) tag.get("MinSpawnDelay").getValue());
+ if ((current = tag.get("MinSpawnDelay")) != null) {
+ builder.put("MinSpawnDelay", current.getValue());
}
- if (tag.get("SpawnData") != null) {
- CompoundTag spawnData = tag.get("SpawnData");
+ CompoundTag spawnData = tag.get("SpawnData");
+ if (spawnData != null) {
String entityID = (String) spawnData.get("id").getValue();
- tags.put("EntityIdentifier", entityID);
+ builder.put("EntityIdentifier", entityID);
EntityType type = EntityType.getFromIdentifier(entityID);
if (type != null) {
- tags.put("DisplayEntityWidth", type.getWidth());
- tags.put("DisplayEntityHeight", type.getHeight());
- tags.put("DisplayEntityScale", 1.0f);
+ builder.put("DisplayEntityWidth", type.getWidth());
+ builder.put("DisplayEntityHeight", type.getHeight());
+ builder.put("DisplayEntityScale", 1.0f);
}
}
- tags.put("id", "MobSpawner");
- tags.put("isMovable", (byte) 1);
-
- return tags;
+ builder.put("id", "MobSpawner");
+ builder.put("isMovable", (byte) 1);
}
-
}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/BlockStorage.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/BlockStorage.java
index d8cd75206..f195394db 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/BlockStorage.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/chunk/BlockStorage.java
@@ -30,6 +30,7 @@ import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import lombok.Getter;
+import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.network.translators.world.chunk.bitarray.BitArray;
import org.geysermc.connector.network.translators.world.chunk.bitarray.BitArrayVersion;
@@ -50,7 +51,7 @@ public class BlockStorage {
public BlockStorage(BitArrayVersion version) {
this.bitArray = version.createArray(SIZE);
this.palette = new IntArrayList(16);
- this.palette.add(0); // Air is at the start of every palette.
+ this.palette.add(BlockTranslator.BEDROCK_AIR_ID); // Air is at the start of every palette and controls what the default block is in second-layer non-air block spaces.
}
public BlockStorage(BitArray bitArray, IntList palette) {
diff --git a/connector/src/main/java/org/geysermc/connector/scoreboard/Objective.java b/connector/src/main/java/org/geysermc/connector/scoreboard/Objective.java
index 3accbc120..419e99fd0 100644
--- a/connector/src/main/java/org/geysermc/connector/scoreboard/Objective.java
+++ b/connector/src/main/java/org/geysermc/connector/scoreboard/Objective.java
@@ -33,14 +33,16 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Getter
-public class Objective {
+public final class Objective {
private final Scoreboard scoreboard;
private final long id;
private boolean active = true;
@Setter
private UpdateType updateType = UpdateType.ADD;
+
private String objectiveName;
+ private ScoreboardPosition displaySlot;
private String displaySlotName;
private String displayName = "unknown";
private int type = 0; // 0 = integer, 1 = heart
@@ -67,39 +69,59 @@ public class Objective {
public Objective(Scoreboard scoreboard, String objectiveName, ScoreboardPosition displaySlot, String displayName, int type) {
this(scoreboard);
this.objectiveName = objectiveName;
+ this.displaySlot = correctDisplaySlot(displaySlot);
this.displaySlotName = translateDisplaySlot(displaySlot);
this.displayName = displayName;
this.type = type;
}
+ private static String translateDisplaySlot(ScoreboardPosition displaySlot) {
+ switch (displaySlot) {
+ case BELOW_NAME:
+ return "belowname";
+ case PLAYER_LIST:
+ return "list";
+ default:
+ return "sidebar";
+ }
+ }
+
+ private static ScoreboardPosition correctDisplaySlot(ScoreboardPosition displaySlot) {
+ switch (displaySlot) {
+ case BELOW_NAME:
+ return ScoreboardPosition.BELOW_NAME;
+ case PLAYER_LIST:
+ return ScoreboardPosition.PLAYER_LIST;
+ default:
+ return ScoreboardPosition.SIDEBAR;
+ }
+ }
+
public void registerScore(String id, int score) {
if (!scores.containsKey(id)) {
- Score score1 = new Score(this, id)
+ long scoreId = scoreboard.getNextId().getAndIncrement();
+ Score scoreObject = new Score(scoreId, id)
.setScore(score)
.setTeam(scoreboard.getTeamFor(id))
.setUpdateType(UpdateType.ADD);
- scores.put(id, score1);
+ scores.put(id, scoreObject);
}
}
public void setScore(String id, int score) {
- if (scores.containsKey(id)) {
- scores.get(id).setScore(score);
+ Score stored = scores.get(id);
+ if (stored != null) {
+ stored.setScore(score)
+ .setUpdateType(UpdateType.UPDATE);
return;
}
registerScore(id, score);
}
- public int getScore(String id) {
- if (scores.containsKey(id)) {
- return scores.get(id).getScore();
- }
- return 0;
- }
-
public void removeScore(String id) {
- if (scores.containsKey(id)) {
- scores.get(id).setUpdateType(UpdateType.REMOVE);
+ Score stored = scores.get(id);
+ if (stored != null) {
+ stored.setUpdateType(UpdateType.REMOVE);
}
}
@@ -129,6 +151,7 @@ public class Objective {
public void setActive(ScoreboardPosition displaySlot) {
if (!active) {
active = true;
+ this.displaySlot = correctDisplaySlot(displaySlot);
displaySlotName = translateDisplaySlot(displaySlot);
}
}
@@ -136,15 +159,4 @@ public class Objective {
public void removed() {
scores = null;
}
-
- private static String translateDisplaySlot(ScoreboardPosition displaySlot) {
- switch (displaySlot) {
- case BELOW_NAME:
- return "belowname";
- case PLAYER_LIST:
- return "list";
- default:
- return "sidebar";
- }
- }
}
diff --git a/connector/src/main/java/org/geysermc/connector/scoreboard/Score.java b/connector/src/main/java/org/geysermc/connector/scoreboard/Score.java
index 3dfd6ed38..e5f97b459 100644
--- a/connector/src/main/java/org/geysermc/connector/scoreboard/Score.java
+++ b/connector/src/main/java/org/geysermc/connector/scoreboard/Score.java
@@ -27,60 +27,107 @@ package org.geysermc.connector.scoreboard;
import com.nukkitx.protocol.bedrock.data.ScoreInfo;
import lombok.Getter;
-import lombok.Setter;
import lombok.experimental.Accessors;
@Getter
@Accessors(chain = true)
-public class Score {
- private final Objective objective;
- private ScoreInfo cachedInfo;
+public final class Score {
private final long id;
-
- @Setter
- private UpdateType updateType = UpdateType.ADD;
private final String name;
- private Team team;
- private int score;
- @Setter
- private int oldScore = Integer.MIN_VALUE;
+ private ScoreInfo cachedInfo;
- public Score(Objective objective, String name) {
- this.id = objective.getScoreboard().getNextId().getAndIncrement();
- this.objective = objective;
+ private ScoreData currentData;
+ private ScoreData cachedData;
+
+ public Score(long id, String name) {
+ this.id = id;
this.name = name;
+ this.currentData = new ScoreData();
}
public String getDisplayName() {
+ Team team = cachedData.team;
if (team != null) {
- return team.getPrefix() + name + team.getSuffix();
+ return team.getDisplayName(name);
}
return name;
}
public Score setScore(int score) {
- this.score = score;
- updateType = UpdateType.UPDATE;
+ currentData.score = score;
return this;
}
+ public Team getTeam() {
+ return currentData.team;
+ }
+
public Score setTeam(Team team) {
- if (this.team != null && team != null) {
- if (!this.team.equals(team)) {
- this.team = team;
- updateType = UpdateType.UPDATE;
+ if (currentData.team != null && team != null) {
+ if (!currentData.team.equals(team)) {
+ currentData.team = team;
+ currentData.updateType = UpdateType.UPDATE;
}
return this;
}
// simplified from (this.team != null && team == null) || (this.team == null && team != null)
- if (this.team != null || team != null) {
- this.team = team;
- updateType = UpdateType.UPDATE;
+ if (currentData.team != null || team != null) {
+ currentData.team = team;
+ currentData.updateType = UpdateType.UPDATE;
}
return this;
}
- public void update() {
- cachedInfo = new ScoreInfo(id, objective.getObjectiveName(), score, getDisplayName());
+ public UpdateType getUpdateType() {
+ return cachedData != null ? cachedData.updateType : currentData.updateType;
+ }
+
+ public Score setUpdateType(UpdateType updateType) {
+ if (updateType != UpdateType.NOTHING) {
+ currentData.updateTime = System.currentTimeMillis();
+ }
+ currentData.updateType = updateType;
+ return this;
+ }
+
+ public boolean shouldUpdate() {
+ return cachedData == null || currentData.updateTime > cachedData.updateTime ||
+ (currentData.team != null && currentData.team.shouldUpdate());
+ }
+
+ public void update(String objectiveName) {
+ if (cachedData == null) {
+ cachedData = new ScoreData();
+ cachedData.updateType = UpdateType.ADD;
+ if (currentData.updateType == UpdateType.REMOVE) {
+ cachedData.updateType = UpdateType.REMOVE;
+ }
+ } else {
+ cachedData.updateType = currentData.updateType;
+ }
+
+ cachedData.updateTime = currentData.updateTime;
+ cachedData.team = currentData.team;
+ cachedData.score = currentData.score;
+
+ String name = this.name;
+ if (cachedData.team != null) {
+ cachedData.team.prepareUpdate();
+ name = cachedData.team.getDisplayName(name);
+ }
+ cachedInfo = new ScoreInfo(id, objectiveName, cachedData.score, name);
+ }
+
+ @Getter
+ public static final class ScoreData {
+ protected UpdateType updateType;
+ protected long updateTime;
+
+ private Team team;
+ private int score;
+
+ protected ScoreData() {
+ updateType = UpdateType.ADD;
+ }
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/scoreboard/Scoreboard.java b/connector/src/main/java/org/geysermc/connector/scoreboard/Scoreboard.java
index 732a056eb..8eaa2e277 100644
--- a/connector/src/main/java/org/geysermc/connector/scoreboard/Scoreboard.java
+++ b/connector/src/main/java/org/geysermc/connector/scoreboard/Scoreboard.java
@@ -43,7 +43,7 @@ import java.util.concurrent.atomic.AtomicLong;
import static org.geysermc.connector.scoreboard.UpdateType.*;
@Getter
-public class Scoreboard {
+public final class Scoreboard {
private final GeyserSession session;
private final GeyserLogger logger;
private final AtomicLong nextId = new AtomicLong(0);
@@ -51,7 +51,8 @@ public class Scoreboard {
private final Map objectives = new ConcurrentHashMap<>();
private final Map teams = new HashMap<>();
- private int lastScoreCount = 0;
+ private int lastAddScoreCount = 0;
+ private int lastRemoveScoreCount = 0;
public Scoreboard(GeyserSession session) {
this.session = session;
@@ -59,19 +60,21 @@ public class Scoreboard {
}
public Objective registerNewObjective(String objectiveId, boolean active) {
- if (active || objectives.containsKey(objectiveId)) {
- return objectives.get(objectiveId);
+ Objective objective = objectives.get(objectiveId);
+ if (active || objective != null) {
+ return objective;
}
- Objective objective = new Objective(this, objectiveId);
+ objective = new Objective(this, objectiveId);
objectives.put(objectiveId, objective);
return objective;
}
- public Objective registerNewObjective(String objectiveId, ScoreboardPosition displaySlot) {
+ public Objective displayObjective(String objectiveId, ScoreboardPosition displaySlot) {
Objective objective = objectives.get(objectiveId);
if (objective != null) {
if (!objective.isActive()) {
objective.setActive(displaySlot);
+ removeOldObjectives(objective);
return objective;
}
despawnObjective(objective);
@@ -79,9 +82,21 @@ public class Scoreboard {
objective = new Objective(this, objectiveId, displaySlot, "unknown", 0);
objectives.put(objectiveId, objective);
+ removeOldObjectives(objective);
return objective;
}
+ private void removeOldObjectives(Objective newObjective) {
+ for (Objective next : objectives.values()) {
+ if (next.getId() == newObjective.getId()) {
+ continue;
+ }
+ if (next.getDisplaySlot() == newObjective.getDisplaySlot()) {
+ next.setUpdateType(REMOVE);
+ }
+ }
+ }
+
public Team registerNewTeam(String teamName, Set players) {
Team team = teams.get(teamName);
if (team != null) {
@@ -89,7 +104,7 @@ public class Scoreboard {
return team;
}
- team = new Team(this, teamName).setEntities(players);
+ team = new Team(this, teamName).addEntities(players);
teams.put(teamName, team);
return team;
}
@@ -117,8 +132,9 @@ public class Scoreboard {
}
public void onUpdate() {
- List addScores = new ArrayList<>(getLastScoreCount());
- List removeScores = new ArrayList<>(getLastScoreCount());
+ List addScores = new ArrayList<>(getLastAddScoreCount());
+ List removeScores = new ArrayList<>(getLastRemoveScoreCount());
+ List removedObjectives = new ArrayList<>();
for (Objective objective : objectives.values()) {
if (!objective.isActive()) {
@@ -129,65 +145,58 @@ public class Scoreboard {
// hearts can't hold teams, so we treat them differently
if (objective.getType() == 1) {
for (Score score : objective.getScores().values()) {
- if (score.getUpdateType() == NOTHING) {
- continue;
- }
+ boolean update = score.shouldUpdate();
- boolean update = score.getUpdateType() == UPDATE;
if (update) {
- score.update();
+ score.update(objective.getObjectiveName());
}
- if (score.getUpdateType() == ADD || update) {
+ if (score.getUpdateType() != REMOVE && update) {
addScores.add(score.getCachedInfo());
}
- if (score.getUpdateType() == REMOVE || update) {
+ if (score.getUpdateType() != ADD && update) {
removeScores.add(score.getCachedInfo());
}
}
continue;
}
- boolean globalUpdate = objective.getUpdateType() == UPDATE;
- boolean globalAdd = objective.getUpdateType() == ADD;
- boolean globalRemove = objective.getUpdateType() == REMOVE;
+ boolean objectiveUpdate = objective.getUpdateType() == UPDATE;
+ boolean objectiveAdd = objective.getUpdateType() == ADD;
+ boolean objectiveRemove = objective.getUpdateType() == REMOVE;
for (Score score : objective.getScores().values()) {
Team team = score.getTeam();
- boolean add = globalAdd || globalUpdate;
- boolean remove = globalRemove;
- boolean teamChanged = false;
+ boolean add = objectiveAdd || objectiveUpdate;
+ boolean remove = false;
if (team != null) {
if (team.getUpdateType() == REMOVE || !team.hasEntity(score.getName())) {
score.setTeam(null);
- teamChanged = true;
+ add = true;
+ remove = true;
}
-
- teamChanged |= team.getUpdateType() == UPDATE;
-
- add |= team.getUpdateType() == ADD || team.getUpdateType() == UPDATE;
- remove |= team.getUpdateType() != NOTHING;
}
- add |= score.getUpdateType() == ADD || score.getUpdateType() == UPDATE;
- remove |= score.getUpdateType() == REMOVE || score.getUpdateType() == UPDATE;
+ add |= score.shouldUpdate();
+ remove |= score.shouldUpdate();
- if (score.getUpdateType() == REMOVE || globalRemove) {
+ if (score.getUpdateType() == REMOVE || objectiveRemove) {
add = false;
}
- if (score.getUpdateType() == ADD) {
+ if (score.getUpdateType() == ADD || objectiveRemove) {
remove = false;
}
- if (score.getUpdateType() == ADD || score.getUpdateType() == UPDATE || teamChanged) {
- score.update();
+ if (score.shouldUpdate()) {
+ score.update(objective.getObjectiveName());
}
if (add) {
addScores.add(score.getCachedInfo());
}
+
if (remove) {
removeScores.add(score.getCachedInfo());
}
@@ -200,17 +209,17 @@ public class Scoreboard {
score.setUpdateType(NOTHING);
}
- if (globalRemove || globalUpdate) {
+ if (objectiveRemove) {
+ removedObjectives.add(objective);
+ }
+
+ if (objectiveUpdate) {
RemoveObjectivePacket removeObjectivePacket = new RemoveObjectivePacket();
removeObjectivePacket.setObjectiveId(objective.getObjectiveName());
session.sendUpstreamPacket(removeObjectivePacket);
- if (globalRemove) {
- objectives.remove(objective.getObjectiveName()); // now we can deregister
- objective.removed();
- }
}
- if ((globalAdd || globalUpdate) && !globalRemove) {
+ if ((objectiveAdd || objectiveUpdate) && !objectiveRemove) {
SetDisplayObjectivePacket displayObjectivePacket = new SetDisplayObjectivePacket();
displayObjectivePacket.setObjectiveId(objective.getObjectiveName());
displayObjectivePacket.setDisplayName(objective.getDisplayName());
@@ -223,6 +232,20 @@ public class Scoreboard {
objective.setUpdateType(NOTHING);
}
+ Iterator teamIterator = teams.values().iterator();
+ while (teamIterator.hasNext()) {
+ Team current = teamIterator.next();
+
+ switch (current.getUpdateType()) {
+ case ADD:
+ case UPDATE:
+ current.markUpdated();
+ break;
+ case REMOVE:
+ teamIterator.remove();
+ }
+ }
+
if (!removeScores.isEmpty()) {
SetScorePacket setScorePacket = new SetScorePacket();
setScorePacket.setAction(SetScorePacket.Action.REMOVE);
@@ -237,37 +260,27 @@ public class Scoreboard {
session.sendUpstreamPacket(setScorePacket);
}
- lastScoreCount = addScores.size();
+ // prevents crashes in some cases
+ for (Objective objective : removedObjectives) {
+ despawnObjective(objective);
+ }
+
+ lastAddScoreCount = addScores.size();
+ lastRemoveScoreCount = removeScores.size();
}
public void despawnObjective(Objective objective) {
+ objectives.remove(objective.getObjectiveName());
+ objective.removed();
+
RemoveObjectivePacket removeObjectivePacket = new RemoveObjectivePacket();
removeObjectivePacket.setObjectiveId(objective.getObjectiveName());
session.sendUpstreamPacket(removeObjectivePacket);
- objectives.remove(objective.getDisplayName());
-
- List toRemove = new ArrayList<>();
- for (String identifier : objective.getScores().keySet()) {
- Score score = objective.getScores().get(identifier);
- toRemove.add(new ScoreInfo(
- score.getId(), score.getObjective().getObjectiveName(),
- 0, ""
- ));
- }
-
- objective.removed();
-
- if (!toRemove.isEmpty()) {
- SetScorePacket setScorePacket = new SetScorePacket();
- setScorePacket.setAction(SetScorePacket.Action.REMOVE);
- setScorePacket.setInfos(toRemove);
- session.sendUpstreamPacket(setScorePacket);
- }
}
public Team getTeamFor(String entity) {
for (Team team : teams.values()) {
- if (team.getEntities().contains(entity)) {
+ if (team.hasEntity(entity)) {
return team;
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/scoreboard/Team.java b/connector/src/main/java/org/geysermc/connector/scoreboard/Team.java
index a073e2e99..377a15f1e 100644
--- a/connector/src/main/java/org/geysermc/connector/scoreboard/Team.java
+++ b/connector/src/main/java/org/geysermc/connector/scoreboard/Team.java
@@ -28,6 +28,7 @@ package org.geysermc.connector.scoreboard;
import com.github.steveice10.mc.protocol.data.game.scoreboard.NameTagVisibility;
import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
+import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@@ -36,62 +37,90 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
-@Getter @Setter
+@Getter
@Accessors(chain = true)
-public class Team {
+public final class Team {
private final Scoreboard scoreboard;
private final String id;
- private UpdateType updateType = UpdateType.ADD;
- private String name;
+ @Getter(AccessLevel.NONE)
+ private final Set entities;
+ @Setter private NameTagVisibility nameTagVisibility;
+ @Setter private TeamColor color;
- private NameTagVisibility nameTagVisibility;
- private String prefix;
- private TeamColor color;
- private String suffix;
- private Set entities = new ObjectOpenHashSet<>();
+ private TeamData currentData;
+ private TeamData cachedData;
+
+ private boolean updating;
public Team(Scoreboard scoreboard, String id) {
this.scoreboard = scoreboard;
this.id = id;
+ currentData = new TeamData();
+ entities = new ObjectOpenHashSet<>();
}
- public void addEntities(String... names) {
- List added = new ArrayList<>();
- for (String name : names) {
- if (entities.add(name)) {
- added.add(name);
- }
+ private void checkAddedEntities(List added) {
+ if (added.size() == 0) {
+ return;
}
- setUpdateType(UpdateType.UPDATE);
+ // we don't have to change the updateType,
+ // because the scores itself need updating, not the team
for (Objective objective : scoreboard.getObjectives().values()) {
- for (Score score : objective.getScores().values()) {
- if (added.contains(score.getName())) {
+ for (String addedEntity : added) {
+ Score score = objective.getScores().get(addedEntity);
+ if (score != null) {
score.setTeam(this);
}
}
}
}
+ public Team addEntities(String... names) {
+ List added = new ArrayList<>();
+ for (String name : names) {
+ if (entities.add(name)) {
+ added.add(name);
+ }
+ }
+ checkAddedEntities(added);
+ return this;
+ }
+
+ public Team addEntities(Set names) {
+ List added = new ArrayList<>();
+ for (String name : names) {
+ if (entities.add(name)) {
+ added.add(name);
+ }
+ }
+ checkAddedEntities(added);
+ return this;
+ }
+
public void removeEntities(String... names) {
for (String name : names) {
entities.remove(name);
}
- setUpdateType(UpdateType.UPDATE);
}
public boolean hasEntity(String name) {
return entities.contains(name);
}
+ public Team setName(String name) {
+ currentData.name = name;
+ return this;
+ }
+
public Team setPrefix(String prefix) {
// replace "null" to an empty string,
// we do this here to improve the performance of Score#getDisplayName
if (prefix.length() == 4 && "null".equals(prefix)) {
- this.prefix = "";
+ currentData.prefix = "";
return this;
}
- this.prefix = prefix;
+ currentData.prefix = prefix;
return this;
}
@@ -99,15 +128,92 @@ public class Team {
// replace "null" to an empty string,
// we do this here to improve the performance of Score#getDisplayName
if (suffix.length() == 4 && "null".equals(suffix)) {
- this.suffix = "";
+ currentData.suffix = "";
return this;
}
- this.suffix = suffix;
+ currentData.suffix = suffix;
return this;
}
+ public String getDisplayName(String score) {
+ return cachedData != null ?
+ cachedData.getDisplayName(score) :
+ currentData.getDisplayName(score);
+ }
+
+ public void markUpdated() {
+ updating = false;
+ }
+
+ public boolean shouldUpdate() {
+ return updating || cachedData == null || currentData.updateTime > cachedData.updateTime;
+ }
+
+ public void prepareUpdate() {
+ if (updating) {
+ return;
+ }
+ updating = true;
+
+ if (cachedData == null) {
+ cachedData = new TeamData();
+ cachedData.updateType = currentData.updateType != UpdateType.REMOVE ? UpdateType.ADD : UpdateType.REMOVE;
+ } else {
+ cachedData.updateType = currentData.updateType;
+ }
+
+ cachedData.updateTime = currentData.updateTime;
+ cachedData.name = currentData.name;
+ cachedData.prefix = currentData.prefix;
+ cachedData.suffix = currentData.suffix;
+ }
+
+ public UpdateType getUpdateType() {
+ return cachedData != null ? cachedData.updateType : currentData.updateType;
+ }
+
+ public Team setUpdateType(UpdateType updateType) {
+ if (updateType != UpdateType.NOTHING) {
+ currentData.updateTime = System.currentTimeMillis();
+ }
+ currentData.updateType = updateType;
+ return this;
+ }
+
+ public boolean isVisibleFor(String entity) {
+ switch (nameTagVisibility) {
+ case HIDE_FOR_OTHER_TEAMS:
+ return hasEntity(entity);
+ case HIDE_FOR_OWN_TEAM:
+ return !hasEntity(entity);
+ case ALWAYS:
+ return true;
+ case NEVER:
+ return false;
+ }
+ return true;
+ }
+
@Override
public int hashCode() {
return id.hashCode();
}
+
+ @Getter
+ public static final class TeamData {
+ protected UpdateType updateType;
+ protected long updateTime;
+
+ protected String name;
+ protected String prefix;
+ protected String suffix;
+
+ protected TeamData() {
+ updateType = UpdateType.ADD;
+ }
+
+ public String getDisplayName(String score) {
+ return prefix + score + suffix;
+ }
+ }
}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java
index 0ae31b333..e8fd82918 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java
@@ -33,17 +33,17 @@ import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator;
public class BlockEntityUtils {
-
private static final BlockEntityTranslator EMPTY_TRANSLATOR = BlockEntityTranslator.BLOCK_ENTITY_TRANSLATORS.get("Empty");
public static String getBedrockBlockEntityId(String id) {
// These are the only exceptions when it comes to block entity ids
- if (BlockEntityTranslator.BLOCK_ENTITY_TRANSLATIONS.containsKey(id)) {
- return BlockEntityTranslator.BLOCK_ENTITY_TRANSLATIONS.get(id);
+ String value = BlockEntityTranslator.BLOCK_ENTITY_TRANSLATIONS.get(id);
+ if (value != null) {
+ return value;
}
id = id.replace("minecraft:", "")
- .replace("_", " ");
+ .replace("_", " ");
// Split at every space or capital letter - for the latter, some legacy Java block entity tags are the correct format already
String[] words;
if (!id.toUpperCase().equals(id)) { // Otherwise we get [S, K, U, L, L]
@@ -60,11 +60,10 @@ public class BlockEntityUtils {
public static BlockEntityTranslator getBlockEntityTranslator(String name) {
BlockEntityTranslator blockEntityTranslator = BlockEntityTranslator.BLOCK_ENTITY_TRANSLATORS.get(name);
- if (blockEntityTranslator == null) {
- return EMPTY_TRANSLATOR;
+ if (blockEntityTranslator != null) {
+ return blockEntityTranslator;
}
-
- return blockEntityTranslator;
+ return EMPTY_TRANSLATOR;
}
public static void updateBlockEntity(GeyserSession session, NbtMap blockEntity, Position position) {
diff --git a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java
index a63eeb424..005a4960e 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java
@@ -28,6 +28,7 @@ package org.geysermc.connector.utils;
import com.github.steveice10.mc.protocol.data.game.chunk.BitStorage;
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
import com.github.steveice10.mc.protocol.data.game.chunk.Column;
+import com.github.steveice10.mc.protocol.data.game.chunk.palette.GlobalPalette;
import com.github.steveice10.mc.protocol.data.game.chunk.palette.Palette;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
@@ -65,16 +66,17 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.BitSet;
-import java.util.Collections;
import java.util.List;
-import static org.geysermc.connector.network.translators.world.block.BlockTranslator.*;
+import static org.geysermc.connector.network.translators.world.block.BlockTranslator.JAVA_AIR_ID;
+import static org.geysermc.connector.network.translators.world.block.BlockTranslator.BEDROCK_AIR_ID;
+import static org.geysermc.connector.network.translators.world.block.BlockTranslator.BEDROCK_WATER_ID;
@UtilityClass
public class ChunkUtils {
-
/**
- * Temporarily stores positions of BlockState values that are needed for certain block entities actively
+ * Temporarily stores positions of BlockState values that are needed for certain block entities actively.
+ * Not used if cache chunks is enabled
*/
public static final Object2IntMap CACHED_BLOCK_ENTITIES = new Object2IntOpenHashMap<>();
@@ -107,7 +109,7 @@ public class ChunkUtils {
ChunkSection[] sections = new ChunkSection[javaSections.length];
// Temporarily stores compound tags of Bedrock-only block entities
- List bedrockOnlyBlockEntities = Collections.emptyList();
+ List bedrockOnlyBlockEntities = new ArrayList<>();
BitSet waterloggedPaletteIds = new BitSet();
BitSet pistonOrFlowerPaletteIds = new BitSet();
@@ -155,6 +157,33 @@ public class ChunkUtils {
}
Palette javaPalette = javaSection.getPalette();
+ BitStorage javaData = javaSection.getStorage();
+
+ if (javaPalette instanceof GlobalPalette) {
+ // As this is the global palette, simply iterate through the whole chunk section once
+ ChunkSection section = new ChunkSection();
+ for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) {
+ int javaId = javaData.get(yzx);
+ int bedrockId = BlockTranslator.getBedrockBlockId(javaId);
+ int xzy = indexYZXtoXZY(yzx);
+ section.getBlockStorageArray()[0].setFullBlock(xzy, bedrockId);
+
+ if (BlockTranslator.isWaterlogged(javaId)) {
+ section.getBlockStorageArray()[1].setFullBlock(xzy, BEDROCK_WATER_ID);
+ }
+
+ // Check if block is piston or flower to see if we'll need to create additional block entities, as they're only block entities in Bedrock
+ if (BlockStateValues.getFlowerPotValues().containsKey(javaId) || BlockStateValues.getPistonValues().containsKey(javaId)) {
+ bedrockOnlyBlockEntities.add(BedrockOnlyBlockEntity.getTag(
+ Vector3i.from((column.getX() << 4) + (yzx & 0xF), (sectionY << 4) + ((yzx >> 8) & 0xF), (column.getZ() << 4) + ((yzx >> 4) & 0xF)),
+ javaId
+ ));
+ }
+ }
+ sections[sectionY] = section;
+ continue;
+ }
+
IntList bedrockPalette = new IntArrayList(javaPalette.size());
waterloggedPaletteIds.clear();
pistonOrFlowerPaletteIds.clear();
@@ -174,13 +203,10 @@ public class ChunkUtils {
}
}
- BitStorage javaData = javaSection.getStorage();
-
// Add Bedrock-exclusive block entities
// We only if the palette contained any blocks that are Bedrock-exclusive block entities to avoid iterating through the whole block data
// for no reason, as most sections will not contain any pistons or flower pots
if (!pistonOrFlowerPaletteIds.isEmpty()) {
- bedrockOnlyBlockEntities = new ArrayList<>();
for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) {
int paletteId = javaData.get(yzx);
if (pistonOrFlowerPaletteIds.get(paletteId)) {
@@ -221,7 +247,7 @@ public class ChunkUtils {
// V1 palette
IntList layer1Palette = new IntArrayList(2);
- layer1Palette.add(0); // Air
+ layer1Palette.add(BEDROCK_AIR_ID); // Air - see BlockStorage's constructor for more information
layer1Palette.add(BEDROCK_WATER_ID);
layers = new BlockStorage[]{ layer0, new BlockStorage(BitArrayVersion.V1.createArray(BlockStorage.SIZE, layer1Data), layer1Palette) };
@@ -293,18 +319,37 @@ public class ChunkUtils {
}
}
+ /**
+ * Sends a block update to the Bedrock client. If chunk caching is enabled and the platform is not Spigot, this also
+ * adds that block to the cache.
+ * @param session the Bedrock session to send/register the block to
+ * @param blockState the Java block state of the block
+ * @param position the position of the block
+ */
public static void updateBlock(GeyserSession session, int blockState, Position position) {
Vector3i pos = Vector3i.from(position.getX(), position.getY(), position.getZ());
updateBlock(session, blockState, pos);
}
+ /**
+ * Sends a block update to the Bedrock client. If chunk caching is enabled and the platform is not Spigot, this also
+ * adds that block to the cache.
+ * @param session the Bedrock session to send/register the block to
+ * @param blockState the Java block state of the block
+ * @param position the position of the block
+ */
public static void updateBlock(GeyserSession session, int blockState, Vector3i position) {
// Checks for item frames so they aren't tripped up and removed
- if (ItemFrameEntity.positionContainsItemFrame(session, position) && blockState == AIR) {
- ((ItemFrameEntity) session.getEntityCache().getEntityByJavaId(ItemFrameEntity.getItemFrameEntityId(session, position))).updateBlock(session);
- return;
- } else if (ItemFrameEntity.positionContainsItemFrame(session, position)) {
- Entity entity = session.getEntityCache().getEntityByJavaId(ItemFrameEntity.getItemFrameEntityId(session, position));
+ long frameEntityId = ItemFrameEntity.getItemFrameEntityId(session, position);
+ if (frameEntityId != -1) {
+ // TODO: Very occasionally the item frame doesn't sync up when destroyed
+ Entity entity = session.getEntityCache().getEntityByJavaId(frameEntityId);
+ if (blockState == JAVA_AIR_ID && entity != null) { // Item frame is still present and no block overrides that; refresh it
+ ((ItemFrameEntity) entity).updateBlock(session);
+ return;
+ }
+
+ // Otherwise the item frame is gone
if (entity != null) {
session.getEntityCache().removeEntity(entity, false);
} else {
@@ -328,7 +373,7 @@ public class ChunkUtils {
if (BlockTranslator.isWaterlogged(blockState)) {
waterPacket.setRuntimeId(BEDROCK_WATER_ID);
} else {
- waterPacket.setRuntimeId(0);
+ waterPacket.setRuntimeId(BEDROCK_AIR_ID);
}
session.sendUpstreamPacket(waterPacket);
@@ -342,7 +387,10 @@ public class ChunkUtils {
((BedrockOnlyBlockEntity) requiresBlockState).updateBlock(session, blockState, position);
break;
}
- CACHED_BLOCK_ENTITIES.put(new Position(position.getX(), position.getY(), position.getZ()), blockState);
+ if (!session.getConnector().getConfig().isCacheChunks()) {
+ // Blocks aren't saved to a chunk cache; resort to this smaller cache
+ CACHED_BLOCK_ENTITIES.put(new Position(position.getX(), position.getY(), position.getZ()), blockState);
+ }
break; //No block will be a part of two classes
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java
index 7b283e9cb..f8083108c 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java
@@ -41,17 +41,29 @@ public class DimensionUtils {
// Changes if the above-bedrock Nether building workaround is applied
private static int BEDROCK_NETHER_ID = 1;
- // Static references to all vanilla dimensions
+ /**
+ * String reference to vanilla Java overworld dimension identifier
+ */
public static final String OVERWORLD = "minecraft:overworld";
+ /**
+ * String reference to vanilla Java nether dimension identifier
+ */
public static final String NETHER = "minecraft:the_nether";
+ /**
+ * String reference to vanilla Java end dimension identifier
+ */
public static final String THE_END = "minecraft:the_end";
public static void switchDimension(GeyserSession session, String javaDimension) {
int bedrockDimension = javaToBedrock(javaDimension);
Entity player = session.getPlayerEntity();
- if (javaDimension.equals(player.getDimension()))
+ if (javaDimension.equals(session.getDimension()))
return;
+ if (session.getMovementSendIfIdle() != null) {
+ session.getMovementSendIfIdle().cancel(true);
+ }
+
session.getEntityCache().removeAllEntities();
session.getItemFrameCache().clear();
if (session.getPendingDimSwitches().getAndIncrement() > 0) {
@@ -65,7 +77,7 @@ public class DimensionUtils {
changeDimensionPacket.setRespawn(true);
changeDimensionPacket.setPosition(pos.toFloat());
session.sendUpstreamPacket(changeDimensionPacket);
- player.setDimension(javaDimension);
+ session.setDimension(javaDimension);
player.setPosition(pos.toFloat());
session.setSpawned(false);
session.setLastChunkPosition(null);
@@ -111,23 +123,30 @@ public class DimensionUtils {
/**
* Determines the new dimension based on the {@link CompoundTag} sent by either the {@link com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket}
* or {@link com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket}.
+ *
* @param dimensionTag the packet's dimension tag.
* @return the dimension identifier.
*/
public static String getNewDimension(CompoundTag dimensionTag) {
if (dimensionTag == null || dimensionTag.isEmpty()) {
GeyserConnector.getInstance().getLogger().debug("Dimension tag was null or empty.");
- return "minecraft:overworld";
+ return OVERWORLD;
}
if (dimensionTag.getValue().get("effects") != null) {
return ((StringTag) dimensionTag.getValue().get("effects")).getValue();
}
GeyserConnector.getInstance().getLogger().debug("Effects portion of the tag was null or empty.");
- return "minecraft:overworld";
+ return OVERWORLD;
}
- public static void changeBedrockNetherId() {
+ /**
+ * The Nether dimension in Bedrock does not permit building above Y128 - the Bedrock above the dimension.
+ * This workaround sets the Nether as the End dimension to ignore this limit.
+ *
+ * @param isAboveNetherBedrockBuilding true if we should apply The End workaround
+ */
+ public static void changeBedrockNetherId(boolean isAboveNetherBedrockBuilding) {
// Change dimension ID to the End to allow for building above Bedrock
- BEDROCK_NETHER_ID = 2;
+ BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? 2 : 1;
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java
index 63255cfa0..0b2b132ab 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java
@@ -159,7 +159,8 @@ public class FileUtils {
}
/**
- * Calculate the SHA256 hash of the resource pack file
+ * Calculate the SHA256 hash of a file
+ *
* @param file File to calculate the hash for
* @return A byte[] representation of the hash
*/
@@ -175,6 +176,24 @@ public class FileUtils {
return sha256;
}
+ /**
+ * Calculate the SHA1 hash of a file
+ *
+ * @param file File to calculate the hash for
+ * @return A byte[] representation of the hash
+ */
+ public static byte[] calculateSHA1(File file) {
+ byte[] sha1;
+
+ try {
+ sha1 = MessageDigest.getInstance("SHA-1").digest(Files.readAllBytes(file.toPath()));
+ } catch (Exception e) {
+ throw new RuntimeException("Could not calculate pack hash", e);
+ }
+
+ return sha1;
+ }
+
/**
* Get the stored reflection data for a given path
*
diff --git a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java
index 11e81eee1..4e9e4b003 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java
@@ -47,7 +47,7 @@ public class LocaleUtils {
private static final Map ASSET_MAP = new HashMap<>();
- private static String smallestURL = "";
+ private static VersionDownload clientJarInfo;
static {
// Create the locales folder
@@ -87,9 +87,8 @@ public class LocaleUtils {
// Get the client jar for use when downloading the en_us locale
GeyserConnector.getInstance().getLogger().debug(GeyserConnector.JSON_MAPPER.writeValueAsString(versionInfo.getDownloads()));
- VersionDownload download = versionInfo.getDownloads().get("client");
- GeyserConnector.getInstance().getLogger().debug(GeyserConnector.JSON_MAPPER.writeValueAsString(download));
- smallestURL = download.getUrl();
+ clientJarInfo = versionInfo.getDownloads().get("client");
+ GeyserConnector.getInstance().getLogger().debug(GeyserConnector.JSON_MAPPER.writeValueAsString(clientJarInfo));
// Get the assets list
JsonNode assets = GeyserConnector.JSON_MAPPER.readTree(WebUtils.getBody(versionInfo.getAssetIndex().getUrl())).get("objects");
@@ -136,8 +135,28 @@ public class LocaleUtils {
// Check if we have already downloaded the locale file
if (localeFile.exists()) {
- GeyserConnector.getInstance().getLogger().debug("Locale already downloaded: " + locale);
- return;
+ String curHash = "";
+ String targetHash = "";
+
+ if (locale.equals("en_us")) {
+ try {
+ Path hashFile = localeFile.getParentFile().toPath().resolve("en_us.hash");
+ if (hashFile.toFile().exists()) {
+ curHash = String.join("", Files.readAllLines(hashFile));
+ }
+ } catch (IOException ignored) { }
+ targetHash = clientJarInfo.getSha1();
+ } else {
+ curHash = byteArrayToHexString(FileUtils.calculateSHA1(localeFile));
+ targetHash = ASSET_MAP.get("minecraft/lang/" + locale + ".json").getHash();
+ }
+
+ if (!curHash.equals(targetHash)) {
+ GeyserConnector.getInstance().getLogger().debug("Locale out of date; re-downloading: " + locale);
+ } else {
+ GeyserConnector.getInstance().getLogger().debug("Locale already downloaded and up-to date: " + locale);
+ return;
+ }
}
// Create the en_us locale
@@ -202,11 +221,11 @@ public class LocaleUtils {
try {
// Let the user know we are downloading the JAR
GeyserConnector.getInstance().getLogger().info(LanguageUtils.getLocaleStringLog("geyser.locale.download.en_us"));
- GeyserConnector.getInstance().getLogger().debug("Download URL: " + smallestURL);
+ GeyserConnector.getInstance().getLogger().debug("Download URL: " + clientJarInfo.getUrl());
// Download the smallest JAR (client or server)
Path tmpFilePath = GeyserConnector.getInstance().getBootstrap().getConfigFolder().resolve("tmp_locale.jar");
- WebUtils.downloadFile(smallestURL, tmpFilePath.toString());
+ WebUtils.downloadFile(clientJarInfo.getUrl(), tmpFilePath.toString());
// Load in the JAR as a zip and extract the file
ZipFile localeJar = new ZipFile(tmpFilePath.toString());
@@ -227,6 +246,9 @@ public class LocaleUtils {
fileStream.close();
localeJar.close();
+ // Store the latest jar hash
+ FileUtils.writeFile(localeFile.getParentFile().toPath().resolve("en_us.hash").toString(), clientJarInfo.getSha1().toCharArray());
+
// Delete the nolonger needed client/server jar
Files.delete(tmpFilePath);
} catch (Exception e) {
@@ -243,17 +265,32 @@ public class LocaleUtils {
*/
public static String getLocaleString(String messageText, String locale) {
Map localeStrings = LocaleUtils.LOCALE_MAPPINGS.get(locale.toLowerCase());
- if (localeStrings == null)
- localeStrings = LocaleUtils.LOCALE_MAPPINGS.get(LanguageUtils.getDefaultLocale());
if (localeStrings == null) {
- // Don't cause a NPE if the locale is STILL missing
- GeyserConnector.getInstance().getLogger().debug("MISSING DEFAULT LOCALE: " + LanguageUtils.getDefaultLocale());
- return messageText;
+ localeStrings = LocaleUtils.LOCALE_MAPPINGS.get(LanguageUtils.getDefaultLocale());
+ if (localeStrings == null) {
+ // Don't cause a NPE if the locale is STILL missing
+ GeyserConnector.getInstance().getLogger().debug("MISSING DEFAULT LOCALE: " + LanguageUtils.getDefaultLocale());
+ return messageText;
+ }
}
return localeStrings.getOrDefault(messageText, messageText);
}
+ /**
+ * Convert a byte array into a hex string
+ *
+ * @param b Byte array to convert
+ * @return The hex representation of the given byte array
+ */
+ private static String byteArrayToHexString(byte[] b) {
+ StringBuilder result = new StringBuilder();
+ for (byte value : b) {
+ result.append(Integer.toString((value & 0xff) + 0x100, 16).substring(1));
+ }
+ return result.toString();
+ }
+
public static void init() {
// no-op
}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java
deleted file mode 100644
index b5a2bfdcc..000000000
--- a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright (c) 2019-2020 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.connector.utils;
-
-import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor;
-import com.github.steveice10.mc.protocol.data.message.Message;
-import com.github.steveice10.mc.protocol.data.message.MessageSerializer;
-import com.github.steveice10.mc.protocol.data.message.TextMessage;
-import com.github.steveice10.mc.protocol.data.message.TranslationMessage;
-import com.github.steveice10.mc.protocol.data.message.style.ChatColor;
-import com.github.steveice10.mc.protocol.data.message.style.ChatFormat;
-import com.github.steveice10.mc.protocol.data.message.style.MessageStyle;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import net.kyori.adventure.text.Component;
-import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
-import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
-import org.geysermc.connector.network.session.GeyserSession;
-
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class MessageUtils {
-
- private static final Map COLORS = new HashMap<>();
- private static final Map TEAM_COLORS = new HashMap<>();
-
- static {
- COLORS.put(ChatColor.BLACK, 0x000000);
- COLORS.put(ChatColor.DARK_BLUE, 0x0000aa);
- COLORS.put(ChatColor.DARK_GREEN, 0x00aa00);
- COLORS.put(ChatColor.DARK_AQUA, 0x00aaaa);
- COLORS.put(ChatColor.DARK_RED, 0xaa0000);
- COLORS.put(ChatColor.DARK_PURPLE, 0xaa00aa);
- COLORS.put(ChatColor.GOLD, 0xffaa00);
- COLORS.put(ChatColor.GRAY, 0xaaaaaa);
- COLORS.put(ChatColor.DARK_GRAY, 0x555555);
- COLORS.put(ChatColor.BLUE, 0x5555ff);
- COLORS.put(ChatColor.GREEN, 0x55ff55);
- COLORS.put(ChatColor.AQUA, 0x55ffff);
- COLORS.put(ChatColor.RED, 0xff5555);
- COLORS.put(ChatColor.LIGHT_PURPLE, 0xff55ff);
- COLORS.put(ChatColor.YELLOW, 0xffff55);
- COLORS.put(ChatColor.WHITE, 0xffffff);
-
- TEAM_COLORS.put(TeamColor.BLACK, getColor(ChatColor.BLACK));
- TEAM_COLORS.put(TeamColor.DARK_BLUE, getColor(ChatColor.DARK_BLUE));
- TEAM_COLORS.put(TeamColor.DARK_GREEN, getColor(ChatColor.DARK_GREEN));
- TEAM_COLORS.put(TeamColor.DARK_AQUA, getColor(ChatColor.DARK_AQUA));
- TEAM_COLORS.put(TeamColor.DARK_RED, getColor(ChatColor.DARK_RED));
- TEAM_COLORS.put(TeamColor.DARK_PURPLE, getColor(ChatColor.DARK_PURPLE));
- TEAM_COLORS.put(TeamColor.GOLD, getColor(ChatColor.GOLD));
- TEAM_COLORS.put(TeamColor.GRAY, getColor(ChatColor.GRAY));
- TEAM_COLORS.put(TeamColor.DARK_GRAY, getColor(ChatColor.DARK_GRAY));
- TEAM_COLORS.put(TeamColor.BLUE, getColor(ChatColor.BLUE));
- TEAM_COLORS.put(TeamColor.GREEN, getColor(ChatColor.GREEN));
- TEAM_COLORS.put(TeamColor.AQUA, getColor(ChatColor.AQUA));
- TEAM_COLORS.put(TeamColor.RED, getColor(ChatColor.RED));
- TEAM_COLORS.put(TeamColor.LIGHT_PURPLE, getColor(ChatColor.LIGHT_PURPLE));
- TEAM_COLORS.put(TeamColor.YELLOW, getColor(ChatColor.YELLOW));
- TEAM_COLORS.put(TeamColor.WHITE, getColor(ChatColor.WHITE));
- TEAM_COLORS.put(TeamColor.OBFUSCATED, getFormat(Collections.singletonList(ChatFormat.OBFUSCATED)));
- TEAM_COLORS.put(TeamColor.BOLD, getFormat(Collections.singletonList(ChatFormat.BOLD)));
- TEAM_COLORS.put(TeamColor.STRIKETHROUGH, getFormat(Collections.singletonList(ChatFormat.STRIKETHROUGH)));
- TEAM_COLORS.put(TeamColor.ITALIC, getFormat(Collections.singletonList(ChatFormat.ITALIC)));
- }
-
- /**
- * Recursively parse each message from a list for usage in a {@link TranslationMessage}
- *
- * @param messages A {@link List} of {@link Message} to parse
- * @param locale A locale loaded to get the message for
- * @param parent A {@link Message} to use as the parent (can be null)
- * @return the translation parameters
- */
- public static List getTranslationParams(List messages, String locale, Message parent) {
- List strings = new ArrayList<>();
- for (Message message : messages) {
- message = fixMessageStyle(message, parent);
-
- if (message instanceof TranslationMessage) {
- TranslationMessage translation = (TranslationMessage) message;
-
- if (locale == null) {
- String builder = "%" + translation.getKey();
- strings.add(builder);
- }
-
- // Collect all params and add format corrections to the end of them
- List furtherParams = new ArrayList<>();
- for (String param : getTranslationParams(translation.getWith(), locale, message)) {
- String newParam = param;
- if (parent.getStyle().getFormats().size() != 0) {
- newParam += getFormat(parent.getStyle().getFormats());
- }
- if (parent.getStyle().getColor() != ChatColor.NONE) {
- newParam += getColor(parent.getStyle().getColor());
- }
-
- furtherParams.add(newParam);
- }
-
- if (locale != null) {
- String builder = getFormat(message.getStyle().getFormats()) +
- getColor(message.getStyle().getColor());
- builder += insertParams(LocaleUtils.getLocaleString(translation.getKey(), locale), furtherParams);
- strings.add(builder);
- } else {
- String format = getFormat(message.getStyle().getFormats()) +
- getColor(message.getStyle().getColor());
- for (String param : furtherParams) {
- strings.add(format + param);
- }
- }
- } else {
- String builder = getFormat(message.getStyle().getFormats()) +
- getColor(message.getStyle().getColor());
- builder += getTranslatedBedrockMessage(message, locale, false, parent);
- strings.add(builder);
- }
- }
-
- return strings;
- }
-
- public static String getTranslatedBedrockMessage(Message message, String locale) {
- return getTranslatedBedrockMessage(message, locale, true);
- }
-
- public static String getTranslatedBedrockMessage(Message message, String locale, boolean shouldTranslate) {
- return getTranslatedBedrockMessage(message, locale, shouldTranslate, null);
- }
-
- /**
- * Translate a given {@link TranslationMessage} to the given locale
- *
- * @param message The {@link Message} to send
- * @param locale the locale
- * @param shouldTranslate if the message should be translated
- * @param parent the parent message
- * @return the given translation message translated from the given locale
- */
- public static String getTranslatedBedrockMessage(Message message, String locale, boolean shouldTranslate, Message parent) {
- JsonParser parser = new JsonParser();
- if (isMessage(message.toString())) {
- JsonObject object = parser.parse(message.toString()).getAsJsonObject();
- message = MessageSerializer.fromJson(object);
- }
-
- message = fixMessageStyle(message, parent);
-
- String messageText = (message instanceof TranslationMessage) ? ((TranslationMessage) message).getKey() : ((TextMessage) message).getText();
- if (locale != null && shouldTranslate) {
- messageText = LocaleUtils.getLocaleString(messageText, locale);
- }
-
- StringBuilder builder = new StringBuilder();
- builder.append(getFormat(message.getStyle().getFormats()));
- builder.append(getColor(message.getStyle().getColor()));
- builder.append(messageText);
-
- for (Message msg : message.getExtra()) {
- builder.append(getFormat(msg.getStyle().getFormats()));
- builder.append(getColor(msg.getStyle().getColor()));
- if (!(msg.toString() == null)) {
- boolean isTranslationMessage = (msg instanceof TranslationMessage);
- String extraText = "";
-
- if (isTranslationMessage) {
- List paramsTranslated = getTranslationParams(((TranslationMessage) msg).getWith(), locale, message);
- extraText = insertParams(getTranslatedBedrockMessage(msg, locale, isTranslationMessage, message), paramsTranslated);
- } else {
- extraText = getTranslatedBedrockMessage(msg, locale, isTranslationMessage, message);
- }
-
- builder.append(extraText);
- builder.append("\u00a7r");
- }
- }
-
- return builder.toString();
- }
-
- /**
- * If the passed {@link Message} color or format are empty then copy from parent
- *
- * @param message {@link Message} to update
- * @param parent Parent {@link Message} for style
- * @return The updated {@link Message}
- */
- private static Message fixMessageStyle(Message message, Message parent) {
- if (parent == null) {
- return message;
- }
- MessageStyle.Builder styleBuilder = message.getStyle().toBuilder();
-
- // Copy color from parent
- if (message.getStyle().getColor() == ChatColor.NONE) {
- styleBuilder.color(parent.getStyle().getColor());
- }
-
- // Copy formatting from parent
- if (message.getStyle().getFormats().size() == 0) {
- styleBuilder.formats(parent.getStyle().getFormats());
- }
-
- return message.toBuilder().style(styleBuilder.build()).build();
- }
-
- public static String getBedrockMessage(Message message) {
- if (isMessage(((TextMessage) message).getText())) {
- return getBedrockMessage(((TextMessage) message).getText());
- } else {
- return getBedrockMessage(MessageSerializer.toJsonString(message));
- }
- }
-
- /**
- * Verifies the message is valid JSON in case it's plaintext. Works around GsonComponentSeraializer not using lenient mode.
- * See https://wiki.vg/Chat for messages sent in lenient mode, and for a description on leniency.
- *
- * @param message Potentially lenient JSON message
- * @return Bedrock formatted message
- */
- public static String getBedrockMessageLenient(String message) {
- if (isMessage(message)) {
- return getBedrockMessage(message);
- } else {
- final JsonObject obj = new JsonObject();
- obj.addProperty("text", message);
- return getBedrockMessage(obj.toString());
- }
- }
-
- public static String getBedrockMessage(String message) {
- Component component = phraseJavaMessage(message);
- return LegacyComponentSerializer.legacySection().serialize(component);
- }
-
- public static Component phraseJavaMessage(String message) {
- return GsonComponentSerializer.gson().deserialize(message);
- }
-
- public static String getJavaMessage(String message) {
- Component component = LegacyComponentSerializer.legacySection().deserialize(message);
- return GsonComponentSerializer.gson().serialize(component);
- }
-
- /**
- * Inserts the given parameters into the given message both in sequence and as requested
- *
- * @param message Message containing possible parameter replacement strings
- * @param params A list of parameter strings
- * @return Parsed message with all params inserted as needed
- */
- public static String insertParams(String message, List params) {
- String newMessage = message;
-
- Pattern p = Pattern.compile("%([1-9])\\$s");
- Matcher m = p.matcher(message);
- while (m.find()) {
- try {
- newMessage = newMessage.replaceFirst("%" + m.group(1) + "\\$s", params.get(Integer.parseInt(m.group(1)) - 1));
- } catch (Exception e) {
- // Couldn't find the param to replace
- }
- }
-
- for (String text : params) {
- newMessage = newMessage.replaceFirst("%s", text.replaceAll("%s", "%r"));
- }
-
- newMessage = newMessage.replaceAll("%r", "MISSING!");
-
- return newMessage;
- }
-
- /**
- * Convert a ChatColor into a string for inserting into messages
- *
- * @param color ChatColor to convert
- * @return The converted color string
- */
- private static String getColor(String color) {
- String base = "\u00a7";
- switch (color) {
- case ChatColor.BLACK:
- base += "0";
- break;
- case ChatColor.DARK_BLUE:
- base += "1";
- break;
- case ChatColor.DARK_GREEN:
- base += "2";
- break;
- case ChatColor.DARK_AQUA:
- base += "3";
- break;
- case ChatColor.DARK_RED:
- base += "4";
- break;
- case ChatColor.DARK_PURPLE:
- base += "5";
- break;
- case ChatColor.GOLD:
- base += "6";
- break;
- case ChatColor.GRAY:
- base += "7";
- break;
- case ChatColor.DARK_GRAY:
- base += "8";
- break;
- case ChatColor.BLUE:
- base += "9";
- break;
- case ChatColor.GREEN:
- base += "a";
- break;
- case ChatColor.AQUA:
- base += "b";
- break;
- case ChatColor.RED:
- base += "c";
- break;
- case ChatColor.LIGHT_PURPLE:
- base += "d";
- break;
- case ChatColor.YELLOW:
- base += "e";
- break;
- case ChatColor.WHITE:
- base += "f";
- break;
- case ChatColor.RESET:
- //case NONE:
- base += "r";
- break;
- case "": // To stop recursion
- return "";
- default:
- return getClosestColor(color);
- }
-
- return base;
- }
-
- /**
- * Based on https://github.com/ViaVersion/ViaBackwards/blob/master/core/src/main/java/nl/matsv/viabackwards/protocol/protocol1_15_2to1_16/chat/TranslatableRewriter1_16.java
- *
- * @param color A color string
- * @return The closest color to that string
- */
- private static String getClosestColor(String color) {
- if (!color.startsWith("#")) {
- return "";
- }
-
- int rgb = Integer.parseInt(color.substring(1), 16);
- int r = (rgb >> 16) & 0xFF;
- int g = (rgb >> 8) & 0xFF;
- int b = rgb & 0xFF;
-
- String closest = null;
- int smallestDiff = 0;
-
- for (Map.Entry testColor : COLORS.entrySet()) {
- if (testColor.getValue() == rgb) {
- closest = testColor.getKey();
- break;
- }
-
- int testR = (testColor.getValue() >> 16) & 0xFF;
- int testG = (testColor.getValue() >> 8) & 0xFF;
- int testB = testColor.getValue() & 0xFF;
-
- // Check by the greatest diff of the 3 values
- int rAverage = (testR + r) / 2;
- int rDiff = testR - r;
- int gDiff = testG - g;
- int bDiff = testB - b;
- int diff = ((2 + (rAverage >> 8)) * rDiff * rDiff)
- + (4 * gDiff * gDiff)
- + ((2 + ((255 - rAverage) >> 8)) * bDiff * bDiff);
- if (closest == null || diff < smallestDiff) {
- closest = testColor.getKey();
- smallestDiff = diff;
- }
- }
-
- return getColor(closest);
- }
-
- /**
- * Convert a list of ChatFormats into a string for inserting into messages
- *
- * @param formats ChatFormats to convert
- * @return The converted chat formatting string
- */
- private static String getFormat(List formats) {
- StringBuilder str = new StringBuilder();
- for (ChatFormat cf : formats) {
- String base = "\u00a7";
- switch (cf) {
- case OBFUSCATED:
- base += "k";
- break;
- case BOLD:
- base += "l";
- break;
- case STRIKETHROUGH:
- base += "m";
- break;
- case UNDERLINED:
- base += "n";
- break;
- case ITALIC:
- base += "o";
- break;
- default:
- return "";
- }
-
- str.append(base);
- }
-
- return str.toString();
- }
-
- /**
- * Checks if the given text string is a json message
- *
- * @param text String to test
- * @return True if its a valid message json string, false if not
- */
- public static boolean isMessage(String text) {
- JsonParser parser = new JsonParser();
- try {
- JsonObject object = parser.parse(text).getAsJsonObject();
- try {
- MessageSerializer.fromJson(object);
- } catch (Exception ex) {
- return false;
- }
- } catch (Exception ex) {
- return false;
- }
- return true;
- }
-
- public static String toChatColor(TeamColor teamColor) {
- return TEAM_COLORS.getOrDefault(teamColor, "");
- }
-
- /**
- * Checks if the given message is over 256 characters (Java edition server chat limit) and sends a message to the user if it is
- *
- * @param message Message to check
- * @param session GeyserSession for the user
- * @return True if the message is too long, false if not
- */
- public static boolean isTooLong(String message, GeyserSession session) {
- if (message.length() > 256) {
- session.sendMessage(LanguageUtils.getPlayerLocaleString("geyser.chat.too_long", session.getLocale(), message.length()));
- return true;
- }
-
- return false;
- }
-}
diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java
index 530c551ab..8b9e7ee5e 100644
--- a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java
+++ b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java
@@ -606,7 +606,7 @@ public class SkinProvider {
public enum CapeProvider {
MINECRAFT,
OPTIFINE("https://optifine.net/capes/%s.png", CapeUrlType.USERNAME),
- LABYMOD("https://www.labymod.net/page/php/getCapeTexture.php?uuid=%s", CapeUrlType.UUID_DASHED),
+ LABYMOD("https://dl.labymod.net/capes/%s", CapeUrlType.UUID_DASHED),
FIVEZIG("https://textures.5zigreborn.eu/profile/%s", CapeUrlType.UUID_DASHED),
MINECRAFTCAPES("https://minecraftcapes.net/profile/%s/cape", CapeUrlType.UUID);
diff --git a/connector/src/main/resources/bedrock/blockpalette.nbt b/connector/src/main/resources/bedrock/blockpalette.nbt
new file mode 100644
index 000000000..b92a06260
Binary files /dev/null and b/connector/src/main/resources/bedrock/blockpalette.nbt differ
diff --git a/connector/src/main/resources/bedrock/creative_items.json b/connector/src/main/resources/bedrock/creative_items.json
index eea92a950..90839b0dc 100644
--- a/connector/src/main/resources/bedrock/creative_items.json
+++ b/connector/src/main/resources/bedrock/creative_items.json
@@ -258,31 +258,31 @@
"id" : -275
},
{
- "id" : 324
+ "id" : 359
},
{
- "id" : 427
+ "id" : 543
},
{
- "id" : 428
+ "id" : 544
},
{
- "id" : 429
+ "id" : 545
},
{
- "id" : 430
+ "id" : 546
},
{
- "id" : 431
+ "id" : 547
},
{
- "id" : 330
+ "id" : 370
},
{
- "id" : 755
+ "id" : 604
},
{
- "id" : 756
+ "id" : 605
},
{
"id" : 96
@@ -314,9 +314,6 @@
{
"id" : 101
},
- {
- "id" : 758
- },
{
"id" : 20
},
@@ -741,66 +738,15 @@
{
"id" : 170
},
- {
- "id" : -239
- },
{
"id" : 216
},
- {
- "id" : 214
- },
- {
- "id" : -227
- },
{
"id" : 112
},
{
"id" : 215
},
- {
- "id" : -225
- },
- {
- "id" : -226
- },
- {
- "id" : -240
- },
- {
- "id" : -241
- },
- {
- "id" : -299
- },
- {
- "id" : -298
- },
- {
- "id" : -300
- },
- {
- "id" : -301
- },
- {
- "id" : -230
- },
- {
- "id" : -232
- },
- {
- "id" : -233
- },
- {
- "id" : -234
- },
- {
- "id" : -235
- },
- {
- "id" : -236
- },
{
"id" : -270
},
@@ -1183,6 +1129,30 @@
"id" : 201,
"damage" : 2
},
+ {
+ "id" : 214
+ },
+ {
+ "id" : -227
+ },
+ {
+ "id" : -230
+ },
+ {
+ "id" : -232
+ },
+ {
+ "id" : -233
+ },
+ {
+ "id" : -234
+ },
+ {
+ "id" : -235
+ },
+ {
+ "id" : -236
+ },
{
"id" : 3
},
@@ -1190,6 +1160,9 @@
"id" : 3,
"damage" : 1
},
+ {
+ "id" : 60
+ },
{
"id" : 2
},
@@ -1318,6 +1291,18 @@
{
"id" : -9
},
+ {
+ "id" : -225
+ },
+ {
+ "id" : -240
+ },
+ {
+ "id" : -226
+ },
+ {
+ "id" : -241
+ },
{
"id" : -212
},
@@ -1365,6 +1350,18 @@
"id" : -212,
"damage" : 13
},
+ {
+ "id" : -299
+ },
+ {
+ "id" : -300
+ },
+ {
+ "id" : -298
+ },
+ {
+ "id" : -301
+ },
{
"id" : 18
},
@@ -1411,59 +1408,58 @@
"damage" : 5
},
{
- "id" : -218,
- "damage" : 3
+ "id" : -218
+ },
+ {
+ "id" : 291
+ },
+ {
+ "id" : 292
+ },
+ {
+ "id" : 293
},
{
"id" : 295
},
{
- "id" : 361
+ "id" : 334
},
{
- "id" : 362
+ "id" : 285
},
{
- "id" : 458
+ "id" : 280
},
{
- "id" : 296
+ "id" : 282
},
{
- "id" : 457
+ "id" : 279
},
{
- "id" : 392
+ "id" : 283
},
{
- "id" : 394
+ "id" : 257
},
{
- "id" : 391
+ "id" : 258
},
{
- "id" : 396
- },
- {
- "id" : 260
- },
- {
- "id" : 322
- },
- {
- "id" : 466
+ "id" : 259
},
{
"id" : 103
},
{
- "id" : 360
+ "id" : 272
},
{
- "id" : 382
+ "id" : 432
},
{
- "id" : 477
+ "id" : 287
},
{
"id" : 86
@@ -1475,7 +1471,7 @@
"id" : 91
},
{
- "id" : 736
+ "id" : 580
},
{
"id" : 31,
@@ -1494,7 +1490,7 @@
"damage" : 2
},
{
- "id" : 760
+ "id" : 609
},
{
"id" : -131,
@@ -1574,7 +1570,7 @@
"damage" : 4
},
{
- "id" : 335
+ "id" : 380
},
{
"id" : -130
@@ -1650,83 +1646,64 @@
"id" : -216
},
{
- "id" : 351,
- "damage" : 19
+ "id" : 408
},
{
- "id" : 351,
- "damage" : 7
+ "id" : 400
},
{
- "id" : 351,
- "damage" : 8
+ "id" : 401
},
{
- "id" : 351,
- "damage" : 16
+ "id" : 393
},
{
- "id" : 351,
- "damage" : 17
+ "id" : 396
},
{
- "id" : 351,
- "damage" : 1
+ "id" : 394
},
{
- "id" : 351,
- "damage" : 14
+ "id" : 407
},
{
- "id" : 351,
- "damage" : 11
+ "id" : 404
},
{
- "id" : 351,
- "damage" : 10
+ "id" : 403
},
{
- "id" : 351,
- "damage" : 2
+ "id" : 395
},
{
- "id" : 351,
- "damage" : 6
+ "id" : 399
},
{
- "id" : 351,
- "damage" : 12
+ "id" : 405
},
{
- "id" : 351,
- "damage" : 18
+ "id" : 397
},
{
- "id" : 351,
- "damage" : 5
+ "id" : 398
},
{
- "id" : 351,
- "damage" : 13
+ "id" : 406
},
{
- "id" : 351,
- "damage" : 9
+ "id" : 402
},
{
- "id" : 351
+ "id" : 411
},
{
- "id" : 351,
- "damage" : 3
+ "id" : 410
},
{
- "id" : 351,
- "damage" : 4
+ "id" : 412
},
{
- "id" : 351,
- "damage" : 15
+ "id" : 409
},
{
"id" : 106
@@ -1762,31 +1739,31 @@
"id" : 78
},
{
- "id" : 365
+ "id" : 275
},
{
- "id" : 319
+ "id" : 262
},
{
- "id" : 363
+ "id" : 273
},
{
- "id" : 423
+ "id" : 540
},
{
- "id" : 411
+ "id" : 288
},
{
- "id" : 349
+ "id" : 264
},
{
- "id" : 460
+ "id" : 265
},
{
- "id" : 461
+ "id" : 266
},
{
- "id" : 462
+ "id" : 267
},
{
"id" : 39
@@ -1816,25 +1793,25 @@
"id" : 99
},
{
- "id" : 344
+ "id" : 388
},
{
- "id" : 338
+ "id" : 383
},
{
- "id" : 353
+ "id" : 414
},
{
- "id" : 367
+ "id" : 277
},
{
- "id" : 352
+ "id" : 413
},
{
"id" : 30
},
{
- "id" : 375
+ "id" : 278
},
{
"id" : 52
@@ -1869,252 +1846,193 @@
"id" : -159
},
{
- "id" : 383,
- "damage" : 10
+ "id" : 433
},
{
- "id" : 383,
- "damage" : 122
+ "id" : 492
},
{
- "id" : 383,
- "damage" : 11
+ "id" : 434
},
{
- "id" : 383,
- "damage" : 12
+ "id" : 435
},
{
- "id" : 383,
- "damage" : 13
+ "id" : 436
},
{
- "id" : 383,
- "damage" : 14
+ "id" : 437
},
{
- "id" : 383,
- "damage" : 28
+ "id" : 470
},
{
- "id" : 383,
- "damage" : 22
+ "id" : 449
},
{
- "id" : 383,
- "damage" : 75
+ "id" : 486
},
{
- "id" : 383,
- "damage" : 16
+ "id" : 438
},
{
- "id" : 383,
- "damage" : 19
+ "id" : 451
},
{
- "id" : 383,
- "damage" : 30
+ "id" : 476
},
{
- "id" : 383,
- "damage" : 18
+ "id" : 457
},
{
- "id" : 383,
- "damage" : 29
+ "id" : 471
},
{
- "id" : 383,
- "damage" : 23
+ "id" : 456
},
{
- "id" : 383,
- "damage" : 24
+ "id" : 463
},
{
- "id" : 383,
- "damage" : 25
+ "id" : 464
},
{
- "id" : 383,
- "damage" : 26
+ "id" : 465
},
{
- "id" : 383,
- "damage" : 27
+ "id" : 466
},
{
- "id" : 383,
- "damage" : 111
+ "id" : 477
},
{
- "id" : 383,
- "damage" : 112
+ "id" : 478
},
{
- "id" : 383,
- "damage" : 108
+ "id" : 479
},
{
- "id" : 383,
- "damage" : 109
+ "id" : 480
},
{
- "id" : 383,
- "damage" : 31
+ "id" : 482
},
{
- "id" : 383,
- "damage" : 74
+ "id" : 483
},
{
- "id" : 383,
- "damage" : 113
+ "id" : 487
},
{
- "id" : 383,
- "damage" : 121
+ "id" : 488
},
{
- "id" : 383,
- "damage" : 33
+ "id" : 439
},
{
- "id" : 383,
- "damage" : 38
+ "id" : 440
},
{
- "id" : 383,
- "damage" : 39
+ "id" : 441
},
{
- "id" : 383,
- "damage" : 34
+ "id" : 442
},
{
- "id" : 383,
- "damage" : 48
+ "id" : 462
},
{
- "id" : 383,
- "damage" : 46
+ "id" : 460
},
{
- "id" : 383,
- "damage" : 37
+ "id" : 443
},
{
- "id" : 383,
- "damage" : 35
+ "id" : 444
},
{
- "id" : 383,
- "damage" : 32
+ "id" : 445
},
{
- "id" : 383,
- "damage" : 36
+ "id" : 446
},
{
- "id" : 383,
- "damage" : 47
+ "id" : 461
},
{
- "id" : 383,
- "damage" : 110
+ "id" : 481
},
{
- "id" : 383,
- "damage" : 17
+ "id" : 448
},
{
- "id" : 383,
- "damage" : 40
+ "id" : 455
},
{
- "id" : 383,
- "damage" : 45
+ "id" : 450
},
{
- "id" : 383,
- "damage" : 49
+ "id" : 459
},
{
- "id" : 383,
- "damage" : 50
+ "id" : 469
},
{
- "id" : 383,
- "damage" : 55
+ "id" : 458
},
{
- "id" : 383,
- "damage" : 42
+ "id" : 453
},
{
- "id" : 383,
- "damage" : 125
+ "id" : 493
},
{
- "id" : 383,
- "damage" : 124
+ "id" : 494
},
{
- "id" : 383,
- "damage" : 123
+ "id" : 495
},
{
- "id" : 383,
- "damage" : 126
+ "id" : 496
},
{
- "id" : 383,
- "damage" : 41
+ "id" : 497
},
{
- "id" : 383,
- "damage" : 43
+ "id" : 452
},
{
- "id" : 383,
- "damage" : 54
+ "id" : 454
},
{
- "id" : 383,
- "damage" : 57
+ "id" : 467
},
{
- "id" : 383,
- "damage" : 104
+ "id" : 472
},
{
- "id" : 383,
- "damage" : 105
+ "id" : 473
},
{
- "id" : 383,
- "damage" : 115
+ "id" : 474
},
{
- "id" : 383,
- "damage" : 118
+ "id" : 447
},
{
- "id" : 383,
- "damage" : 116
+ "id" : 490
},
{
- "id" : 383,
- "damage" : 58
+ "id" : 475
},
{
- "id" : 383,
- "damage" : 114
+ "id" : 484
},
{
- "id" : 383,
- "damage" : 59
+ "id" : 489
+ },
+ {
+ "id" : 491
},
{
"id" : 49
@@ -2135,7 +2053,7 @@
"id" : 213
},
{
- "id" : 372
+ "id" : 294
},
{
"id" : 121
@@ -2147,10 +2065,10 @@
"id" : 240
},
{
- "id" : 432
+ "id" : 548
},
{
- "id" : 433
+ "id" : 549
},
{
"id" : 19
@@ -2199,1023 +2117,1023 @@
"damage" : 12
},
{
- "id" : 298
+ "id" : 335
},
{
- "id" : 302
+ "id" : 339
},
{
- "id" : 306
+ "id" : 343
},
{
- "id" : 314
- },
- {
- "id" : 310
- },
- {
- "id" : 748
- },
- {
- "id" : 299
- },
- {
- "id" : 303
- },
- {
- "id" : 307
- },
- {
- "id" : 315
- },
- {
- "id" : 311
- },
- {
- "id" : 749
- },
- {
- "id" : 300
- },
- {
- "id" : 304
- },
- {
- "id" : 308
- },
- {
- "id" : 316
- },
- {
- "id" : 312
- },
- {
- "id" : 750
- },
- {
- "id" : 301
- },
- {
- "id" : 305
- },
- {
- "id" : 309
- },
- {
- "id" : 317
- },
- {
- "id" : 313
- },
- {
- "id" : 751
- },
- {
- "id" : 268
- },
- {
- "id" : 272
- },
- {
- "id" : 267
- },
- {
- "id" : 283
- },
- {
- "id" : 276
- },
- {
- "id" : 743
- },
- {
- "id" : 271
- },
- {
- "id" : 275
- },
- {
- "id" : 258
- },
- {
- "id" : 286
- },
- {
- "id" : 279
- },
- {
- "id" : 746
- },
- {
- "id" : 270
- },
- {
- "id" : 274
- },
- {
- "id" : 257
- },
- {
- "id" : 285
- },
- {
- "id" : 278
- },
- {
- "id" : 745
- },
- {
- "id" : 269
- },
- {
- "id" : 273
- },
- {
- "id" : 256
- },
- {
- "id" : 284
- },
- {
- "id" : 277
- },
- {
- "id" : 744
- },
- {
- "id" : 290
- },
- {
- "id" : 291
- },
- {
- "id" : 292
- },
- {
- "id" : 294
- },
- {
- "id" : 293
- },
- {
- "id" : 747
- },
- {
- "id" : 261
- },
- {
- "id" : 471
- },
- {
- "id" : 262
- },
- {
- "id" : 262,
- "damage" : 6
- },
- {
- "id" : 262,
- "damage" : 7
- },
- {
- "id" : 262,
- "damage" : 8
- },
- {
- "id" : 262,
- "damage" : 9
- },
- {
- "id" : 262,
- "damage" : 10
- },
- {
- "id" : 262,
- "damage" : 11
- },
- {
- "id" : 262,
- "damage" : 12
- },
- {
- "id" : 262,
- "damage" : 13
- },
- {
- "id" : 262,
- "damage" : 14
- },
- {
- "id" : 262,
- "damage" : 15
- },
- {
- "id" : 262,
- "damage" : 16
- },
- {
- "id" : 262,
- "damage" : 17
- },
- {
- "id" : 262,
- "damage" : 18
- },
- {
- "id" : 262,
- "damage" : 19
- },
- {
- "id" : 262,
- "damage" : 20
- },
- {
- "id" : 262,
- "damage" : 21
- },
- {
- "id" : 262,
- "damage" : 22
- },
- {
- "id" : 262,
- "damage" : 23
- },
- {
- "id" : 262,
- "damage" : 24
- },
- {
- "id" : 262,
- "damage" : 25
- },
- {
- "id" : 262,
- "damage" : 26
- },
- {
- "id" : 262,
- "damage" : 27
- },
- {
- "id" : 262,
- "damage" : 28
- },
- {
- "id" : 262,
- "damage" : 29
- },
- {
- "id" : 262,
- "damage" : 30
- },
- {
- "id" : 262,
- "damage" : 31
- },
- {
- "id" : 262,
- "damage" : 32
- },
- {
- "id" : 262,
- "damage" : 33
- },
- {
- "id" : 262,
- "damage" : 34
- },
- {
- "id" : 262,
- "damage" : 35
- },
- {
- "id" : 262,
- "damage" : 36
- },
- {
- "id" : 262,
- "damage" : 37
- },
- {
- "id" : 262,
- "damage" : 38
- },
- {
- "id" : 262,
- "damage" : 39
- },
- {
- "id" : 262,
- "damage" : 40
- },
- {
- "id" : 262,
- "damage" : 41
- },
- {
- "id" : 262,
- "damage" : 42
- },
- {
- "id" : 262,
- "damage" : 43
- },
- {
- "id" : 513
- },
- {
- "id" : 366
- },
- {
- "id" : 320
- },
- {
- "id" : 364
- },
- {
- "id" : 424
- },
- {
- "id" : 412
- },
- {
- "id" : 350
- },
- {
- "id" : 463
- },
- {
- "id" : 297
- },
- {
- "id" : 282
- },
- {
- "id" : 459
- },
- {
- "id" : 413
- },
- {
- "id" : 393
- },
- {
- "id" : 357
- },
- {
- "id" : 400
- },
- {
- "id" : 354
- },
- {
- "id" : 464
- },
- {
- "id" : 346
- },
- {
- "id" : 398
- },
- {
- "id" : 757
- },
- {
- "id" : 332
- },
- {
- "id" : 359
- },
- {
- "id" : 259
- },
- {
- "id" : 420
+ "id" : 351
},
{
"id" : 347
},
+ {
+ "id" : 597
+ },
+ {
+ "id" : 336
+ },
+ {
+ "id" : 340
+ },
+ {
+ "id" : 344
+ },
+ {
+ "id" : 352
+ },
+ {
+ "id" : 348
+ },
+ {
+ "id" : 598
+ },
+ {
+ "id" : 337
+ },
+ {
+ "id" : 341
+ },
{
"id" : 345
},
{
- "id" : 395
+ "id" : 353
},
{
- "id" : 395,
- "damage" : 2
+ "id" : 349
+ },
+ {
+ "id" : 599
+ },
+ {
+ "id" : 338
+ },
+ {
+ "id" : 342
+ },
+ {
+ "id" : 346
+ },
+ {
+ "id" : 354
+ },
+ {
+ "id" : 350
+ },
+ {
+ "id" : 600
+ },
+ {
+ "id" : 308
+ },
+ {
+ "id" : 312
+ },
+ {
+ "id" : 307
+ },
+ {
+ "id" : 322
+ },
+ {
+ "id" : 316
+ },
+ {
+ "id" : 592
+ },
+ {
+ "id" : 311
+ },
+ {
+ "id" : 315
+ },
+ {
+ "id" : 298
+ },
+ {
+ "id" : 325
+ },
+ {
+ "id" : 319
+ },
+ {
+ "id" : 595
+ },
+ {
+ "id" : 310
+ },
+ {
+ "id" : 314
+ },
+ {
+ "id" : 297
+ },
+ {
+ "id" : 324
+ },
+ {
+ "id" : 318
+ },
+ {
+ "id" : 594
+ },
+ {
+ "id" : 309
+ },
+ {
+ "id" : 313
+ },
+ {
+ "id" : 296
+ },
+ {
+ "id" : 323
+ },
+ {
+ "id" : 317
+ },
+ {
+ "id" : 593
},
{
"id" : 329
},
{
- "id" : 416
+ "id" : 330
},
{
- "id" : 417
+ "id" : 331
},
{
- "id" : 418
+ "id" : 333
},
{
- "id" : 419
+ "id" : 332
},
{
- "id" : 455
+ "id" : 596
},
{
- "id" : 469
+ "id" : 300
},
{
- "id" : 444
+ "id" : 565
},
{
- "id" : 450
+ "id" : 301
},
{
- "id" : 374
- },
- {
- "id" : 384
- },
- {
- "id" : 373
- },
- {
- "id" : 373,
- "damage" : 1
- },
- {
- "id" : 373,
- "damage" : 2
- },
- {
- "id" : 373,
- "damage" : 3
- },
- {
- "id" : 373,
- "damage" : 4
- },
- {
- "id" : 373,
- "damage" : 5
- },
- {
- "id" : 373,
+ "id" : 301,
"damage" : 6
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 7
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 8
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 9
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 10
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 11
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 12
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 13
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 14
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 15
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 16
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 17
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 18
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 19
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 20
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 21
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 22
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 23
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 24
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 25
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 26
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 27
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 28
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 29
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 30
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 31
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 32
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 33
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 34
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 35
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 36
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 37
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 38
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 39
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 40
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 41
},
{
- "id" : 373,
+ "id" : 301,
"damage" : 42
},
{
- "id" : 438
- },
- {
- "id" : 438,
- "damage" : 1
- },
- {
- "id" : 438,
- "damage" : 2
- },
- {
- "id" : 438,
- "damage" : 3
- },
- {
- "id" : 438,
- "damage" : 4
- },
- {
- "id" : 438,
- "damage" : 5
- },
- {
- "id" : 438,
- "damage" : 6
- },
- {
- "id" : 438,
- "damage" : 7
- },
- {
- "id" : 438,
- "damage" : 8
- },
- {
- "id" : 438,
- "damage" : 9
- },
- {
- "id" : 438,
- "damage" : 10
- },
- {
- "id" : 438,
- "damage" : 11
- },
- {
- "id" : 438,
- "damage" : 12
- },
- {
- "id" : 438,
- "damage" : 13
- },
- {
- "id" : 438,
- "damage" : 14
- },
- {
- "id" : 438,
- "damage" : 15
- },
- {
- "id" : 438,
- "damage" : 16
- },
- {
- "id" : 438,
- "damage" : 17
- },
- {
- "id" : 438,
- "damage" : 18
- },
- {
- "id" : 438,
- "damage" : 19
- },
- {
- "id" : 438,
- "damage" : 20
- },
- {
- "id" : 438,
- "damage" : 21
- },
- {
- "id" : 438,
- "damage" : 22
- },
- {
- "id" : 438,
- "damage" : 23
- },
- {
- "id" : 438,
- "damage" : 24
- },
- {
- "id" : 438,
- "damage" : 25
- },
- {
- "id" : 438,
- "damage" : 26
- },
- {
- "id" : 438,
- "damage" : 27
- },
- {
- "id" : 438,
- "damage" : 28
- },
- {
- "id" : 438,
- "damage" : 29
- },
- {
- "id" : 438,
- "damage" : 30
- },
- {
- "id" : 438,
- "damage" : 31
- },
- {
- "id" : 438,
- "damage" : 32
- },
- {
- "id" : 438,
- "damage" : 33
- },
- {
- "id" : 438,
- "damage" : 34
- },
- {
- "id" : 438,
- "damage" : 35
- },
- {
- "id" : 438,
- "damage" : 36
- },
- {
- "id" : 438,
- "damage" : 37
- },
- {
- "id" : 438,
- "damage" : 38
- },
- {
- "id" : 438,
- "damage" : 39
- },
- {
- "id" : 438,
- "damage" : 40
- },
- {
- "id" : 438,
- "damage" : 41
- },
- {
- "id" : 438,
- "damage" : 42
- },
- {
- "id" : 441
- },
- {
- "id" : 441,
- "damage" : 1
- },
- {
- "id" : 441,
- "damage" : 2
- },
- {
- "id" : 441,
- "damage" : 3
- },
- {
- "id" : 441,
- "damage" : 4
- },
- {
- "id" : 441,
- "damage" : 5
- },
- {
- "id" : 441,
- "damage" : 6
- },
- {
- "id" : 441,
- "damage" : 7
- },
- {
- "id" : 441,
- "damage" : 8
- },
- {
- "id" : 441,
- "damage" : 9
- },
- {
- "id" : 441,
- "damage" : 10
- },
- {
- "id" : 441,
- "damage" : 11
- },
- {
- "id" : 441,
- "damage" : 12
- },
- {
- "id" : 441,
- "damage" : 13
- },
- {
- "id" : 441,
- "damage" : 14
- },
- {
- "id" : 441,
- "damage" : 15
- },
- {
- "id" : 441,
- "damage" : 16
- },
- {
- "id" : 441,
- "damage" : 17
- },
- {
- "id" : 441,
- "damage" : 18
- },
- {
- "id" : 441,
- "damage" : 19
- },
- {
- "id" : 441,
- "damage" : 20
- },
- {
- "id" : 441,
- "damage" : 21
- },
- {
- "id" : 441,
- "damage" : 22
- },
- {
- "id" : 441,
- "damage" : 23
- },
- {
- "id" : 441,
- "damage" : 24
- },
- {
- "id" : 441,
- "damage" : 25
- },
- {
- "id" : 441,
- "damage" : 26
- },
- {
- "id" : 441,
- "damage" : 27
- },
- {
- "id" : 441,
- "damage" : 28
- },
- {
- "id" : 441,
- "damage" : 29
- },
- {
- "id" : 441,
- "damage" : 30
- },
- {
- "id" : 441,
- "damage" : 31
- },
- {
- "id" : 441,
- "damage" : 32
- },
- {
- "id" : 441,
- "damage" : 33
- },
- {
- "id" : 441,
- "damage" : 34
- },
- {
- "id" : 441,
- "damage" : 35
- },
- {
- "id" : 441,
- "damage" : 36
- },
- {
- "id" : 441,
- "damage" : 37
- },
- {
- "id" : 441,
- "damage" : 38
- },
- {
- "id" : 441,
- "damage" : 39
- },
- {
- "id" : 441,
- "damage" : 40
- },
- {
- "id" : 441,
- "damage" : 41
- },
- {
- "id" : 441,
- "damage" : 42
- },
- {
- "id" : 280
+ "id" : 301,
+ "damage" : 43
},
{
"id" : 355
},
{
- "id" : 355,
- "damage" : 8
+ "id" : 276
},
{
- "id" : 355,
- "damage" : 7
+ "id" : 263
},
{
- "id" : 355,
- "damage" : 15
+ "id" : 274
},
{
- "id" : 355,
- "damage" : 12
+ "id" : 541
},
{
- "id" : 355,
- "damage" : 14
+ "id" : 289
},
{
- "id" : 355,
- "damage" : 1
+ "id" : 268
},
{
- "id" : 355,
- "damage" : 4
+ "id" : 269
},
{
- "id" : 355,
- "damage" : 5
+ "id" : 261
},
{
- "id" : 355,
- "damage" : 13
+ "id" : 260
},
{
- "id" : 355,
- "damage" : 9
+ "id" : 286
},
{
- "id" : 355,
- "damage" : 3
+ "id" : 290
},
{
- "id" : 355,
- "damage" : 11
+ "id" : 281
},
{
- "id" : 355,
- "damage" : 10
+ "id" : 271
},
{
- "id" : 355,
+ "id" : 284
+ },
+ {
+ "id" : 415
+ },
+ {
+ "id" : 270
+ },
+ {
+ "id" : 390
+ },
+ {
+ "id" : 507
+ },
+ {
+ "id" : 606
+ },
+ {
+ "id" : 372
+ },
+ {
+ "id" : 419
+ },
+ {
+ "id" : 299
+ },
+ {
+ "id" : 537
+ },
+ {
+ "id" : 391
+ },
+ {
+ "id" : 389
+ },
+ {
+ "id" : 505
+ },
+ {
+ "id" : 505,
"damage" : 2
},
{
- "id" : 355,
+ "id" : 369
+ },
+ {
+ "id" : 520
+ },
+ {
+ "id" : 521
+ },
+ {
+ "id" : 522
+ },
+ {
+ "id" : 523
+ },
+ {
+ "id" : 536
+ },
+ {
+ "id" : 563
+ },
+ {
+ "id" : 554
+ },
+ {
+ "id" : 558
+ },
+ {
+ "id" : 425
+ },
+ {
+ "id" : 498
+ },
+ {
+ "id" : 424
+ },
+ {
+ "id" : 424,
+ "damage" : 1
+ },
+ {
+ "id" : 424,
+ "damage" : 2
+ },
+ {
+ "id" : 424,
+ "damage" : 3
+ },
+ {
+ "id" : 424,
+ "damage" : 4
+ },
+ {
+ "id" : 424,
+ "damage" : 5
+ },
+ {
+ "id" : 424,
+ "damage" : 6
+ },
+ {
+ "id" : 424,
+ "damage" : 7
+ },
+ {
+ "id" : 424,
+ "damage" : 8
+ },
+ {
+ "id" : 424,
+ "damage" : 9
+ },
+ {
+ "id" : 424,
+ "damage" : 10
+ },
+ {
+ "id" : 424,
+ "damage" : 11
+ },
+ {
+ "id" : 424,
+ "damage" : 12
+ },
+ {
+ "id" : 424,
+ "damage" : 13
+ },
+ {
+ "id" : 424,
+ "damage" : 14
+ },
+ {
+ "id" : 424,
+ "damage" : 15
+ },
+ {
+ "id" : 424,
+ "damage" : 16
+ },
+ {
+ "id" : 424,
+ "damage" : 17
+ },
+ {
+ "id" : 424,
+ "damage" : 18
+ },
+ {
+ "id" : 424,
+ "damage" : 19
+ },
+ {
+ "id" : 424,
+ "damage" : 20
+ },
+ {
+ "id" : 424,
+ "damage" : 21
+ },
+ {
+ "id" : 424,
+ "damage" : 22
+ },
+ {
+ "id" : 424,
+ "damage" : 23
+ },
+ {
+ "id" : 424,
+ "damage" : 24
+ },
+ {
+ "id" : 424,
+ "damage" : 25
+ },
+ {
+ "id" : 424,
+ "damage" : 26
+ },
+ {
+ "id" : 424,
+ "damage" : 27
+ },
+ {
+ "id" : 424,
+ "damage" : 28
+ },
+ {
+ "id" : 424,
+ "damage" : 29
+ },
+ {
+ "id" : 424,
+ "damage" : 30
+ },
+ {
+ "id" : 424,
+ "damage" : 31
+ },
+ {
+ "id" : 424,
+ "damage" : 32
+ },
+ {
+ "id" : 424,
+ "damage" : 33
+ },
+ {
+ "id" : 424,
+ "damage" : 34
+ },
+ {
+ "id" : 424,
+ "damage" : 35
+ },
+ {
+ "id" : 424,
+ "damage" : 36
+ },
+ {
+ "id" : 424,
+ "damage" : 37
+ },
+ {
+ "id" : 424,
+ "damage" : 38
+ },
+ {
+ "id" : 424,
+ "damage" : 39
+ },
+ {
+ "id" : 424,
+ "damage" : 40
+ },
+ {
+ "id" : 424,
+ "damage" : 41
+ },
+ {
+ "id" : 424,
+ "damage" : 42
+ },
+ {
+ "id" : 551
+ },
+ {
+ "id" : 551,
+ "damage" : 1
+ },
+ {
+ "id" : 551,
+ "damage" : 2
+ },
+ {
+ "id" : 551,
+ "damage" : 3
+ },
+ {
+ "id" : 551,
+ "damage" : 4
+ },
+ {
+ "id" : 551,
+ "damage" : 5
+ },
+ {
+ "id" : 551,
+ "damage" : 6
+ },
+ {
+ "id" : 551,
+ "damage" : 7
+ },
+ {
+ "id" : 551,
+ "damage" : 8
+ },
+ {
+ "id" : 551,
+ "damage" : 9
+ },
+ {
+ "id" : 551,
+ "damage" : 10
+ },
+ {
+ "id" : 551,
+ "damage" : 11
+ },
+ {
+ "id" : 551,
+ "damage" : 12
+ },
+ {
+ "id" : 551,
+ "damage" : 13
+ },
+ {
+ "id" : 551,
+ "damage" : 14
+ },
+ {
+ "id" : 551,
+ "damage" : 15
+ },
+ {
+ "id" : 551,
+ "damage" : 16
+ },
+ {
+ "id" : 551,
+ "damage" : 17
+ },
+ {
+ "id" : 551,
+ "damage" : 18
+ },
+ {
+ "id" : 551,
+ "damage" : 19
+ },
+ {
+ "id" : 551,
+ "damage" : 20
+ },
+ {
+ "id" : 551,
+ "damage" : 21
+ },
+ {
+ "id" : 551,
+ "damage" : 22
+ },
+ {
+ "id" : 551,
+ "damage" : 23
+ },
+ {
+ "id" : 551,
+ "damage" : 24
+ },
+ {
+ "id" : 551,
+ "damage" : 25
+ },
+ {
+ "id" : 551,
+ "damage" : 26
+ },
+ {
+ "id" : 551,
+ "damage" : 27
+ },
+ {
+ "id" : 551,
+ "damage" : 28
+ },
+ {
+ "id" : 551,
+ "damage" : 29
+ },
+ {
+ "id" : 551,
+ "damage" : 30
+ },
+ {
+ "id" : 551,
+ "damage" : 31
+ },
+ {
+ "id" : 551,
+ "damage" : 32
+ },
+ {
+ "id" : 551,
+ "damage" : 33
+ },
+ {
+ "id" : 551,
+ "damage" : 34
+ },
+ {
+ "id" : 551,
+ "damage" : 35
+ },
+ {
+ "id" : 551,
+ "damage" : 36
+ },
+ {
+ "id" : 551,
+ "damage" : 37
+ },
+ {
+ "id" : 551,
+ "damage" : 38
+ },
+ {
+ "id" : 551,
+ "damage" : 39
+ },
+ {
+ "id" : 551,
+ "damage" : 40
+ },
+ {
+ "id" : 551,
+ "damage" : 41
+ },
+ {
+ "id" : 551,
+ "damage" : 42
+ },
+ {
+ "id" : 552
+ },
+ {
+ "id" : 552,
+ "damage" : 1
+ },
+ {
+ "id" : 552,
+ "damage" : 2
+ },
+ {
+ "id" : 552,
+ "damage" : 3
+ },
+ {
+ "id" : 552,
+ "damage" : 4
+ },
+ {
+ "id" : 552,
+ "damage" : 5
+ },
+ {
+ "id" : 552,
+ "damage" : 6
+ },
+ {
+ "id" : 552,
+ "damage" : 7
+ },
+ {
+ "id" : 552,
+ "damage" : 8
+ },
+ {
+ "id" : 552,
+ "damage" : 9
+ },
+ {
+ "id" : 552,
+ "damage" : 10
+ },
+ {
+ "id" : 552,
+ "damage" : 11
+ },
+ {
+ "id" : 552,
+ "damage" : 12
+ },
+ {
+ "id" : 552,
+ "damage" : 13
+ },
+ {
+ "id" : 552,
+ "damage" : 14
+ },
+ {
+ "id" : 552,
+ "damage" : 15
+ },
+ {
+ "id" : 552,
+ "damage" : 16
+ },
+ {
+ "id" : 552,
+ "damage" : 17
+ },
+ {
+ "id" : 552,
+ "damage" : 18
+ },
+ {
+ "id" : 552,
+ "damage" : 19
+ },
+ {
+ "id" : 552,
+ "damage" : 20
+ },
+ {
+ "id" : 552,
+ "damage" : 21
+ },
+ {
+ "id" : 552,
+ "damage" : 22
+ },
+ {
+ "id" : 552,
+ "damage" : 23
+ },
+ {
+ "id" : 552,
+ "damage" : 24
+ },
+ {
+ "id" : 552,
+ "damage" : 25
+ },
+ {
+ "id" : 552,
+ "damage" : 26
+ },
+ {
+ "id" : 552,
+ "damage" : 27
+ },
+ {
+ "id" : 552,
+ "damage" : 28
+ },
+ {
+ "id" : 552,
+ "damage" : 29
+ },
+ {
+ "id" : 552,
+ "damage" : 30
+ },
+ {
+ "id" : 552,
+ "damage" : 31
+ },
+ {
+ "id" : 552,
+ "damage" : 32
+ },
+ {
+ "id" : 552,
+ "damage" : 33
+ },
+ {
+ "id" : 552,
+ "damage" : 34
+ },
+ {
+ "id" : 552,
+ "damage" : 35
+ },
+ {
+ "id" : 552,
+ "damage" : 36
+ },
+ {
+ "id" : 552,
+ "damage" : 37
+ },
+ {
+ "id" : 552,
+ "damage" : 38
+ },
+ {
+ "id" : 552,
+ "damage" : 39
+ },
+ {
+ "id" : 552,
+ "damage" : 40
+ },
+ {
+ "id" : 552,
+ "damage" : 41
+ },
+ {
+ "id" : 552,
+ "damage" : 42
+ },
+ {
+ "id" : 320
+ },
+ {
+ "id" : 416
+ },
+ {
+ "id" : 416,
+ "damage" : 8
+ },
+ {
+ "id" : 416,
+ "damage" : 7
+ },
+ {
+ "id" : 416,
+ "damage" : 15
+ },
+ {
+ "id" : 416,
+ "damage" : 12
+ },
+ {
+ "id" : 416,
+ "damage" : 14
+ },
+ {
+ "id" : 416,
+ "damage" : 1
+ },
+ {
+ "id" : 416,
+ "damage" : 4
+ },
+ {
+ "id" : 416,
+ "damage" : 5
+ },
+ {
+ "id" : 416,
+ "damage" : 13
+ },
+ {
+ "id" : 416,
+ "damage" : 9
+ },
+ {
+ "id" : 416,
+ "damage" : 3
+ },
+ {
+ "id" : 416,
+ "damage" : 11
+ },
+ {
+ "id" : 416,
+ "damage" : 10
+ },
+ {
+ "id" : 416,
+ "damage" : 2
+ },
+ {
+ "id" : 416,
"damage" : 6
},
{
@@ -3246,14 +3164,13 @@
"id" : -202
},
{
- "id" : -219,
- "damage" : 3
+ "id" : -219
},
{
- "id" : 720
+ "id" : 578
},
{
- "id" : 801
+ "id" : 610
},
{
"id" : 61
@@ -3268,7 +3185,7 @@
"id" : -272
},
{
- "id" : 379
+ "id" : 429
},
{
"id" : 145
@@ -3294,7 +3211,7 @@
"id" : -194
},
{
- "id" : 380
+ "id" : 430
},
{
"id" : -213
@@ -3378,7 +3295,7 @@
"damage" : 6
},
{
- "id" : 425
+ "id" : 542
},
{
"id" : 25
@@ -3387,46 +3304,46 @@
"id" : 84
},
{
- "id" : 500
+ "id" : 524
},
{
- "id" : 501
+ "id" : 525
},
{
- "id" : 502
+ "id" : 526
},
{
- "id" : 503
+ "id" : 527
},
{
- "id" : 504
+ "id" : 528
},
{
- "id" : 505
+ "id" : 529
},
{
- "id" : 506
+ "id" : 530
},
{
- "id" : 507
+ "id" : 531
},
{
- "id" : 508
+ "id" : 532
},
{
- "id" : 509
+ "id" : 533
},
{
- "id" : 510
+ "id" : 534
},
{
- "id" : 511
+ "id" : 535
},
{
- "id" : 759
+ "id" : 608
},
{
- "id" : 348
+ "id" : 392
},
{
"id" : 89
@@ -3438,96 +3355,89 @@
"id" : 169
},
{
- "id" : 323
+ "id" : 358
},
{
- "id" : 472
+ "id" : 566
},
{
- "id" : 473
+ "id" : 567
},
{
- "id" : 474
+ "id" : 568
},
{
- "id" : 475
+ "id" : 569
},
{
- "id" : 476
+ "id" : 570
},
{
- "id" : 753
+ "id" : 602
},
{
- "id" : 754
+ "id" : 603
+ },
+ {
+ "id" : 357
+ },
+ {
+ "id" : 503
+ },
+ {
+ "id" : 581
+ },
+ {
+ "id" : 504
},
{
"id" : 321
},
{
- "id" : 389
+ "id" : 360
},
{
- "id" : 737
+ "id" : 361
},
{
- "id" : 390
+ "id" : 362
},
{
- "id" : 281
+ "id" : 363
},
{
- "id" : 325
+ "id" : 364
},
{
- "id" : 325,
- "damage" : 1
+ "id" : 365
},
{
- "id" : 325,
- "damage" : 8
+ "id" : 366
},
{
- "id" : 325,
- "damage" : 10
+ "id" : 367
},
{
- "id" : 325,
- "damage" : 2
- },
- {
- "id" : 325,
+ "id" : 506,
"damage" : 3
},
{
- "id" : 325,
- "damage" : 4
- },
- {
- "id" : 325,
- "damage" : 5
- },
- {
- "id" : 397,
- "damage" : 3
- },
- {
- "id" : 397,
+ "id" : 506,
"damage" : 2
},
{
- "id" : 397,
+ "id" : 506,
"damage" : 4
},
{
- "id" : 397,
+ "id" : 506,
"damage" : 5
},
{
- "id" : 397
+ "id" : 506
},
{
- "id" : 397,
+ "id" : 506,
"damage" : 1
},
{
@@ -3546,92 +3456,576 @@
"id" : 120
},
{
- "id" : 263
+ "id" : 302
},
{
- "id" : 263,
- "damage" : 1
+ "id" : 303
},
{
- "id" : 264
+ "id" : 304
},
{
- "id" : 452
+ "id" : 559
},
{
- "id" : 265
+ "id" : 305
},
{
- "id" : 752
+ "id" : 601
},
{
- "id" : 742
+ "id" : 591
},
{
- "id" : 371
+ "id" : 423
},
{
- "id" : 266
+ "id" : 306
},
{
- "id" : 388
+ "id" : 502
},
{
- "id" : 406
+ "id" : 514
},
{
- "id" : 337
+ "id" : 382
},
{
- "id" : 336
+ "id" : 381
},
{
- "id" : 405
+ "id" : 513
},
{
- "id" : 409
+ "id" : 555
+ },
+ {
+ "id" : 539
+ },
+ {
+ "id" : 560
+ },
+ {
+ "id" : 561
+ },
+ {
+ "id" : 562
+ },
+ {
+ "id" : 564
+ },
+ {
+ "id" : 326
+ },
+ {
+ "id" : 327
+ },
+ {
+ "id" : 356
+ },
+ {
+ "id" : 328
+ },
+ {
+ "id" : 379
+ },
+ {
+ "id" : 519
+ },
+ {
+ "id" : 518
+ },
+ {
+ "id" : 499
+ },
+ {
+ "id" : 421
+ },
+ {
+ "id" : 427
+ },
+ {
+ "id" : 428
+ },
+ {
+ "id" : 426
+ },
+ {
+ "id" : 550
+ },
+ {
+ "id" : 556
},
{
"id" : 422
},
{
- "id" : 465
+ "id" : 386
},
{
- "id" : 467
+ "id" : 420
},
{
- "id" : 468
+ "id" : 431
},
{
- "id" : 470
+ "id" : 508
},
{
- "id" : 287
+ "id" : 208
},
{
- "id" : 288
+ "id" : 615
},
{
- "id" : 318
- },
- {
- "id" : 289
- },
- {
- "id" : 334
- },
- {
- "id" : 415
- },
- {
- "id" : 414
+ "id" : 384
},
{
"id" : 385
},
{
- "id" : 369
+ "id" : 500
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQAAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQBAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQCAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQDAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQEAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQFAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQGAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQHAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQIAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQJAAIDAGx2bAUAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQKAAIDAGx2bAUAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQLAAIDAGx2bAUAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQMAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQNAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQOAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQPAAIDAGx2bAUAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQQAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQRAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQSAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQTAAIDAGx2bAUAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQUAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQVAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQWAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQXAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQYAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQZAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQaAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQbAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQcAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQdAAIDAGx2bAUAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQeAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQfAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQgAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQhAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQiAAIDAGx2bAQAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQjAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAEAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAIAAAA="
+ },
+ {
+ "id" : 511,
+ "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgIAaWQkAAIDAGx2bAMAAAA="
+ },
+ {
+ "id" : 373
+ },
+ {
+ "id" : 376
+ },
+ {
+ "id" : 374
+ },
+ {
+ "id" : 375
},
{
"id" : 377
@@ -3639,496 +4033,6 @@
{
"id" : 378
},
- {
- "id" : 376
- },
- {
- "id" : 437
- },
- {
- "id" : 445
- },
- {
- "id" : 370
- },
- {
- "id" : 341
- },
- {
- "id" : 368
- },
- {
- "id" : 381
- },
- {
- "id" : 399
- },
- {
- "id" : 208
- },
- {
- "id" : 426
- },
- {
- "id" : 339
- },
- {
- "id" : 340
- },
- {
- "id" : 386
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAAAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAAAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAAAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZAAAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAEAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAEAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAEAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZAEAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZAIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZAMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAQAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAQAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAQAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZAQAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAUAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAUAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAUAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAYAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAYAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAYAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAcAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAcAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAcAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAgAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAkAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAkAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAkAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZAkAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBQACAgBpZAkAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAoAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAoAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAoAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZAoAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBQACAgBpZAoAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAsAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAsAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZAsAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZAsAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBQACAgBpZAsAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZAwAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZAwAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZA0AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZA0AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZA4AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZA4AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZA4AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZA8AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZA8AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZA8AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZA8AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBQACAgBpZA8AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBAAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBEAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZBEAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZBEAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZBIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZBIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZBMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZBMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZBMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBQACAgBpZBMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBQAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZBQAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBUAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBYAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBcAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZBcAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZBcAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBgAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZBgAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZBgAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBkAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZBkAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBoAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBsAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBwAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZB0AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZB0AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZB0AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZB0AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBQACAgBpZB0AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZB4AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZB4AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZB4AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZB8AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZB8AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZB8AAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZCAAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZCEAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZCIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZCIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZCIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsBAACAgBpZCIAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZCMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZCMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZCMAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZCQAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZCQAAAA="
- },
- {
- "id" : 403,
- "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZCQAAAA="
- },
- {
- "id" : 333
- },
- {
- "id" : 333,
- "damage" : 1
- },
- {
- "id" : 333,
- "damage" : 2
- },
- {
- "id" : 333,
- "damage" : 3
- },
- {
- "id" : 333,
- "damage" : 4
- },
- {
- "id" : 333,
- "damage" : 5
- },
{
"id" : 66
},
@@ -4142,19 +4046,19 @@
"id" : 126
},
{
- "id" : 328
+ "id" : 368
},
{
- "id" : 342
+ "id" : 387
},
{
- "id" : 408
+ "id" : 516
},
{
- "id" : 407
+ "id" : 515
},
{
- "id" : 331
+ "id" : 371
},
{
"id" : 152
@@ -4241,13 +4145,13 @@
"id" : 151
},
{
- "id" : 356
+ "id" : 417
},
{
- "id" : 404
+ "id" : 512
},
{
- "id" : 410
+ "id" : 517
},
{
"id" : 125,
@@ -4269,252 +4173,255 @@
"id" : 46
},
{
- "id" : 421
+ "id" : 538
},
{
"id" : -204
},
{
- "id" : 446
+ "id" : 557
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 8
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 7
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 15
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 12
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 14
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 1
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 4
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 5
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 13
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 9
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 3
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 11
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 10
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 2
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 6
},
{
- "id" : 446,
+ "id" : 557,
"damage" : 15,
"nbt_b64" : "CgAAAwQAVHlwZQEAAAAA"
},
{
- "id" : 434
+ "id" : 572
},
{
- "id" : 434,
- "damage" : 1
+ "id" : 573
},
{
- "id" : 434,
- "damage" : 2
+ "id" : 571
},
{
- "id" : 434,
- "damage" : 3
+ "id" : 574
},
{
- "id" : 434,
- "damage" : 4
+ "id" : 575
},
{
- "id" : 434,
- "damage" : 5
+ "id" : 576
},
{
- "id" : 434,
- "damage" : 6
+ "id" : 577
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMAAAAAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwAAAAAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAAAAEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAABwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAACAEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAIBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAABwEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAHBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAADwEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAPBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAADAEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAMBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAADgEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAOBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAAAQEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAABBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAABAEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAEBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAABQEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAFBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAADQEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAANBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAACQEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAJBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAAAwEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAADBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAACwEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAALBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAACgEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAKBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAAAgEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAACBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 401,
- "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMKAQAAAAcNAEZpcmV3b3JrQ29sb3IBAAAABgEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAAA"
+ "id" : 509,
+ "nbt_b64" : "CgAACgkARmlyZXdvcmtzCQoARXhwbG9zaW9ucwoBAAAABw0ARmlyZXdvcmtDb2xvcgEAAAAGBwwARmlyZXdvcmtGYWRlAAAAAAEPAEZpcmV3b3JrRmxpY2tlcgABDQBGaXJld29ya1RyYWlsAAEMAEZpcmV3b3JrVHlwZQAAAQYARmxpZ2h0AQAA"
},
{
- "id" : 402,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3IhHR3/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "id" : 510,
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yIR0d/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 8,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3JST0f/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yUk9H/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 7,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3KXnZ3/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yl52d/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 15,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3Lw8PD/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y8PDw/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 12,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3Laszr/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9y2rM6/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 14,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3IdgPn/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yHYD5/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 1,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3ImLrD/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yJi6w/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 4,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3KqRDz/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABAcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqkQ8/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 5,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3K4Mon/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yuDKJ/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 13,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3K9Tsf/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAADQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yvU7H/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 9,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3Kqi/P/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACQcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yqovz/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 3,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3IyVIP/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yMlSD/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 11,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3I92P7/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACwcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yPdj+/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 10,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3Ifx4D/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAACgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yH8eA/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 2,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3IWfF7/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAAAgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9yFnxe/wA="
},
{
- "id" : 402,
+ "id" : 510,
"damage" : 6,
- "nbt_b64" : "CgAAAwsAY3VzdG9tQ29sb3KcnBb/Cg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgEMAEZpcmV3b3JrVHlwZQAHDABGaXJld29ya0ZhZGUAAAAAAQ0ARmlyZXdvcmtUcmFpbAABDwBGaXJld29ya0ZsaWNrZXIAAAA="
+ "nbt_b64" : "CgAACg0ARmlyZXdvcmtzSXRlbQcNAEZpcmV3b3JrQ29sb3IBAAAABgcMAEZpcmV3b3JrRmFkZQAAAAABDwBGaXJld29ya0ZsaWNrZXIAAQ0ARmlyZXdvcmtUcmFpbAABDABGaXJld29ya1R5cGUAAAMLAGN1c3RvbUNvbG9ynJwW/wA="
+ },
+ {
+ "id" : 607
+ },
+ {
+ "id" : -239
+ },
+ {
+ "id" : 590
}
]
}
\ No newline at end of file
diff --git a/connector/src/main/resources/bedrock/legacy_block_ids.json b/connector/src/main/resources/bedrock/legacy_block_ids.json
deleted file mode 100644
index 275949157..000000000
--- a/connector/src/main/resources/bedrock/legacy_block_ids.json
+++ /dev/null
@@ -1,555 +0,0 @@
-{
- "minecraft:air" : 0,
- "minecraft:stone" : 1,
- "minecraft:grass" : 2,
- "minecraft:dirt" : 3,
- "minecraft:cobblestone" : 4,
- "minecraft:planks" : 5,
- "minecraft:sapling" : 6,
- "minecraft:bedrock" : 7,
- "minecraft:flowing_water" : 8,
- "minecraft:water" : 9,
- "minecraft:flowing_lava" : 10,
- "minecraft:lava" : 11,
- "minecraft:sand" : 12,
- "minecraft:gravel" : 13,
- "minecraft:gold_ore" : 14,
- "minecraft:iron_ore" : 15,
- "minecraft:coal_ore" : 16,
- "minecraft:log" : 17,
- "minecraft:leaves" : 18,
- "minecraft:sponge" : 19,
- "minecraft:glass" : 20,
- "minecraft:lapis_ore" : 21,
- "minecraft:lapis_block" : 22,
- "minecraft:dispenser" : 23,
- "minecraft:sandstone" : 24,
- "minecraft:noteblock" : 25,
- "minecraft:bed" : 26,
- "minecraft:golden_rail" : 27,
- "minecraft:detector_rail" : 28,
- "minecraft:sticky_piston" : 29,
- "minecraft:web" : 30,
- "minecraft:tallgrass" : 31,
- "minecraft:deadbush" : 32,
- "minecraft:piston" : 33,
- "minecraft:pistonArmCollision" : 34,
- "minecraft:wool" : 35,
- "minecraft:element_0" : 36,
- "minecraft:yellow_flower" : 37,
- "minecraft:red_flower" : 38,
- "minecraft:brown_mushroom" : 39,
- "minecraft:red_mushroom" : 40,
- "minecraft:gold_block" : 41,
- "minecraft:iron_block" : 42,
- "minecraft:double_stone_slab" : 43,
- "minecraft:stone_slab" : 44,
- "minecraft:brick_block" : 45,
- "minecraft:tnt" : 46,
- "minecraft:bookshelf" : 47,
- "minecraft:mossy_cobblestone" : 48,
- "minecraft:obsidian" : 49,
- "minecraft:torch" : 50,
- "minecraft:fire" : 51,
- "minecraft:mob_spawner" : 52,
- "minecraft:oak_stairs" : 53,
- "minecraft:chest" : 54,
- "minecraft:redstone_wire" : 55,
- "minecraft:diamond_ore" : 56,
- "minecraft:diamond_block" : 57,
- "minecraft:crafting_table" : 58,
- "minecraft:wheat" : 59,
- "minecraft:farmland" : 60,
- "minecraft:furnace" : 61,
- "minecraft:lit_furnace" : 62,
- "minecraft:standing_sign" : 63,
- "minecraft:wooden_door" : 64,
- "minecraft:ladder" : 65,
- "minecraft:rail" : 66,
- "minecraft:stone_stairs" : 67,
- "minecraft:wall_sign" : 68,
- "minecraft:lever" : 69,
- "minecraft:stone_pressure_plate" : 70,
- "minecraft:iron_door" : 71,
- "minecraft:wooden_pressure_plate" : 72,
- "minecraft:redstone_ore" : 73,
- "minecraft:lit_redstone_ore" : 74,
- "minecraft:unlit_redstone_torch" : 75,
- "minecraft:redstone_torch" : 76,
- "minecraft:stone_button" : 77,
- "minecraft:snow_layer" : 78,
- "minecraft:ice" : 79,
- "minecraft:snow" : 80,
- "minecraft:cactus" : 81,
- "minecraft:clay" : 82,
- "minecraft:reeds" : 83,
- "minecraft:jukebox" : 84,
- "minecraft:fence" : 85,
- "minecraft:pumpkin" : 86,
- "minecraft:netherrack" : 87,
- "minecraft:soul_sand" : 88,
- "minecraft:glowstone" : 89,
- "minecraft:portal" : 90,
- "minecraft:lit_pumpkin" : 91,
- "minecraft:cake" : 92,
- "minecraft:unpowered_repeater" : 93,
- "minecraft:powered_repeater" : 94,
- "minecraft:invisibleBedrock" : 95,
- "minecraft:trapdoor" : 96,
- "minecraft:monster_egg" : 97,
- "minecraft:stonebrick" : 98,
- "minecraft:brown_mushroom_block" : 99,
- "minecraft:red_mushroom_block" : 100,
- "minecraft:iron_bars" : 101,
- "minecraft:glass_pane" : 102,
- "minecraft:melon_block" : 103,
- "minecraft:pumpkin_stem" : 104,
- "minecraft:melon_stem" : 105,
- "minecraft:vine" : 106,
- "minecraft:fence_gate" : 107,
- "minecraft:brick_stairs" : 108,
- "minecraft:stone_brick_stairs" : 109,
- "minecraft:mycelium" : 110,
- "minecraft:waterlily" : 111,
- "minecraft:nether_brick" : 112,
- "minecraft:nether_brick_fence" : 113,
- "minecraft:nether_brick_stairs" : 114,
- "minecraft:nether_wart" : 115,
- "minecraft:enchanting_table" : 116,
- "minecraft:brewing_stand" : 117,
- "minecraft:cauldron" : 118,
- "minecraft:end_portal" : 119,
- "minecraft:end_portal_frame" : 120,
- "minecraft:end_stone" : 121,
- "minecraft:dragon_egg" : 122,
- "minecraft:redstone_lamp" : 123,
- "minecraft:lit_redstone_lamp" : 124,
- "minecraft:dropper" : 125,
- "minecraft:activator_rail" : 126,
- "minecraft:cocoa" : 127,
- "minecraft:sandstone_stairs" : 128,
- "minecraft:emerald_ore" : 129,
- "minecraft:ender_chest" : 130,
- "minecraft:tripwire_hook" : 131,
- "minecraft:tripWire" : 132,
- "minecraft:emerald_block" : 133,
- "minecraft:spruce_stairs" : 134,
- "minecraft:birch_stairs" : 135,
- "minecraft:jungle_stairs" : 136,
- "minecraft:command_block" : 137,
- "minecraft:beacon" : 138,
- "minecraft:cobblestone_wall" : 139,
- "minecraft:flower_pot" : 140,
- "minecraft:carrots" : 141,
- "minecraft:potatoes" : 142,
- "minecraft:wooden_button" : 143,
- "minecraft:skull" : 144,
- "minecraft:anvil" : 145,
- "minecraft:trapped_chest" : 146,
- "minecraft:light_weighted_pressure_plate" : 147,
- "minecraft:heavy_weighted_pressure_plate" : 148,
- "minecraft:unpowered_comparator" : 149,
- "minecraft:powered_comparator" : 150,
- "minecraft:daylight_detector" : 151,
- "minecraft:redstone_block" : 152,
- "minecraft:quartz_ore" : 153,
- "minecraft:hopper" : 154,
- "minecraft:quartz_block" : 155,
- "minecraft:quartz_stairs" : 156,
- "minecraft:double_wooden_slab" : 157,
- "minecraft:wooden_slab" : 158,
- "minecraft:stained_hardened_clay" : 159,
- "minecraft:stained_glass_pane" : 160,
- "minecraft:leaves2" : 161,
- "minecraft:log2" : 162,
- "minecraft:acacia_stairs" : 163,
- "minecraft:dark_oak_stairs" : 164,
- "minecraft:slime" : 165,
- "minecraft:iron_trapdoor" : 167,
- "minecraft:prismarine" : 168,
- "minecraft:seaLantern" : 169,
- "minecraft:hay_block" : 170,
- "minecraft:carpet" : 171,
- "minecraft:hardened_clay" : 172,
- "minecraft:coal_block" : 173,
- "minecraft:packed_ice" : 174,
- "minecraft:double_plant" : 175,
- "minecraft:standing_banner" : 176,
- "minecraft:wall_banner" : 177,
- "minecraft:daylight_detector_inverted" : 178,
- "minecraft:red_sandstone" : 179,
- "minecraft:red_sandstone_stairs" : 180,
- "minecraft:double_stone_slab2" : 181,
- "minecraft:stone_slab2" : 182,
- "minecraft:spruce_fence_gate" : 183,
- "minecraft:birch_fence_gate" : 184,
- "minecraft:jungle_fence_gate" : 185,
- "minecraft:dark_oak_fence_gate" : 186,
- "minecraft:acacia_fence_gate" : 187,
- "minecraft:repeating_command_block" : 188,
- "minecraft:chain_command_block" : 189,
- "minecraft:hard_glass_pane" : 190,
- "minecraft:hard_stained_glass_pane" : 191,
- "minecraft:chemical_heat" : 192,
- "minecraft:spruce_door" : 193,
- "minecraft:birch_door" : 194,
- "minecraft:jungle_door" : 195,
- "minecraft:acacia_door" : 196,
- "minecraft:dark_oak_door" : 197,
- "minecraft:grass_path" : 198,
- "minecraft:frame" : 199,
- "minecraft:chorus_flower" : 200,
- "minecraft:purpur_block" : 201,
- "minecraft:colored_torch_rg" : 202,
- "minecraft:purpur_stairs" : 203,
- "minecraft:colored_torch_bp" : 204,
- "minecraft:undyed_shulker_box" : 205,
- "minecraft:end_bricks" : 206,
- "minecraft:frosted_ice" : 207,
- "minecraft:end_rod" : 208,
- "minecraft:end_gateway" : 209,
- "minecraft:allow" : 210,
- "minecraft:deny" : 211,
- "minecraft:border_block" : 212,
- "minecraft:magma" : 213,
- "minecraft:nether_wart_block" : 214,
- "minecraft:red_nether_brick" : 215,
- "minecraft:bone_block" : 216,
- "minecraft:structure_void" : 217,
- "minecraft:shulker_box" : 218,
- "minecraft:purple_glazed_terracotta" : 219,
- "minecraft:white_glazed_terracotta" : 220,
- "minecraft:orange_glazed_terracotta" : 221,
- "minecraft:magenta_glazed_terracotta" : 222,
- "minecraft:light_blue_glazed_terracotta" : 223,
- "minecraft:yellow_glazed_terracotta" : 224,
- "minecraft:lime_glazed_terracotta" : 225,
- "minecraft:pink_glazed_terracotta" : 226,
- "minecraft:gray_glazed_terracotta" : 227,
- "minecraft:silver_glazed_terracotta" : 228,
- "minecraft:cyan_glazed_terracotta" : 229,
- "minecraft:blue_glazed_terracotta" : 231,
- "minecraft:brown_glazed_terracotta" : 232,
- "minecraft:green_glazed_terracotta" : 233,
- "minecraft:red_glazed_terracotta" : 234,
- "minecraft:black_glazed_terracotta" : 235,
- "minecraft:concrete" : 236,
- "minecraft:concretePowder" : 237,
- "minecraft:chemistry_table" : 238,
- "minecraft:underwater_torch" : 239,
- "minecraft:chorus_plant" : 240,
- "minecraft:stained_glass" : 241,
- "minecraft:camera" : 242,
- "minecraft:podzol" : 243,
- "minecraft:beetroot" : 244,
- "minecraft:stonecutter" : 245,
- "minecraft:glowingobsidian" : 246,
- "minecraft:netherreactor" : 247,
- "minecraft:info_update" : 248,
- "minecraft:info_update2" : 249,
- "minecraft:movingBlock" : 250,
- "minecraft:observer" : 251,
- "minecraft:structure_block" : 252,
- "minecraft:hard_glass" : 253,
- "minecraft:hard_stained_glass" : 254,
- "minecraft:reserved6" : 255,
- "minecraft:prismarine_stairs" : 257,
- "minecraft:dark_prismarine_stairs" : 258,
- "minecraft:prismarine_bricks_stairs" : 259,
- "minecraft:stripped_spruce_log" : 260,
- "minecraft:stripped_birch_log" : 261,
- "minecraft:stripped_jungle_log" : 262,
- "minecraft:stripped_acacia_log" : 263,
- "minecraft:stripped_dark_oak_log" : 264,
- "minecraft:stripped_oak_log" : 265,
- "minecraft:blue_ice" : 266,
- "minecraft:element_1" : 267,
- "minecraft:element_2" : 268,
- "minecraft:element_3" : 269,
- "minecraft:element_4" : 270,
- "minecraft:element_5" : 271,
- "minecraft:element_6" : 272,
- "minecraft:element_7" : 273,
- "minecraft:element_8" : 274,
- "minecraft:element_9" : 275,
- "minecraft:element_10" : 276,
- "minecraft:element_11" : 277,
- "minecraft:element_12" : 278,
- "minecraft:element_13" : 279,
- "minecraft:element_14" : 280,
- "minecraft:element_15" : 281,
- "minecraft:element_16" : 282,
- "minecraft:element_17" : 283,
- "minecraft:element_18" : 284,
- "minecraft:element_19" : 285,
- "minecraft:element_20" : 286,
- "minecraft:element_21" : 287,
- "minecraft:element_22" : 288,
- "minecraft:element_23" : 289,
- "minecraft:element_24" : 290,
- "minecraft:element_25" : 291,
- "minecraft:element_26" : 292,
- "minecraft:element_27" : 293,
- "minecraft:element_28" : 294,
- "minecraft:element_29" : 295,
- "minecraft:element_30" : 296,
- "minecraft:element_31" : 297,
- "minecraft:element_32" : 298,
- "minecraft:element_33" : 299,
- "minecraft:element_34" : 300,
- "minecraft:element_35" : 301,
- "minecraft:element_36" : 302,
- "minecraft:element_37" : 303,
- "minecraft:element_38" : 304,
- "minecraft:element_39" : 305,
- "minecraft:element_40" : 306,
- "minecraft:element_41" : 307,
- "minecraft:element_42" : 308,
- "minecraft:element_43" : 309,
- "minecraft:element_44" : 310,
- "minecraft:element_45" : 311,
- "minecraft:element_46" : 312,
- "minecraft:element_47" : 313,
- "minecraft:element_48" : 314,
- "minecraft:element_49" : 315,
- "minecraft:element_50" : 316,
- "minecraft:element_51" : 317,
- "minecraft:element_52" : 318,
- "minecraft:element_53" : 319,
- "minecraft:element_54" : 320,
- "minecraft:element_55" : 321,
- "minecraft:element_56" : 322,
- "minecraft:element_57" : 323,
- "minecraft:element_58" : 324,
- "minecraft:element_59" : 325,
- "minecraft:element_60" : 326,
- "minecraft:element_61" : 327,
- "minecraft:element_62" : 328,
- "minecraft:element_63" : 329,
- "minecraft:element_64" : 330,
- "minecraft:element_65" : 331,
- "minecraft:element_66" : 332,
- "minecraft:element_67" : 333,
- "minecraft:element_68" : 334,
- "minecraft:element_69" : 335,
- "minecraft:element_70" : 336,
- "minecraft:element_71" : 337,
- "minecraft:element_72" : 338,
- "minecraft:element_73" : 339,
- "minecraft:element_74" : 340,
- "minecraft:element_75" : 341,
- "minecraft:element_76" : 342,
- "minecraft:element_77" : 343,
- "minecraft:element_78" : 344,
- "minecraft:element_79" : 345,
- "minecraft:element_80" : 346,
- "minecraft:element_81" : 347,
- "minecraft:element_82" : 348,
- "minecraft:element_83" : 349,
- "minecraft:element_84" : 350,
- "minecraft:element_85" : 351,
- "minecraft:element_86" : 352,
- "minecraft:element_87" : 353,
- "minecraft:element_88" : 354,
- "minecraft:element_89" : 355,
- "minecraft:element_90" : 356,
- "minecraft:element_91" : 357,
- "minecraft:element_92" : 358,
- "minecraft:element_93" : 359,
- "minecraft:element_94" : 360,
- "minecraft:element_95" : 361,
- "minecraft:element_96" : 362,
- "minecraft:element_97" : 363,
- "minecraft:element_98" : 364,
- "minecraft:element_99" : 365,
- "minecraft:element_100" : 366,
- "minecraft:element_101" : 367,
- "minecraft:element_102" : 368,
- "minecraft:element_103" : 369,
- "minecraft:element_104" : 370,
- "minecraft:element_105" : 371,
- "minecraft:element_106" : 372,
- "minecraft:element_107" : 373,
- "minecraft:element_108" : 374,
- "minecraft:element_109" : 375,
- "minecraft:element_110" : 376,
- "minecraft:element_111" : 377,
- "minecraft:element_112" : 378,
- "minecraft:element_113" : 379,
- "minecraft:element_114" : 380,
- "minecraft:element_115" : 381,
- "minecraft:element_116" : 382,
- "minecraft:element_117" : 383,
- "minecraft:element_118" : 384,
- "minecraft:seagrass" : 385,
- "minecraft:coral" : 386,
- "minecraft:coral_block" : 387,
- "minecraft:coral_fan" : 388,
- "minecraft:coral_fan_dead" : 389,
- "minecraft:coral_fan_hang" : 390,
- "minecraft:coral_fan_hang2" : 391,
- "minecraft:coral_fan_hang3" : 392,
- "minecraft:kelp" : 393,
- "minecraft:dried_kelp_block" : 394,
- "minecraft:acacia_button" : 395,
- "minecraft:birch_button" : 396,
- "minecraft:dark_oak_button" : 397,
- "minecraft:jungle_button" : 398,
- "minecraft:spruce_button" : 399,
- "minecraft:acacia_trapdoor" : 400,
- "minecraft:birch_trapdoor" : 401,
- "minecraft:dark_oak_trapdoor" : 402,
- "minecraft:jungle_trapdoor" : 403,
- "minecraft:spruce_trapdoor" : 404,
- "minecraft:acacia_pressure_plate" : 405,
- "minecraft:birch_pressure_plate" : 406,
- "minecraft:dark_oak_pressure_plate" : 407,
- "minecraft:jungle_pressure_plate" : 408,
- "minecraft:spruce_pressure_plate" : 409,
- "minecraft:carved_pumpkin" : 410,
- "minecraft:sea_pickle" : 411,
- "minecraft:conduit" : 412,
- "minecraft:turtle_egg" : 414,
- "minecraft:bubble_column" : 415,
- "minecraft:barrier" : 416,
- "minecraft:stone_slab3" : 417,
- "minecraft:bamboo" : 418,
- "minecraft:bamboo_sapling" : 419,
- "minecraft:scaffolding" : 420,
- "minecraft:stone_slab4" : 421,
- "minecraft:double_stone_slab3" : 422,
- "minecraft:double_stone_slab4" : 423,
- "minecraft:granite_stairs" : 424,
- "minecraft:diorite_stairs" : 425,
- "minecraft:andesite_stairs" : 426,
- "minecraft:polished_granite_stairs" : 427,
- "minecraft:polished_diorite_stairs" : 428,
- "minecraft:polished_andesite_stairs" : 429,
- "minecraft:mossy_stone_brick_stairs" : 430,
- "minecraft:smooth_red_sandstone_stairs" : 431,
- "minecraft:smooth_sandstone_stairs" : 432,
- "minecraft:end_brick_stairs" : 433,
- "minecraft:mossy_cobblestone_stairs" : 434,
- "minecraft:normal_stone_stairs" : 435,
- "minecraft:spruce_standing_sign" : 436,
- "minecraft:spruce_wall_sign" : 437,
- "minecraft:smooth_stone" : 438,
- "minecraft:red_nether_brick_stairs" : 439,
- "minecraft:smooth_quartz_stairs" : 440,
- "minecraft:birch_standing_sign" : 441,
- "minecraft:birch_wall_sign" : 442,
- "minecraft:jungle_standing_sign" : 443,
- "minecraft:jungle_wall_sign" : 444,
- "minecraft:acacia_standing_sign" : 445,
- "minecraft:acacia_wall_sign" : 446,
- "minecraft:darkoak_standing_sign" : 447,
- "minecraft:darkoak_wall_sign" : 448,
- "minecraft:lectern" : 449,
- "minecraft:grindstone" : 450,
- "minecraft:blast_furnace" : 451,
- "minecraft:stonecutter_block" : 452,
- "minecraft:smoker" : 453,
- "minecraft:lit_smoker" : 454,
- "minecraft:cartography_table" : 455,
- "minecraft:fletching_table" : 456,
- "minecraft:smithing_table" : 457,
- "minecraft:barrel" : 458,
- "minecraft:loom" : 459,
- "minecraft:bell" : 461,
- "minecraft:sweet_berry_bush" : 462,
- "minecraft:lantern" : 463,
- "minecraft:campfire" : 464,
- "minecraft:lava_cauldron" : 465,
- "minecraft:jigsaw" : 466,
- "minecraft:wood" : 467,
- "minecraft:composter" : 468,
- "minecraft:lit_blast_furnace" : 469,
- "minecraft:light_block" : 470,
- "minecraft:wither_rose" : 471,
- "minecraft:stickyPistonArmCollision" : 472,
- "minecraft:bee_nest" : 473,
- "minecraft:beehive" : 474,
- "minecraft:honey_block" : 475,
- "minecraft:honeycomb_block" : 476,
- "minecraft:lodestone" : 477,
- "minecraft:crimson_roots" : 478,
- "minecraft:warped_roots" : 479,
- "minecraft:crimson_stem" : 480,
- "minecraft:warped_stem" : 481,
- "minecraft:warped_wart_block" : 482,
- "minecraft:crimson_fungus" : 483,
- "minecraft:warped_fungus" : 484,
- "minecraft:shroomlight" : 485,
- "minecraft:weeping_vines" : 486,
- "minecraft:crimson_nylium" : 487,
- "minecraft:warped_nylium" : 488,
- "minecraft:basalt" : 489,
- "minecraft:polished_basalt" : 490,
- "minecraft:soul_soil" : 491,
- "minecraft:soul_fire" : 492,
- "minecraft:nether_sprouts" : 493,
- "minecraft:target" : 494,
- "minecraft:stripped_crimson_stem" : 495,
- "minecraft:stripped_warped_stem" : 496,
- "minecraft:crimson_planks" : 497,
- "minecraft:warped_planks" : 498,
- "minecraft:crimson_door" : 499,
- "minecraft:warped_door" : 500,
- "minecraft:crimson_trapdoor" : 501,
- "minecraft:warped_trapdoor" : 502,
- "minecraft:crimson_standing_sign" : 505,
- "minecraft:warped_standing_sign" : 506,
- "minecraft:crimson_wall_sign" : 507,
- "minecraft:warped_wall_sign" : 508,
- "minecraft:crimson_stairs" : 509,
- "minecraft:warped_stairs" : 510,
- "minecraft:crimson_fence" : 511,
- "minecraft:warped_fence" : 512,
- "minecraft:crimson_fence_gate" : 513,
- "minecraft:warped_fence_gate" : 514,
- "minecraft:crimson_button" : 515,
- "minecraft:warped_button" : 516,
- "minecraft:crimson_pressure_plate" : 517,
- "minecraft:warped_pressure_plate" : 518,
- "minecraft:crimson_slab" : 519,
- "minecraft:warped_slab" : 520,
- "minecraft:crimson_double_slab" : 521,
- "minecraft:warped_double_slab" : 522,
- "minecraft:soul_torch" : 523,
- "minecraft:soul_lantern" : 524,
- "minecraft:netherite_block" : 525,
- "minecraft:ancient_debris" : 526,
- "minecraft:respawn_anchor" : 527,
- "minecraft:blackstone" : 528,
- "minecraft:polished_blackstone_bricks" : 529,
- "minecraft:polished_blackstone_brick_stairs" : 530,
- "minecraft:blackstone_stairs" : 531,
- "minecraft:blackstone_wall" : 532,
- "minecraft:polished_blackstone_brick_wall" : 533,
- "minecraft:chiseled_polished_blackstone" : 534,
- "minecraft:cracked_polished_blackstone_bricks" : 535,
- "minecraft:gilded_blackstone" : 536,
- "minecraft:blackstone_slab" : 537,
- "minecraft:blackstone_double_slab" : 538,
- "minecraft:polished_blackstone_brick_slab" : 539,
- "minecraft:polished_blackstone_brick_double_slab" : 540,
- "minecraft:chain" : 541,
- "minecraft:twisting_vines" : 542,
- "minecraft:nether_gold_ore" : 543,
- "minecraft:crying_obsidian" : 544,
- "minecraft:soul_campfire" : 545,
- "minecraft:polished_blackstone" : 546,
- "minecraft:polished_blackstone_stairs" : 547,
- "minecraft:polished_blackstone_slab" : 548,
- "minecraft:polished_blackstone_double_slab" : 549,
- "minecraft:polished_blackstone_pressure_plate" : 550,
- "minecraft:polished_blackstone_button" : 551,
- "minecraft:polished_blackstone_wall" : 552,
- "minecraft:warped_hyphae" : 553,
- "minecraft:crimson_hyphae" : 554,
- "minecraft:stripped_crimson_hyphae" : 555,
- "minecraft:stripped_warped_hyphae" : 556,
- "minecraft:chiseled_nether_bricks" : 557,
- "minecraft:cracked_nether_bricks" : 558,
- "minecraft:quartz_bricks" : 559
-}
\ No newline at end of file
diff --git a/connector/src/main/resources/bedrock/legacy_item_ids.json b/connector/src/main/resources/bedrock/legacy_item_ids.json
deleted file mode 100644
index 3f22c91c3..000000000
--- a/connector/src/main/resources/bedrock/legacy_item_ids.json
+++ /dev/null
@@ -1,255 +0,0 @@
-{
- "minecraft:iron_shovel" : 256,
- "minecraft:iron_pickaxe" : 257,
- "minecraft:iron_axe" : 258,
- "minecraft:flint_and_steel" : 259,
- "minecraft:apple" : 260,
- "minecraft:bow" : 261,
- "minecraft:arrow" : 262,
- "minecraft:coal" : 263,
- "minecraft:diamond" : 264,
- "minecraft:iron_ingot" : 265,
- "minecraft:gold_ingot" : 266,
- "minecraft:iron_sword" : 267,
- "minecraft:wooden_sword" : 268,
- "minecraft:wooden_shovel" : 269,
- "minecraft:wooden_pickaxe" : 270,
- "minecraft:wooden_axe" : 271,
- "minecraft:stone_sword" : 272,
- "minecraft:stone_shovel" : 273,
- "minecraft:stone_pickaxe" : 274,
- "minecraft:stone_axe" : 275,
- "minecraft:diamond_sword" : 276,
- "minecraft:diamond_shovel" : 277,
- "minecraft:diamond_pickaxe" : 278,
- "minecraft:diamond_axe" : 279,
- "minecraft:stick" : 280,
- "minecraft:bowl" : 281,
- "minecraft:mushroom_stew" : 282,
- "minecraft:golden_sword" : 283,
- "minecraft:golden_shovel" : 284,
- "minecraft:golden_pickaxe" : 285,
- "minecraft:golden_axe" : 286,
- "minecraft:string" : 287,
- "minecraft:feather" : 288,
- "minecraft:gunpowder" : 289,
- "minecraft:wooden_hoe" : 290,
- "minecraft:stone_hoe" : 291,
- "minecraft:iron_hoe" : 292,
- "minecraft:diamond_hoe" : 293,
- "minecraft:golden_hoe" : 294,
- "minecraft:wheat_seeds" : 295,
- "minecraft:wheat" : 296,
- "minecraft:bread" : 297,
- "minecraft:leather_helmet" : 298,
- "minecraft:leather_chestplate" : 299,
- "minecraft:leather_leggings" : 300,
- "minecraft:leather_boots" : 301,
- "minecraft:chainmail_helmet" : 302,
- "minecraft:chainmail_chestplate" : 303,
- "minecraft:chainmail_leggings" : 304,
- "minecraft:chainmail_boots" : 305,
- "minecraft:iron_helmet" : 306,
- "minecraft:iron_chestplate" : 307,
- "minecraft:iron_leggings" : 308,
- "minecraft:iron_boots" : 309,
- "minecraft:diamond_helmet" : 310,
- "minecraft:diamond_chestplate" : 311,
- "minecraft:diamond_leggings" : 312,
- "minecraft:diamond_boots" : 313,
- "minecraft:golden_helmet" : 314,
- "minecraft:golden_chestplate" : 315,
- "minecraft:golden_leggings" : 316,
- "minecraft:golden_boots" : 317,
- "minecraft:flint" : 318,
- "minecraft:porkchop" : 319,
- "minecraft:cooked_porkchop" : 320,
- "minecraft:painting" : 321,
- "minecraft:golden_apple" : 322,
- "minecraft:sign" : 323,
- "minecraft:wooden_door" : 324,
- "minecraft:bucket" : 325,
- "minecraft:minecart" : 328,
- "minecraft:saddle" : 329,
- "minecraft:iron_door" : 330,
- "minecraft:redstone" : 331,
- "minecraft:snowball" : 332,
- "minecraft:boat" : 333,
- "minecraft:leather" : 334,
- "minecraft:kelp" : 335,
- "minecraft:brick" : 336,
- "minecraft:clay_ball" : 337,
- "minecraft:reeds" : 338,
- "minecraft:paper" : 339,
- "minecraft:book" : 340,
- "minecraft:slime_ball" : 341,
- "minecraft:chest_minecart" : 342,
- "minecraft:egg" : 344,
- "minecraft:compass" : 345,
- "minecraft:fishing_rod" : 346,
- "minecraft:clock" : 347,
- "minecraft:glowstone_dust" : 348,
- "minecraft:fish" : 349,
- "minecraft:cooked_fish" : 350,
- "minecraft:dye" : 351,
- "minecraft:bone" : 352,
- "minecraft:sugar" : 353,
- "minecraft:cake" : 354,
- "minecraft:bed" : 355,
- "minecraft:repeater" : 356,
- "minecraft:cookie" : 357,
- "minecraft:map" : 358,
- "minecraft:shears" : 359,
- "minecraft:melon" : 360,
- "minecraft:pumpkin_seeds" : 361,
- "minecraft:melon_seeds" : 362,
- "minecraft:beef" : 363,
- "minecraft:cooked_beef" : 364,
- "minecraft:chicken" : 365,
- "minecraft:cooked_chicken" : 366,
- "minecraft:rotten_flesh" : 367,
- "minecraft:ender_pearl" : 368,
- "minecraft:blaze_rod" : 369,
- "minecraft:ghast_tear" : 370,
- "minecraft:gold_nugget" : 371,
- "minecraft:nether_wart" : 372,
- "minecraft:potion" : 373,
- "minecraft:glass_bottle" : 374,
- "minecraft:spider_eye" : 375,
- "minecraft:fermented_spider_eye" : 376,
- "minecraft:blaze_powder" : 377,
- "minecraft:magma_cream" : 378,
- "minecraft:brewing_stand" : 379,
- "minecraft:cauldron" : 380,
- "minecraft:ender_eye" : 381,
- "minecraft:speckled_melon" : 382,
- "minecraft:spawn_egg" : 383,
- "minecraft:experience_bottle" : 384,
- "minecraft:fireball" : 385,
- "minecraft:writable_book" : 386,
- "minecraft:written_book" : 387,
- "minecraft:emerald" : 388,
- "minecraft:frame" : 389,
- "minecraft:flower_pot" : 390,
- "minecraft:carrot" : 391,
- "minecraft:potato" : 392,
- "minecraft:baked_potato" : 393,
- "minecraft:poisonous_potato" : 394,
- "minecraft:emptymap" : 395,
- "minecraft:golden_carrot" : 396,
- "minecraft:skull" : 397,
- "minecraft:carrotonastick" : 398,
- "minecraft:netherstar" : 399,
- "minecraft:pumpkin_pie" : 400,
- "minecraft:fireworks" : 401,
- "minecraft:fireworkscharge" : 402,
- "minecraft:enchanted_book" : 403,
- "minecraft:comparator" : 404,
- "minecraft:netherbrick" : 405,
- "minecraft:quartz" : 406,
- "minecraft:tnt_minecart" : 407,
- "minecraft:hopper_minecart" : 408,
- "minecraft:prismarine_shard" : 409,
- "minecraft:hopper" : 410,
- "minecraft:rabbit" : 411,
- "minecraft:cooked_rabbit" : 412,
- "minecraft:rabbit_stew" : 413,
- "minecraft:rabbit_foot" : 414,
- "minecraft:rabbit_hide" : 415,
- "minecraft:horsearmorleather" : 416,
- "minecraft:horsearmoriron" : 417,
- "minecraft:horsearmorgold" : 418,
- "minecraft:horsearmordiamond" : 419,
- "minecraft:lead" : 420,
- "minecraft:name_tag" : 421,
- "minecraft:prismarine_crystals" : 422,
- "minecraft:muttonraw" : 423,
- "minecraft:muttoncooked" : 424,
- "minecraft:armor_stand" : 425,
- "minecraft:end_crystal" : 426,
- "minecraft:spruce_door" : 427,
- "minecraft:birch_door" : 428,
- "minecraft:jungle_door" : 429,
- "minecraft:acacia_door" : 430,
- "minecraft:dark_oak_door" : 431,
- "minecraft:chorus_fruit" : 432,
- "minecraft:chorus_fruit_popped" : 433,
- "minecraft:banner_pattern" : 434,
- "minecraft:dragon_breath" : 437,
- "minecraft:splash_potion" : 438,
- "minecraft:lingering_potion" : 441,
- "minecraft:sparkler" : 442,
- "minecraft:command_block_minecart" : 443,
- "minecraft:elytra" : 444,
- "minecraft:shulker_shell" : 445,
- "minecraft:banner" : 446,
- "minecraft:medicine" : 447,
- "minecraft:balloon" : 448,
- "minecraft:rapid_fertilizer" : 449,
- "minecraft:totem" : 450,
- "minecraft:bleach" : 451,
- "minecraft:iron_nugget" : 452,
- "minecraft:ice_bomb" : 453,
- "minecraft:trident" : 455,
- "minecraft:beetroot" : 457,
- "minecraft:beetroot_seeds" : 458,
- "minecraft:beetroot_soup" : 459,
- "minecraft:salmon" : 460,
- "minecraft:clownfish" : 461,
- "minecraft:pufferfish" : 462,
- "minecraft:cooked_salmon" : 463,
- "minecraft:dried_kelp" : 464,
- "minecraft:nautilus_shell" : 465,
- "minecraft:appleenchanted" : 466,
- "minecraft:heart_of_the_sea" : 467,
- "minecraft:turtle_shell_piece" : 468,
- "minecraft:turtle_helmet" : 469,
- "minecraft:phantom_membrane" : 470,
- "minecraft:crossbow" : 471,
- "minecraft:spruce_sign" : 472,
- "minecraft:birch_sign" : 473,
- "minecraft:jungle_sign" : 474,
- "minecraft:acacia_sign" : 475,
- "minecraft:darkoak_sign" : 476,
- "minecraft:sweet_berries" : 477,
- "minecraft:camera" : 498,
- "minecraft:compound" : 499,
- "minecraft:record_13" : 500,
- "minecraft:record_cat" : 501,
- "minecraft:record_blocks" : 502,
- "minecraft:record_chirp" : 503,
- "minecraft:record_far" : 504,
- "minecraft:record_mall" : 505,
- "minecraft:record_mellohi" : 506,
- "minecraft:record_stal" : 507,
- "minecraft:record_strad" : 508,
- "minecraft:record_ward" : 509,
- "minecraft:record_11" : 510,
- "minecraft:record_wait" : 511,
- "minecraft:shield" : 513,
- "minecraft:campfire" : 720,
- "minecraft:suspicious_stew" : 734,
- "minecraft:honeycomb" : 736,
- "minecraft:honey_bottle" : 737,
- "minecraft:lodestonecompass" : 741,
- "minecraft:netherite_ingot" : 742,
- "minecraft:netherite_sword" : 743,
- "minecraft:netherite_shovel" : 744,
- "minecraft:netherite_pickaxe" : 745,
- "minecraft:netherite_axe" : 746,
- "minecraft:netherite_hoe" : 747,
- "minecraft:netherite_helmet" : 748,
- "minecraft:netherite_chestplate" : 749,
- "minecraft:netherite_leggings" : 750,
- "minecraft:netherite_boots" : 751,
- "minecraft:netherite_scrap" : 752,
- "minecraft:crimson_sign" : 753,
- "minecraft:warped_sign" : 754,
- "minecraft:crimson_door" : 755,
- "minecraft:warped_door" : 756,
- "minecraft:warped_fungus_on_a_stick" : 757,
- "minecraft:chain" : 758,
- "minecraft:record_pigstep" : 759,
- "minecraft:nether_sprouts" : 760,
- "minecraft:soul_campfire" : 801
-}
\ No newline at end of file
diff --git a/connector/src/main/resources/bedrock/runtime_block_states.dat b/connector/src/main/resources/bedrock/runtime_block_states.dat
deleted file mode 100644
index feeeda664..000000000
Binary files a/connector/src/main/resources/bedrock/runtime_block_states.dat and /dev/null differ
diff --git a/connector/src/main/resources/bedrock/items.json b/connector/src/main/resources/bedrock/runtime_item_states.json
similarity index 84%
rename from connector/src/main/resources/bedrock/items.json
rename to connector/src/main/resources/bedrock/runtime_item_states.json
index 0614b3641..eaf6656bd 100644
--- a/connector/src/main/resources/bedrock/items.json
+++ b/connector/src/main/resources/bedrock/runtime_item_states.json
@@ -1,2315 +1,975 @@
[
{
- "name" : "minecraft:purpur_block",
- "id" : 201
- },
- {
- "name" : "minecraft:bow",
- "id" : 261
- },
- {
- "name" : "minecraft:end_bricks",
- "id" : 206
- },
- {
- "name" : "minecraft:air",
- "id" : -158
- },
- {
- "name" : "minecraft:element_94",
- "id" : -105
- },
- {
- "name" : "minecraft:rabbit",
- "id" : 411
- },
- {
- "name" : "minecraft:element_25",
- "id" : -36
- },
- {
- "name" : "minecraft:mushroom_stew",
- "id" : 282
- },
- {
- "name" : "minecraft:polished_blackstone_brick_slab",
- "id" : -284
- },
- {
- "name" : "minecraft:cooked_porkchop",
- "id" : 320
- },
- {
- "name" : "minecraft:record_ward",
- "id" : 509
- },
- {
- "name" : "minecraft:appleenchanted",
- "id" : 466
- },
- {
- "name" : "minecraft:pumpkin",
- "id" : 86
- },
- {
- "name" : "minecraft:slime",
- "id" : 165
- },
- {
- "name" : "minecraft:apple",
- "id" : 260
- },
- {
- "name" : "minecraft:element_50",
- "id" : -61
- },
- {
- "name" : "minecraft:stripped_oak_log",
- "id" : -10
- },
- {
- "name" : "minecraft:golden_apple",
- "id" : 322
- },
- {
- "name" : "minecraft:fish",
- "id" : 349
- },
- {
- "name" : "minecraft:item.dark_oak_door",
- "id" : 197
- },
- {
- "name" : "minecraft:light_block",
- "id" : -215
- },
- {
- "name" : "minecraft:yellow_glazed_terracotta",
- "id" : 224
- },
- {
- "name" : "minecraft:stone_brick_stairs",
- "id" : 109
- },
- {
- "name" : "minecraft:portal",
- "id" : 90
- },
- {
- "name" : "minecraft:gold_ingot",
- "id" : 266
- },
- {
- "name" : "minecraft:iron_ingot",
- "id" : 265
- },
- {
- "name" : "minecraft:cookie",
- "id" : 357
- },
- {
- "name" : "minecraft:porkchop",
- "id" : 319
- },
- {
- "name" : "minecraft:bread",
- "id" : 297
- },
- {
- "name" : "minecraft:element_7",
- "id" : -18
- },
- {
- "name" : "minecraft:diamond_block",
- "id" : 57
- },
- {
- "name" : "minecraft:iron_pickaxe",
- "id" : 257
- },
- {
- "name" : "minecraft:element_27",
- "id" : -38
- },
- {
- "name" : "minecraft:beef",
- "id" : 363
- },
- {
- "name" : "minecraft:salmon",
- "id" : 460
- },
- {
- "name" : "minecraft:melon",
- "id" : 360
- },
- {
- "name" : "minecraft:clownfish",
- "id" : 461
- },
- {
- "name" : "minecraft:element_16",
- "id" : -27
- },
- {
- "name" : "minecraft:tripwire",
- "id" : 132
- },
- {
- "name" : "minecraft:stone_axe",
- "id" : 275
- },
- {
- "name" : "minecraft:stained_glass_pane",
- "id" : 160
- },
- {
- "name" : "minecraft:trapped_chest",
- "id" : 146
- },
- {
- "name" : "minecraft:pufferfish",
- "id" : 462
- },
- {
- "name" : "minecraft:bucket",
- "id" : 325
- },
- {
- "name" : "minecraft:ancient_debris",
- "id" : -271
- },
- {
- "name" : "minecraft:anvil",
- "id" : 145
- },
- {
- "name" : "minecraft:stick",
- "id" : 280
- },
- {
- "name" : "minecraft:cooked_fish",
- "id" : 350
- },
- {
- "name" : "minecraft:cooked_salmon",
- "id" : 463
- },
- {
- "name" : "minecraft:element_61",
- "id" : -72
- },
- {
- "name" : "minecraft:sparkler",
- "id" : 442
- },
- {
- "name" : "minecraft:warped_door",
- "id" : 756
- },
- {
- "name" : "minecraft:dried_kelp",
- "id" : 464
- },
- {
- "name" : "minecraft:hay_block",
- "id" : 170
- },
- {
- "name" : "minecraft:wooden_shovel",
- "id" : 269
- },
- {
- "name" : "minecraft:nautilus_shell",
- "id" : 465
- },
- {
- "name" : "minecraft:element_1",
- "id" : -12
- },
- {
- "name" : "minecraft:stonecutter_block",
- "id" : -197
- },
- {
- "name" : "minecraft:cooked_beef",
- "id" : 364
- },
- {
- "name" : "minecraft:comparator",
- "id" : 404
- },
- {
- "name" : "minecraft:carrot",
- "id" : 391
- },
- {
- "name" : "minecraft:command_block",
- "id" : 137
- },
- {
- "name" : "minecraft:chicken",
- "id" : 365
- },
- {
- "name" : "minecraft:potion",
- "id" : 373
- },
- {
- "name" : "minecraft:rotten_flesh",
- "id" : 367
- },
- {
- "name" : "minecraft:dirt",
- "id" : 3
- },
- {
- "name" : "minecraft:element_62",
- "id" : -73
- },
- {
- "name" : "minecraft:daylight_detector",
- "id" : 151
- },
- {
- "name" : "minecraft:snow_layer",
- "id" : 78
- },
- {
- "name" : "minecraft:rabbit_foot",
- "id" : 414
- },
- {
- "name" : "minecraft:lingering_potion",
- "id" : 441
- },
- {
- "name" : "minecraft:campfire",
- "id" : 720
- },
- {
- "name" : "minecraft:smoker",
- "id" : -198
- },
- {
- "name" : "minecraft:warped_fence",
- "id" : -257
- },
- {
- "name" : "minecraft:cooked_chicken",
- "id" : 366
- },
- {
- "name" : "minecraft:light_blue_glazed_terracotta",
- "id" : 223
- },
- {
- "name" : "minecraft:stone_sword",
- "id" : 272
- },
- {
- "name" : "minecraft:record_far",
- "id" : 504
- },
- {
- "name" : "minecraft:spider_eye",
- "id" : 375
- },
- {
- "name" : "minecraft:smooth_quartz_stairs",
- "id" : -185
- },
- {
- "name" : "minecraft:potato",
- "id" : 392
- },
- {
- "name" : "minecraft:baked_potato",
- "id" : 393
- },
- {
- "name" : "minecraft:element_88",
- "id" : -99
- },
- {
- "name" : "minecraft:golden_carrot",
- "id" : 396
- },
- {
- "name" : "minecraft:spruce_stairs",
- "id" : 134
- },
- {
- "name" : "minecraft:poisonous_potato",
- "id" : 394
- },
- {
- "name" : "minecraft:element_13",
- "id" : -24
- },
- {
- "name" : "minecraft:obsidian",
- "id" : 49
- },
- {
- "name" : "minecraft:pumpkin_pie",
- "id" : 400
- },
- {
- "name" : "minecraft:diamond_pickaxe",
- "id" : 278
- },
- {
- "name" : "minecraft:lantern",
- "id" : -208
- },
- {
- "name" : "minecraft:iron_sword",
- "id" : 267
- },
- {
- "name" : "minecraft:smooth_stone",
- "id" : -183
- },
- {
- "name" : "minecraft:beetroot",
- "id" : 457
- },
- {
- "name" : "minecraft:element_43",
- "id" : -54
- },
- {
- "name" : "minecraft:beetroot_soup",
- "id" : 459
- },
- {
- "name" : "minecraft:red_mushroom",
- "id" : 40
- },
- {
- "name" : "minecraft:wooden_pickaxe",
- "id" : 270
- },
- {
- "name" : "minecraft:invisiblebedrock",
- "id" : 95
- },
- {
- "name" : "minecraft:sweet_berries",
- "id" : 477
- },
- {
- "name" : "minecraft:prismarine_bricks_stairs",
- "id" : -4
- },
- {
- "name" : "minecraft:cooked_rabbit",
- "id" : 412
- },
- {
- "name" : "minecraft:rabbit_stew",
- "id" : 413
- },
- {
- "name" : "minecraft:birch_fence_gate",
- "id" : 184
- },
- {
- "name" : "minecraft:wheat_seeds",
- "id" : 295
- },
- {
- "name" : "minecraft:chest",
- "id" : 54
- },
- {
- "name" : "minecraft:pumpkin_seeds",
- "id" : 361
- },
- {
- "name" : "minecraft:element_2",
- "id" : -13
- },
- {
- "name" : "minecraft:item.crimson_door",
- "id" : -244
- },
- {
- "name" : "minecraft:command_block_minecart",
- "id" : 443
- },
- {
- "name" : "minecraft:melon_seeds",
- "id" : 362
- },
- {
- "name" : "minecraft:iron_axe",
- "id" : 258
- },
- {
- "name" : "minecraft:spawn_egg",
- "id" : 383
- },
- {
- "name" : "minecraft:element_93",
- "id" : -104
- },
- {
- "name" : "minecraft:nether_wart",
- "id" : 372
- },
- {
- "name" : "minecraft:beetroot_seeds",
- "id" : 458
- },
- {
- "name" : "minecraft:element_35",
- "id" : -46
- },
- {
- "name" : "minecraft:iron_shovel",
- "id" : 256
- },
- {
- "name" : "minecraft:element_104",
- "id" : -115
- },
- {
- "name" : "minecraft:granite_stairs",
- "id" : -169
- },
- {
- "name" : "minecraft:flint_and_steel",
- "id" : 259
- },
- {
- "name" : "minecraft:stone_shovel",
- "id" : 273
- },
- {
- "name" : "minecraft:horsearmorleather",
- "id" : 416
- },
- {
- "name" : "minecraft:item.cauldron",
- "id" : 118
- },
- {
- "name" : "minecraft:melon_block",
- "id" : 103
- },
- {
- "name" : "minecraft:arrow",
- "id" : 262
- },
- {
- "name" : "minecraft:coal",
- "id" : 263
- },
- {
- "name" : "minecraft:real_double_stone_slab2",
- "id" : 181
- },
- {
- "name" : "minecraft:chorus_plant",
- "id" : 240
- },
- {
- "name" : "minecraft:gold_block",
- "id" : 41
- },
- {
- "name" : "minecraft:carrots",
- "id" : 141
- },
- {
- "name" : "minecraft:diamond",
- "id" : 264
- },
- {
- "name" : "minecraft:wooden_sword",
- "id" : 268
- },
- {
- "name" : "minecraft:record_strad",
- "id" : 508
- },
- {
- "name" : "minecraft:netherite_boots",
- "id" : 751
- },
- {
- "name" : "minecraft:dark_oak_stairs",
- "id" : 164
- },
- {
- "name" : "minecraft:farmland",
- "id" : 60
- },
- {
- "name" : "minecraft:wooden_axe",
- "id" : 271
- },
- {
- "name" : "minecraft:stone_pickaxe",
- "id" : 274
- },
- {
- "name" : "minecraft:planks",
- "id" : 5
- },
- {
- "name" : "minecraft:chainmail_helmet",
- "id" : 302
- },
- {
- "name" : "minecraft:diamond_shovel",
- "id" : 277
- },
- {
- "name" : "minecraft:diamond_sword",
- "id" : 276
- },
- {
- "name" : "minecraft:smithing_table",
- "id" : -202
- },
- {
- "name" : "minecraft:diamond_axe",
- "id" : 279
- },
- {
- "name" : "minecraft:bowl",
- "id" : 281
- },
- {
- "name" : "minecraft:flowing_water",
- "id" : 8
- },
- {
- "name" : "minecraft:golden_sword",
- "id" : 283
- },
- {
- "name" : "minecraft:honey_block",
- "id" : -220
- },
- {
- "name" : "minecraft:golden_shovel",
- "id" : 284
- },
- {
- "name" : "minecraft:golden_pickaxe",
- "id" : 285
- },
- {
- "name" : "minecraft:lit_redstone_lamp",
- "id" : 124
- },
- {
- "name" : "minecraft:elytra",
- "id" : 444
- },
- {
- "name" : "minecraft:golden_axe",
- "id" : 286
- },
- {
- "name" : "minecraft:element_52",
- "id" : -63
- },
- {
- "name" : "minecraft:string",
- "id" : 287
- },
- {
- "name" : "minecraft:real_double_stone_slab4",
- "id" : -168
- },
- {
- "name" : "minecraft:feather",
- "id" : 288
- },
- {
- "name" : "minecraft:gunpowder",
- "id" : 289
- },
- {
- "name" : "minecraft:acacia_stairs",
- "id" : 163
- },
- {
- "name" : "minecraft:wooden_hoe",
- "id" : 290
- },
- {
- "name" : "minecraft:stone_hoe",
- "id" : 291
- },
- {
- "name" : "minecraft:iron_hoe",
- "id" : 292
- },
- {
- "name" : "minecraft:diamond_hoe",
- "id" : 293
- },
- {
- "name" : "minecraft:element_86",
- "id" : -97
- },
- {
- "name" : "minecraft:golden_hoe",
- "id" : 294
- },
- {
- "name" : "minecraft:wheat",
- "id" : 296
- },
- {
- "name" : "minecraft:leather_helmet",
- "id" : 298
- },
- {
- "name" : "minecraft:leather_chestplate",
- "id" : 299
- },
- {
- "name" : "minecraft:leather_leggings",
- "id" : 300
- },
- {
- "name" : "minecraft:lodestone",
- "id" : -222
- },
- {
- "name" : "minecraft:brown_mushroom",
- "id" : 39
- },
- {
- "name" : "minecraft:leather_boots",
- "id" : 301
- },
- {
- "name" : "minecraft:chainmail_chestplate",
- "id" : 303
- },
- {
- "name" : "minecraft:end_gateway",
- "id" : 209
- },
- {
- "name" : "minecraft:item.beetroot",
- "id" : 244
- },
- {
- "name" : "minecraft:chainmail_leggings",
- "id" : 304
- },
- {
- "name" : "minecraft:element_101",
- "id" : -112
- },
- {
- "name" : "minecraft:chainmail_boots",
- "id" : 305
- },
- {
- "name" : "minecraft:soul_sand",
- "id" : 88
- },
- {
- "name" : "minecraft:iron_helmet",
- "id" : 306
- },
- {
- "name" : "minecraft:snowball",
- "id" : 332
- },
- {
- "name" : "minecraft:element_49",
- "id" : -60
- },
- {
- "name" : "minecraft:record_mellohi",
- "id" : 506
- },
- {
- "name" : "minecraft:iron_chestplate",
- "id" : 307
- },
- {
- "name" : "minecraft:barrel",
- "id" : -203
- },
- {
- "name" : "minecraft:iron_leggings",
- "id" : 308
- },
- {
- "name" : "minecraft:crimson_double_slab",
- "id" : -266
- },
- {
- "name" : "minecraft:iron_boots",
- "id" : 309
- },
- {
- "name" : "minecraft:real_double_stone_slab3",
- "id" : -167
- },
- {
- "name" : "minecraft:ender_eye",
- "id" : 381
- },
- {
- "name" : "minecraft:stickypistonarmcollision",
- "id" : -217
- },
- {
- "name" : "minecraft:iron_trapdoor",
- "id" : 167
- },
- {
- "name" : "minecraft:diamond_helmet",
- "id" : 310
- },
- {
- "name" : "minecraft:stone_pressure_plate",
- "id" : 70
- },
- {
- "name" : "minecraft:diamond_chestplate",
- "id" : 311
- },
- {
- "name" : "minecraft:sand",
- "id" : 12
- },
- {
- "name" : "minecraft:light_weighted_pressure_plate",
- "id" : 147
- },
- {
- "name" : "minecraft:piston",
- "id" : 33
- },
- {
- "name" : "minecraft:diamond_leggings",
- "id" : 312
- },
- {
- "name" : "minecraft:element_30",
- "id" : -41
- },
- {
- "name" : "minecraft:diamond_boots",
- "id" : 313
- },
- {
- "name" : "minecraft:golden_helmet",
- "id" : 314
- },
- {
- "name" : "minecraft:element_51",
- "id" : -62
- },
- {
- "name" : "minecraft:double_wooden_slab",
- "id" : 157
- },
- {
- "name" : "minecraft:hard_stained_glass",
- "id" : 254
- },
- {
- "name" : "minecraft:element_84",
- "id" : -95
- },
- {
- "name" : "minecraft:golden_chestplate",
- "id" : 315
- },
- {
- "name" : "minecraft:sealantern",
- "id" : 169
- },
- {
- "name" : "minecraft:bedrock",
- "id" : 7
- },
- {
- "name" : "minecraft:glowstone",
- "id" : 89
- },
- {
- "name" : "minecraft:golden_leggings",
- "id" : 316
- },
- {
- "name" : "minecraft:golden_boots",
- "id" : 317
- },
- {
- "name" : "minecraft:shield",
- "id" : 513
- },
- {
- "name" : "minecraft:jungle_fence_gate",
- "id" : 185
- },
- {
- "name" : "minecraft:carpet",
- "id" : 171
- },
- {
- "name" : "minecraft:flowing_lava",
- "id" : 10
- },
- {
- "name" : "minecraft:flint",
- "id" : 318
- },
- {
- "name" : "minecraft:painting",
- "id" : 321
- },
- {
- "name" : "minecraft:heart_of_the_sea",
- "id" : 467
- },
- {
- "name" : "minecraft:sign",
- "id" : 323
- },
- {
- "name" : "minecraft:muttonraw",
- "id" : 423
- },
- {
- "name" : "minecraft:element_55",
- "id" : -66
- },
- {
- "name" : "minecraft:wooden_door",
- "id" : 324
- },
- {
- "name" : "minecraft:concrete_powder",
- "id" : 237
- },
- {
- "name" : "minecraft:minecart",
- "id" : 328
- },
- {
- "name" : "minecraft:saddle",
- "id" : 329
- },
- {
- "name" : "minecraft:nether_wart_block",
- "id" : 214
- },
- {
- "name" : "minecraft:crimson_roots",
- "id" : -223
- },
- {
- "name" : "minecraft:element_116",
- "id" : -127
- },
- {
- "name" : "minecraft:iron_door",
- "id" : 330
- },
- {
- "name" : "minecraft:redstone",
- "id" : 331
- },
- {
- "name" : "minecraft:boat",
- "id" : 333
- },
- {
- "name" : "minecraft:written_book",
- "id" : 387
- },
- {
- "name" : "minecraft:iron_ore",
- "id" : 15
- },
- {
- "name" : "minecraft:leather",
- "id" : 334
- },
- {
- "name" : "minecraft:kelp",
- "id" : 335
- },
- {
- "name" : "minecraft:gold_nugget",
- "id" : 371
- },
- {
- "name" : "minecraft:brick",
- "id" : 336
- },
- {
- "name" : "minecraft:element_68",
- "id" : -79
- },
- {
- "name" : "minecraft:clay_ball",
- "id" : 337
- },
- {
- "name" : "minecraft:carrotonastick",
- "id" : 398
- },
- {
- "name" : "minecraft:reeds",
- "id" : 338
- },
- {
- "name" : "minecraft:paper",
- "id" : 339
- },
- {
- "name" : "minecraft:element_23",
- "id" : -34
- },
- {
- "name" : "minecraft:coral",
- "id" : -131
- },
- {
- "name" : "minecraft:book",
- "id" : 340
- },
- {
- "name" : "minecraft:end_portal",
- "id" : 119
- },
- {
- "name" : "minecraft:trident",
- "id" : 455
- },
- {
- "name" : "minecraft:slime_ball",
- "id" : 341
- },
- {
- "name" : "minecraft:chest_minecart",
- "id" : 342
- },
- {
- "name" : "minecraft:element_71",
- "id" : -82
- },
- {
- "name" : "minecraft:egg",
- "id" : 344
- },
- {
- "name" : "minecraft:netherite_sword",
- "id" : 743
- },
- {
- "name" : "minecraft:item.reeds",
- "id" : 83
- },
- {
- "name" : "minecraft:compass",
- "id" : 345
- },
- {
- "name" : "minecraft:crimson_stairs",
- "id" : -254
- },
- {
- "name" : "minecraft:fishing_rod",
- "id" : 346
- },
- {
- "name" : "minecraft:andesite_stairs",
- "id" : -171
- },
- {
- "name" : "minecraft:reserved6",
- "id" : 255
- },
- {
- "name" : "minecraft:clock",
- "id" : 347
- },
- {
- "name" : "minecraft:red_sandstone",
- "id" : 179
- },
- {
- "name" : "minecraft:spruce_button",
- "id" : -144
- },
- {
- "name" : "minecraft:glowstone_dust",
- "id" : 348
- },
- {
- "name" : "minecraft:blaze_rod",
- "id" : 369
- },
- {
- "name" : "minecraft:dye",
- "id" : 351
- },
- {
- "name" : "minecraft:element_74",
- "id" : -85
- },
- {
- "name" : "minecraft:bone",
- "id" : 352
- },
- {
- "name" : "minecraft:map",
- "id" : 358
- },
- {
- "name" : "minecraft:sugar",
- "id" : 353
- },
- {
- "name" : "minecraft:name_tag",
- "id" : 421
- },
- {
- "name" : "minecraft:cake",
- "id" : 354
- },
- {
- "name" : "minecraft:bed",
- "id" : 355
- },
- {
- "name" : "minecraft:stained_glass",
- "id" : 241
- },
- {
- "name" : "minecraft:repeater",
- "id" : 356
- },
- {
- "name" : "minecraft:beacon",
- "id" : 138
- },
- {
- "name" : "minecraft:netherite_chestplate",
- "id" : 749
- },
- {
- "name" : "minecraft:unpowered_comparator",
- "id" : 149
- },
- {
- "name" : "minecraft:shears",
- "id" : 359
- },
- {
- "name" : "minecraft:element_31",
- "id" : -42
- },
- {
- "name" : "minecraft:ender_pearl",
- "id" : 368
- },
- {
- "name" : "minecraft:red_sandstone_stairs",
- "id" : 180
- },
- {
- "name" : "minecraft:carved_pumpkin",
- "id" : -155
- },
- {
- "name" : "minecraft:ghast_tear",
- "id" : 370
- },
- {
- "name" : "minecraft:glass_bottle",
- "id" : 374
- },
- {
- "name" : "minecraft:element_44",
- "id" : -55
- },
- {
- "name" : "minecraft:lava",
- "id" : 11
- },
- {
- "name" : "minecraft:polished_blackstone_brick_stairs",
- "id" : -275
- },
- {
- "name" : "minecraft:jungle_pressure_plate",
- "id" : -153
- },
- {
- "name" : "minecraft:fermented_spider_eye",
- "id" : 376
- },
- {
- "name" : "minecraft:honeycomb_block",
- "id" : -221
- },
- {
- "name" : "minecraft:blaze_powder",
+ "name" : "minecraft:acacia_boat",
"id" : 377
},
{
- "name" : "minecraft:magma_cream",
- "id" : 378
- },
- {
- "name" : "minecraft:jigsaw",
- "id" : -211
- },
- {
- "name" : "minecraft:brewing_stand",
- "id" : 379
- },
- {
- "name" : "minecraft:cauldron",
- "id" : 380
- },
- {
- "name" : "minecraft:element_111",
- "id" : -122
- },
- {
- "name" : "minecraft:rapid_fertilizer",
- "id" : 449
- },
- {
- "name" : "minecraft:clay",
- "id" : 82
- },
- {
- "name" : "minecraft:speckled_melon",
- "id" : 382
- },
- {
- "name" : "minecraft:experience_bottle",
- "id" : 384
- },
- {
- "name" : "minecraft:element_48",
- "id" : -59
- },
- {
- "name" : "minecraft:coal_block",
- "id" : 173
- },
- {
- "name" : "minecraft:fireball",
- "id" : 385
- },
- {
- "name" : "minecraft:writable_book",
- "id" : 386
- },
- {
- "name" : "minecraft:element_69",
- "id" : -80
- },
- {
- "name" : "minecraft:emerald",
- "id" : 388
- },
- {
- "name" : "minecraft:record_pigstep",
- "id" : 759
- },
- {
- "name" : "minecraft:element_66",
- "id" : -77
- },
- {
- "name" : "minecraft:frame",
- "id" : 389
- },
- {
- "name" : "minecraft:brewingstandblock",
- "id" : 117
- },
- {
- "name" : "minecraft:flower_pot",
- "id" : 390
- },
- {
- "name" : "minecraft:emptymap",
- "id" : 395
- },
- {
- "name" : "minecraft:element_110",
- "id" : -121
- },
- {
- "name" : "minecraft:element_75",
- "id" : -86
- },
- {
- "name" : "minecraft:skull",
- "id" : 397
- },
- {
- "name" : "minecraft:crimson_door",
- "id" : 755
- },
- {
- "name" : "minecraft:sponge",
- "id" : 19
- },
- {
- "name" : "minecraft:netherstar",
- "id" : 399
- },
- {
- "name" : "minecraft:fireworks",
- "id" : 401
- },
- {
- "name" : "minecraft:hopper_minecart",
- "id" : 408
- },
- {
- "name" : "minecraft:fireworkscharge",
- "id" : 402
- },
- {
- "name" : "minecraft:enchanted_book",
- "id" : 403
- },
- {
- "name" : "minecraft:netherbrick",
- "id" : 405
- },
- {
- "name" : "minecraft:cobblestone_wall",
- "id" : 139
- },
- {
- "name" : "minecraft:quartz",
- "id" : 406
- },
- {
- "name" : "minecraft:tnt_minecart",
- "id" : 407
- },
- {
- "name" : "minecraft:element_63",
- "id" : -74
- },
- {
- "name" : "minecraft:hopper",
- "id" : 410
- },
- {
- "name" : "minecraft:cobblestone",
- "id" : 4
- },
- {
- "name" : "minecraft:dragon_breath",
- "id" : 437
- },
- {
- "name" : "minecraft:rabbit_hide",
- "id" : 415
- },
- {
- "name" : "minecraft:horsearmoriron",
- "id" : 417
- },
- {
- "name" : "minecraft:horsearmorgold",
- "id" : 418
- },
- {
- "name" : "minecraft:colored_torch_bp",
- "id" : 204
- },
- {
- "name" : "minecraft:element_102",
- "id" : -113
- },
- {
- "name" : "minecraft:quartz_ore",
- "id" : 153
- },
- {
- "name" : "minecraft:netherite_shovel",
- "id" : 744
- },
- {
- "name" : "minecraft:horsearmordiamond",
- "id" : 419
- },
- {
- "name" : "minecraft:record_13",
- "id" : 500
- },
- {
- "name" : "minecraft:record_cat",
- "id" : 501
- },
- {
- "name" : "minecraft:element_3",
- "id" : -14
- },
- {
- "name" : "minecraft:polished_diorite_stairs",
- "id" : -173
- },
- {
- "name" : "minecraft:monster_egg",
- "id" : 97
- },
- {
- "name" : "minecraft:record_blocks",
- "id" : 502
- },
- {
- "name" : "minecraft:crimson_standing_sign",
- "id" : -250
- },
- {
- "name" : "minecraft:record_chirp",
- "id" : 503
- },
- {
- "name" : "minecraft:record_mall",
- "id" : 505
- },
- {
- "name" : "minecraft:respawn_anchor",
- "id" : -272
- },
- {
- "name" : "minecraft:record_stal",
- "id" : 507
- },
- {
- "name" : "minecraft:record_11",
- "id" : 510
- },
- {
- "name" : "minecraft:record_wait",
- "id" : 511
- },
- {
- "name" : "minecraft:info_update2",
- "id" : 249
- },
- {
- "name" : "minecraft:lead",
- "id" : 420
- },
- {
- "name" : "minecraft:prismarine_crystals",
- "id" : 422
- },
- {
- "name" : "minecraft:acacia_sign",
- "id" : 475
- },
- {
- "name" : "minecraft:muttoncooked",
- "id" : 424
- },
- {
- "name" : "minecraft:armor_stand",
- "id" : 425
- },
- {
- "name" : "minecraft:coal_ore",
- "id" : 16
- },
- {
- "name" : "minecraft:element_32",
- "id" : -43
- },
- {
- "name" : "minecraft:spruce_door",
- "id" : 427
- },
- {
- "name" : "minecraft:phantom_membrane",
- "id" : 470
- },
- {
- "name" : "minecraft:birch_door",
- "id" : 428
- },
- {
- "name" : "minecraft:element_85",
- "id" : -96
- },
- {
- "name" : "minecraft:polished_blackstone_wall",
- "id" : -297
- },
- {
- "name" : "minecraft:jungle_door",
- "id" : 429
+ "name" : "minecraft:acacia_button",
+ "id" : -140
},
{
"name" : "minecraft:acacia_door",
- "id" : 430
+ "id" : 546
},
{
- "name" : "minecraft:element_42",
- "id" : -53
- },
- {
- "name" : "minecraft:dark_oak_door",
- "id" : 431
- },
- {
- "name" : "minecraft:netherite_leggings",
- "id" : 750
- },
- {
- "name" : "minecraft:stripped_crimson_stem",
- "id" : -240
- },
- {
- "name" : "minecraft:chorus_fruit",
- "id" : 432
- },
- {
- "name" : "minecraft:camera",
- "id" : 498
- },
- {
- "name" : "minecraft:suspicious_stew",
- "id" : 734
- },
- {
- "name" : "minecraft:chorus_fruit_popped",
- "id" : 433
- },
- {
- "name" : "minecraft:element_98",
- "id" : -109
- },
- {
- "name" : "minecraft:splash_potion",
- "id" : 438
- },
- {
- "name" : "minecraft:element_73",
- "id" : -84
- },
- {
- "name" : "minecraft:prismarine_shard",
- "id" : 409
- },
- {
- "name" : "minecraft:seagrass",
- "id" : -130
- },
- {
- "name" : "minecraft:dark_oak_pressure_plate",
- "id" : -152
- },
- {
- "name" : "minecraft:shulker_shell",
- "id" : 445
- },
- {
- "name" : "minecraft:redstone_block",
- "id" : 152
- },
- {
- "name" : "minecraft:banner",
- "id" : 446
- },
- {
- "name" : "minecraft:totem",
- "id" : 450
- },
- {
- "name" : "minecraft:blackstone_slab",
- "id" : -282
- },
- {
- "name" : "minecraft:element_118",
- "id" : -129
- },
- {
- "name" : "minecraft:iron_nugget",
- "id" : 452
- },
- {
- "name" : "minecraft:netherite_pickaxe",
- "id" : 745
- },
- {
- "name" : "minecraft:jukebox",
- "id" : 84
- },
- {
- "name" : "minecraft:turtle_shell_piece",
- "id" : 468
- },
- {
- "name" : "minecraft:turtle_helmet",
- "id" : 469
- },
- {
- "name" : "minecraft:crossbow",
- "id" : 471
- },
- {
- "name" : "minecraft:glowingobsidian",
- "id" : 246
- },
- {
- "name" : "minecraft:leaves2",
- "id" : 161
- },
- {
- "name" : "minecraft:spruce_sign",
- "id" : 472
- },
- {
- "name" : "minecraft:element_38",
- "id" : -49
- },
- {
- "name" : "minecraft:coral_fan_hang2",
- "id" : -136
- },
- {
- "name" : "minecraft:birch_sign",
- "id" : 473
- },
- {
- "name" : "minecraft:coral_fan_dead",
- "id" : -134
- },
- {
- "name" : "minecraft:balloon",
- "id" : 448
- },
- {
- "name" : "minecraft:jungle_sign",
- "id" : 474
- },
- {
- "name" : "minecraft:darkoak_sign",
- "id" : 476
- },
- {
- "name" : "minecraft:element_24",
- "id" : -35
- },
- {
- "name" : "minecraft:banner_pattern",
- "id" : 434
- },
- {
- "name" : "minecraft:honeycomb",
- "id" : 736
- },
- {
- "name" : "minecraft:element_78",
- "id" : -89
- },
- {
- "name" : "minecraft:red_nether_brick",
- "id" : 215
- },
- {
- "name" : "minecraft:honey_bottle",
- "id" : 737
- },
- {
- "name" : "minecraft:compound",
- "id" : 499
- },
- {
- "name" : "minecraft:ice_bomb",
- "id" : 453
- },
- {
- "name" : "minecraft:brick_block",
- "id" : 45
- },
- {
- "name" : "minecraft:bleach",
- "id" : 451
- },
- {
- "name" : "minecraft:colored_torch_rg",
- "id" : 202
- },
- {
- "name" : "minecraft:medicine",
- "id" : 447
- },
- {
- "name" : "minecraft:warped_fungus",
- "id" : -229
- },
- {
- "name" : "minecraft:end_portal_frame",
- "id" : 120
- },
- {
- "name" : "minecraft:element_92",
- "id" : -103
- },
- {
- "name" : "minecraft:glow_stick",
- "id" : 166
- },
- {
- "name" : "minecraft:lodestonecompass",
- "id" : 741
- },
- {
- "name" : "minecraft:element_17",
- "id" : -28
- },
- {
- "name" : "minecraft:lit_pumpkin",
- "id" : 91
- },
- {
- "name" : "minecraft:netherite_ingot",
- "id" : 742
- },
- {
- "name" : "minecraft:chain_command_block",
- "id" : 189
- },
- {
- "name" : "minecraft:loom",
- "id" : -204
- },
- {
- "name" : "minecraft:item.warped_door",
- "id" : -245
- },
- {
- "name" : "minecraft:netherite_axe",
- "id" : 746
- },
- {
- "name" : "minecraft:netherite_hoe",
- "id" : 747
- },
- {
- "name" : "minecraft:dark_oak_fence_gate",
- "id" : 186
- },
- {
- "name" : "minecraft:element_115",
- "id" : -126
- },
- {
- "name" : "minecraft:netherite_helmet",
- "id" : 748
- },
- {
- "name" : "minecraft:element_117",
- "id" : -128
- },
- {
- "name" : "minecraft:netherite_scrap",
- "id" : 752
- },
- {
- "name" : "minecraft:crimson_sign",
- "id" : 753
- },
- {
- "name" : "minecraft:concrete",
- "id" : 236
- },
- {
- "name" : "minecraft:chiseled_nether_bricks",
- "id" : -302
- },
- {
- "name" : "minecraft:mob_spawner",
- "id" : 52
- },
- {
- "name" : "minecraft:warped_sign",
- "id" : 754
- },
- {
- "name" : "minecraft:chain",
- "id" : 758
- },
- {
- "name" : "minecraft:warped_fungus_on_a_stick",
- "id" : 757
- },
- {
- "name" : "minecraft:nether_sprouts",
- "id" : 760
- },
- {
- "name" : "minecraft:cartography_table",
- "id" : -200
- },
- {
- "name" : "minecraft:polished_blackstone_slab",
- "id" : -293
- },
- {
- "name" : "minecraft:soul_campfire",
- "id" : 801
- },
- {
- "name" : "minecraft:stone",
- "id" : 1
- },
- {
- "name" : "minecraft:wool",
- "id" : 35
- },
- {
- "name" : "minecraft:yellow_flower",
- "id" : 37
- },
- {
- "name" : "minecraft:stained_hardened_clay",
- "id" : 159
- },
- {
- "name" : "minecraft:log",
- "id" : 17
- },
- {
- "name" : "minecraft:fence",
- "id" : 85
- },
- {
- "name" : "minecraft:element_53",
- "id" : -64
- },
- {
- "name" : "minecraft:stonebrick",
- "id" : 98
- },
- {
- "name" : "minecraft:lit_blast_furnace",
- "id" : -214
- },
- {
- "name" : "minecraft:coral_block",
- "id" : -132
- },
- {
- "name" : "minecraft:polished_blackstone_bricks",
- "id" : -274
- },
- {
- "name" : "minecraft:double_stone_slab",
- "id" : 44
- },
- {
- "name" : "minecraft:element_100",
- "id" : -111
- },
- {
- "name" : "minecraft:double_stone_slab2",
- "id" : 182
- },
- {
- "name" : "minecraft:fence_gate",
- "id" : 107
- },
- {
- "name" : "minecraft:double_stone_slab3",
- "id" : -162
- },
- {
- "name" : "minecraft:rail",
- "id" : 66
- },
- {
- "name" : "minecraft:double_stone_slab4",
- "id" : -166
- },
- {
- "name" : "minecraft:stripped_acacia_log",
- "id" : -8
- },
- {
- "name" : "minecraft:real_double_stone_slab",
- "id" : 43
- },
- {
- "name" : "minecraft:coral_fan",
- "id" : -133
- },
- {
- "name" : "minecraft:sea_pickle",
- "id" : -156
- },
- {
- "name" : "minecraft:polished_blackstone_button",
- "id" : -296
- },
- {
- "name" : "minecraft:element_90",
- "id" : -101
- },
- {
- "name" : "minecraft:polished_blackstone_double_slab",
- "id" : -294
- },
- {
- "name" : "minecraft:sapling",
- "id" : 6
- },
- {
- "name" : "minecraft:leaves",
- "id" : 18
- },
- {
- "name" : "minecraft:sandstone",
- "id" : 24
- },
- {
- "name" : "minecraft:silver_glazed_terracotta",
- "id" : 228
- },
- {
- "name" : "minecraft:wooden_slab",
- "id" : 158
- },
- {
- "name" : "minecraft:warped_roots",
- "id" : -224
- },
- {
- "name" : "minecraft:element_11",
- "id" : -22
- },
- {
- "name" : "minecraft:red_flower",
- "id" : 38
- },
- {
- "name" : "minecraft:element_59",
- "id" : -70
- },
- {
- "name" : "minecraft:double_plant",
- "id" : 175
- },
- {
- "name" : "minecraft:waterlily",
- "id" : 111
- },
- {
- "name" : "minecraft:quartz_block",
- "id" : 155
- },
- {
- "name" : "minecraft:element_95",
- "id" : -106
- },
- {
- "name" : "minecraft:soul_soil",
- "id" : -236
+ "name" : "minecraft:acacia_fence_gate",
+ "id" : 187
},
{
"name" : "minecraft:acacia_pressure_plate",
"id" : -150
},
{
- "name" : "minecraft:tallgrass",
- "id" : 31
+ "name" : "minecraft:acacia_sign",
+ "id" : 569
},
{
- "name" : "minecraft:brown_mushroom_block",
- "id" : 99
+ "name" : "minecraft:acacia_stairs",
+ "id" : 163
},
{
- "name" : "minecraft:element_103",
- "id" : -114
+ "name" : "minecraft:acacia_standing_sign",
+ "id" : -190
},
{
- "name" : "minecraft:crimson_fungus",
- "id" : -228
+ "name" : "minecraft:acacia_trapdoor",
+ "id" : -145
},
{
- "name" : "minecraft:item.frame",
- "id" : 199
+ "name" : "minecraft:acacia_wall_sign",
+ "id" : -191
},
{
- "name" : "minecraft:red_mushroom_block",
- "id" : 100
+ "name" : "minecraft:activator_rail",
+ "id" : 126
},
{
- "name" : "minecraft:log2",
- "id" : 162
+ "name" : "minecraft:agent_spawn_egg",
+ "id" : 485
},
{
- "name" : "minecraft:conduit",
- "id" : -157
+ "name" : "minecraft:air",
+ "id" : -158
},
{
- "name" : "minecraft:prismarine",
- "id" : 168
+ "name" : "minecraft:allow",
+ "id" : 210
},
{
- "name" : "minecraft:magma",
- "id" : 213
+ "name" : "minecraft:ancient_debris",
+ "id" : -271
},
{
- "name" : "minecraft:element_22",
- "id" : -33
+ "name" : "minecraft:andesite_stairs",
+ "id" : -171
},
{
- "name" : "minecraft:undyed_shulker_box",
- "id" : 205
+ "name" : "minecraft:anvil",
+ "id" : 145
},
{
- "name" : "minecraft:shulker_box",
- "id" : 218
+ "name" : "minecraft:apple",
+ "id" : 257
},
{
- "name" : "minecraft:spruce_standing_sign",
- "id" : -181
+ "name" : "minecraft:armor_stand",
+ "id" : 542
},
{
- "name" : "minecraft:sticky_piston",
- "id" : 29
+ "name" : "minecraft:arrow",
+ "id" : 301
},
{
- "name" : "minecraft:element_10",
- "id" : -21
+ "name" : "minecraft:baked_potato",
+ "id" : 281
},
{
- "name" : "minecraft:turtle_egg",
- "id" : -159
+ "name" : "minecraft:balloon",
+ "id" : 587
},
{
"name" : "minecraft:bamboo",
"id" : -163
},
{
- "name" : "minecraft:observer",
- "id" : 251
+ "name" : "minecraft:bamboo_sapling",
+ "id" : -164
},
{
- "name" : "minecraft:scaffolding",
- "id" : -165
+ "name" : "minecraft:banner",
+ "id" : 557
},
{
- "name" : "minecraft:blast_furnace",
- "id" : -196
+ "name" : "minecraft:banner_pattern",
+ "id" : 613
},
{
- "name" : "minecraft:grindstone",
- "id" : -195
+ "name" : "minecraft:barrel",
+ "id" : -203
+ },
+ {
+ "name" : "minecraft:barrier",
+ "id" : -161
+ },
+ {
+ "name" : "minecraft:basalt",
+ "id" : -234
+ },
+ {
+ "name" : "minecraft:bat_spawn_egg",
+ "id" : 451
+ },
+ {
+ "name" : "minecraft:beacon",
+ "id" : 138
+ },
+ {
+ "name" : "minecraft:bed",
+ "id" : 416
+ },
+ {
+ "name" : "minecraft:bedrock",
+ "id" : 7
+ },
+ {
+ "name" : "minecraft:bee_nest",
+ "id" : -218
+ },
+ {
+ "name" : "minecraft:bee_spawn_egg",
+ "id" : 492
+ },
+ {
+ "name" : "minecraft:beef",
+ "id" : 273
+ },
+ {
+ "name" : "minecraft:beehive",
+ "id" : -219
+ },
+ {
+ "name" : "minecraft:beetroot",
+ "id" : 285
+ },
+ {
+ "name" : "minecraft:beetroot_seeds",
+ "id" : 295
+ },
+ {
+ "name" : "minecraft:beetroot_soup",
+ "id" : 286
},
{
"name" : "minecraft:bell",
"id" : -206
},
{
- "name" : "minecraft:end_rod",
- "id" : 208
+ "name" : "minecraft:birch_boat",
+ "id" : 374
},
{
- "name" : "minecraft:fletching_table",
- "id" : -201
+ "name" : "minecraft:birch_button",
+ "id" : -141
},
{
- "name" : "minecraft:item.hopper",
- "id" : 154
+ "name" : "minecraft:birch_door",
+ "id" : 544
},
{
- "name" : "minecraft:wood",
- "id" : -212
+ "name" : "minecraft:birch_fence_gate",
+ "id" : 184
},
{
- "name" : "minecraft:chemistry_table",
- "id" : 238
+ "name" : "minecraft:birch_pressure_plate",
+ "id" : -151
},
{
- "name" : "minecraft:tnt",
- "id" : 46
+ "name" : "minecraft:birch_sign",
+ "id" : 567
},
{
- "name" : "minecraft:hard_stained_glass_pane",
- "id" : 191
+ "name" : "minecraft:birch_stairs",
+ "id" : 135
},
{
- "name" : "minecraft:crimson_slab",
- "id" : -264
+ "name" : "minecraft:birch_standing_sign",
+ "id" : -186
},
{
- "name" : "minecraft:element_87",
- "id" : -98
+ "name" : "minecraft:birch_trapdoor",
+ "id" : -146
},
{
- "name" : "minecraft:warped_slab",
- "id" : -265
+ "name" : "minecraft:birch_wall_sign",
+ "id" : -187
},
{
- "name" : "minecraft:element_0",
- "id" : 36
- },
- {
- "name" : "minecraft:element_4",
- "id" : -15
- },
- {
- "name" : "minecraft:ender_chest",
- "id" : 130
- },
- {
- "name" : "minecraft:element_5",
- "id" : -16
- },
- {
- "name" : "minecraft:element_6",
- "id" : -17
- },
- {
- "name" : "minecraft:element_8",
- "id" : -19
- },
- {
- "name" : "minecraft:element_9",
- "id" : -20
- },
- {
- "name" : "minecraft:element_12",
- "id" : -23
- },
- {
- "name" : "minecraft:element_14",
- "id" : -25
- },
- {
- "name" : "minecraft:element_15",
- "id" : -26
- },
- {
- "name" : "minecraft:element_18",
- "id" : -29
- },
- {
- "name" : "minecraft:element_19",
- "id" : -30
- },
- {
- "name" : "minecraft:element_20",
- "id" : -31
- },
- {
- "name" : "minecraft:element_21",
- "id" : -32
- },
- {
- "name" : "minecraft:element_26",
- "id" : -37
- },
- {
- "name" : "minecraft:element_28",
- "id" : -39
- },
- {
- "name" : "minecraft:element_29",
- "id" : -40
- },
- {
- "name" : "minecraft:element_33",
- "id" : -44
- },
- {
- "name" : "minecraft:element_34",
- "id" : -45
- },
- {
- "name" : "minecraft:element_36",
- "id" : -47
- },
- {
- "name" : "minecraft:ice",
- "id" : 79
- },
- {
- "name" : "minecraft:element_37",
- "id" : -48
- },
- {
- "name" : "minecraft:element_39",
- "id" : -50
- },
- {
- "name" : "minecraft:element_40",
- "id" : -51
- },
- {
- "name" : "minecraft:element_41",
- "id" : -52
- },
- {
- "name" : "minecraft:element_45",
- "id" : -56
- },
- {
- "name" : "minecraft:element_46",
- "id" : -57
- },
- {
- "name" : "minecraft:netherite_block",
- "id" : -270
- },
- {
- "name" : "minecraft:element_47",
- "id" : -58
- },
- {
- "name" : "minecraft:element_54",
- "id" : -65
- },
- {
- "name" : "minecraft:element_56",
- "id" : -67
+ "name" : "minecraft:black_dye",
+ "id" : 393
},
{
"name" : "minecraft:black_glazed_terracotta",
"id" : 235
},
{
- "name" : "minecraft:lit_redstone_ore",
- "id" : 74
+ "name" : "minecraft:blackstone",
+ "id" : -273
},
{
- "name" : "minecraft:crafting_table",
- "id" : 58
+ "name" : "minecraft:blackstone_double_slab",
+ "id" : -283
},
{
- "name" : "minecraft:element_57",
- "id" : -68
+ "name" : "minecraft:blackstone_slab",
+ "id" : -282
},
{
- "name" : "minecraft:element_58",
- "id" : -69
+ "name" : "minecraft:blackstone_stairs",
+ "id" : -276
},
{
- "name" : "minecraft:element_60",
- "id" : -71
+ "name" : "minecraft:blackstone_wall",
+ "id" : -277
},
{
- "name" : "minecraft:element_64",
- "id" : -75
+ "name" : "minecraft:blast_furnace",
+ "id" : -196
},
{
- "name" : "minecraft:element_65",
- "id" : -76
+ "name" : "minecraft:blaze_powder",
+ "id" : 427
},
{
- "name" : "minecraft:element_67",
- "id" : -78
+ "name" : "minecraft:blaze_rod",
+ "id" : 421
},
{
- "name" : "minecraft:element_70",
- "id" : -81
+ "name" : "minecraft:blaze_spawn_egg",
+ "id" : 454
},
{
- "name" : "minecraft:element_72",
- "id" : -83
+ "name" : "minecraft:bleach",
+ "id" : 585
},
{
- "name" : "minecraft:element_76",
- "id" : -87
+ "name" : "minecraft:blue_dye",
+ "id" : 397
},
{
- "name" : "minecraft:dark_oak_button",
- "id" : -142
- },
- {
- "name" : "minecraft:element_77",
- "id" : -88
- },
- {
- "name" : "minecraft:diorite_stairs",
- "id" : -170
- },
- {
- "name" : "minecraft:redstone_torch",
- "id" : 76
- },
- {
- "name" : "minecraft:element_79",
- "id" : -90
- },
- {
- "name" : "minecraft:iron_bars",
- "id" : 101
- },
- {
- "name" : "minecraft:element_80",
- "id" : -91
- },
- {
- "name" : "minecraft:element_81",
- "id" : -92
- },
- {
- "name" : "minecraft:element_82",
- "id" : -93
- },
- {
- "name" : "minecraft:underwater_torch",
- "id" : 239
+ "name" : "minecraft:blue_glazed_terracotta",
+ "id" : 231
},
{
"name" : "minecraft:blue_ice",
"id" : -11
},
{
- "name" : "minecraft:element_83",
- "id" : -94
+ "name" : "minecraft:boat",
+ "id" : 611
},
{
- "name" : "minecraft:element_89",
- "id" : -100
+ "name" : "minecraft:bone",
+ "id" : 413
},
{
- "name" : "minecraft:element_91",
- "id" : -102
+ "name" : "minecraft:bone_block",
+ "id" : 216
},
{
- "name" : "minecraft:element_96",
- "id" : -107
+ "name" : "minecraft:bone_meal",
+ "id" : 409
},
{
- "name" : "minecraft:element_97",
- "id" : -108
+ "name" : "minecraft:book",
+ "id" : 385
+ },
+ {
+ "name" : "minecraft:bookshelf",
+ "id" : 47
+ },
+ {
+ "name" : "minecraft:border_block",
+ "id" : 212
+ },
+ {
+ "name" : "minecraft:bordure_indented_banner_pattern",
+ "id" : 576
+ },
+ {
+ "name" : "minecraft:bow",
+ "id" : 300
+ },
+ {
+ "name" : "minecraft:bowl",
+ "id" : 321
+ },
+ {
+ "name" : "minecraft:bread",
+ "id" : 261
+ },
+ {
+ "name" : "minecraft:brewing_stand",
+ "id" : 429
+ },
+ {
+ "name" : "minecraft:brewingstandblock",
+ "id" : 117
+ },
+ {
+ "name" : "minecraft:brick",
+ "id" : 381
+ },
+ {
+ "name" : "minecraft:brick_block",
+ "id" : 45
+ },
+ {
+ "name" : "minecraft:brick_stairs",
+ "id" : 108
+ },
+ {
+ "name" : "minecraft:brown_dye",
+ "id" : 396
+ },
+ {
+ "name" : "minecraft:brown_glazed_terracotta",
+ "id" : 232
+ },
+ {
+ "name" : "minecraft:brown_mushroom",
+ "id" : 39
+ },
+ {
+ "name" : "minecraft:brown_mushroom_block",
+ "id" : 99
+ },
+ {
+ "name" : "minecraft:bubble_column",
+ "id" : -160
+ },
+ {
+ "name" : "minecraft:bucket",
+ "id" : 360
},
{
"name" : "minecraft:cactus",
"id" : 81
},
{
- "name" : "minecraft:element_99",
- "id" : -110
+ "name" : "minecraft:cake",
+ "id" : 415
+ },
+ {
+ "name" : "minecraft:camera",
+ "id" : 582
+ },
+ {
+ "name" : "minecraft:campfire",
+ "id" : 578
+ },
+ {
+ "name" : "minecraft:carpet",
+ "id" : 171
+ },
+ {
+ "name" : "minecraft:carrot",
+ "id" : 279
+ },
+ {
+ "name" : "minecraft:carrot_on_a_stick",
+ "id" : 507
+ },
+ {
+ "name" : "minecraft:carrots",
+ "id" : 141
+ },
+ {
+ "name" : "minecraft:cartography_table",
+ "id" : -200
+ },
+ {
+ "name" : "minecraft:carved_pumpkin",
+ "id" : -155
+ },
+ {
+ "name" : "minecraft:cat_spawn_egg",
+ "id" : 486
+ },
+ {
+ "name" : "minecraft:cauldron",
+ "id" : 430
+ },
+ {
+ "name" : "minecraft:cave_spider_spawn_egg",
+ "id" : 455
+ },
+ {
+ "name" : "minecraft:chain",
+ "id" : 607
+ },
+ {
+ "name" : "minecraft:chain_command_block",
+ "id" : 189
+ },
+ {
+ "name" : "minecraft:chainmail_boots",
+ "id" : 342
+ },
+ {
+ "name" : "minecraft:chainmail_chestplate",
+ "id" : 340
+ },
+ {
+ "name" : "minecraft:chainmail_helmet",
+ "id" : 339
+ },
+ {
+ "name" : "minecraft:chainmail_leggings",
+ "id" : 341
+ },
+ {
+ "name" : "minecraft:charcoal",
+ "id" : 303
+ },
+ {
+ "name" : "minecraft:chemical_heat",
+ "id" : 192
+ },
+ {
+ "name" : "minecraft:chemistry_table",
+ "id" : 238
+ },
+ {
+ "name" : "minecraft:chest",
+ "id" : 54
+ },
+ {
+ "name" : "minecraft:chest_minecart",
+ "id" : 387
+ },
+ {
+ "name" : "minecraft:chicken",
+ "id" : 275
+ },
+ {
+ "name" : "minecraft:chicken_spawn_egg",
+ "id" : 433
+ },
+ {
+ "name" : "minecraft:chiseled_nether_bricks",
+ "id" : -302
+ },
+ {
+ "name" : "minecraft:chiseled_polished_blackstone",
+ "id" : -279
+ },
+ {
+ "name" : "minecraft:chorus_flower",
+ "id" : 200
+ },
+ {
+ "name" : "minecraft:chorus_fruit",
+ "id" : 548
+ },
+ {
+ "name" : "minecraft:chorus_plant",
+ "id" : 240
+ },
+ {
+ "name" : "minecraft:clay",
+ "id" : 82
+ },
+ {
+ "name" : "minecraft:clay_ball",
+ "id" : 382
+ },
+ {
+ "name" : "minecraft:clock",
+ "id" : 391
+ },
+ {
+ "name" : "minecraft:coal",
+ "id" : 302
+ },
+ {
+ "name" : "minecraft:coal_block",
+ "id" : 173
+ },
+ {
+ "name" : "minecraft:coal_ore",
+ "id" : 16
+ },
+ {
+ "name" : "minecraft:cobblestone",
+ "id" : 4
+ },
+ {
+ "name" : "minecraft:cobblestone_wall",
+ "id" : 139
+ },
+ {
+ "name" : "minecraft:cocoa",
+ "id" : 127
+ },
+ {
+ "name" : "minecraft:cocoa_beans",
+ "id" : 410
+ },
+ {
+ "name" : "minecraft:cod",
+ "id" : 264
+ },
+ {
+ "name" : "minecraft:cod_bucket",
+ "id" : 364
+ },
+ {
+ "name" : "minecraft:cod_spawn_egg",
+ "id" : 478
+ },
+ {
+ "name" : "minecraft:colored_torch_bp",
+ "id" : 204
+ },
+ {
+ "name" : "minecraft:colored_torch_rg",
+ "id" : 202
+ },
+ {
+ "name" : "minecraft:command_block",
+ "id" : 137
+ },
+ {
+ "name" : "minecraft:command_block_minecart",
+ "id" : 553
+ },
+ {
+ "name" : "minecraft:comparator",
+ "id" : 512
+ },
+ {
+ "name" : "minecraft:compass",
+ "id" : 389
+ },
+ {
+ "name" : "minecraft:composter",
+ "id" : -213
+ },
+ {
+ "name" : "minecraft:compound",
+ "id" : 583
+ },
+ {
+ "name" : "minecraft:concrete",
+ "id" : 236
+ },
+ {
+ "name" : "minecraft:concrete_powder",
+ "id" : 237
+ },
+ {
+ "name" : "minecraft:conduit",
+ "id" : -157
+ },
+ {
+ "name" : "minecraft:cooked_beef",
+ "id" : 274
+ },
+ {
+ "name" : "minecraft:cooked_chicken",
+ "id" : 276
+ },
+ {
+ "name" : "minecraft:cooked_cod",
+ "id" : 268
+ },
+ {
+ "name" : "minecraft:cooked_mutton",
+ "id" : 541
+ },
+ {
+ "name" : "minecraft:cooked_porkchop",
+ "id" : 263
+ },
+ {
+ "name" : "minecraft:cooked_rabbit",
+ "id" : 289
+ },
+ {
+ "name" : "minecraft:cooked_salmon",
+ "id" : 269
+ },
+ {
+ "name" : "minecraft:cookie",
+ "id" : 271
+ },
+ {
+ "name" : "minecraft:coral",
+ "id" : -131
+ },
+ {
+ "name" : "minecraft:coral_block",
+ "id" : -132
+ },
+ {
+ "name" : "minecraft:coral_fan",
+ "id" : -133
+ },
+ {
+ "name" : "minecraft:coral_fan_dead",
+ "id" : -134
+ },
+ {
+ "name" : "minecraft:coral_fan_hang",
+ "id" : -135
+ },
+ {
+ "name" : "minecraft:coral_fan_hang2",
+ "id" : -136
+ },
+ {
+ "name" : "minecraft:coral_fan_hang3",
+ "id" : -137
+ },
+ {
+ "name" : "minecraft:cow_spawn_egg",
+ "id" : 434
+ },
+ {
+ "name" : "minecraft:cracked_nether_bricks",
+ "id" : -303
+ },
+ {
+ "name" : "minecraft:cracked_polished_blackstone_bricks",
+ "id" : -280
+ },
+ {
+ "name" : "minecraft:crafting_table",
+ "id" : 58
+ },
+ {
+ "name" : "minecraft:creeper_banner_pattern",
+ "id" : 572
+ },
+ {
+ "name" : "minecraft:creeper_spawn_egg",
+ "id" : 439
+ },
+ {
+ "name" : "minecraft:crimson_button",
+ "id" : -260
+ },
+ {
+ "name" : "minecraft:crimson_door",
+ "id" : 604
+ },
+ {
+ "name" : "minecraft:crimson_double_slab",
+ "id" : -266
+ },
+ {
+ "name" : "minecraft:crimson_fence",
+ "id" : -256
+ },
+ {
+ "name" : "minecraft:crimson_fence_gate",
+ "id" : -258
+ },
+ {
+ "name" : "minecraft:crimson_fungus",
+ "id" : -228
+ },
+ {
+ "name" : "minecraft:crimson_hyphae",
+ "id" : -299
+ },
+ {
+ "name" : "minecraft:crimson_nylium",
+ "id" : -232
+ },
+ {
+ "name" : "minecraft:crimson_planks",
+ "id" : -242
+ },
+ {
+ "name" : "minecraft:crimson_pressure_plate",
+ "id" : -262
+ },
+ {
+ "name" : "minecraft:crimson_roots",
+ "id" : -223
+ },
+ {
+ "name" : "minecraft:crimson_sign",
+ "id" : 602
+ },
+ {
+ "name" : "minecraft:crimson_slab",
+ "id" : -264
+ },
+ {
+ "name" : "minecraft:crimson_stairs",
+ "id" : -254
+ },
+ {
+ "name" : "minecraft:crimson_standing_sign",
+ "id" : -250
+ },
+ {
+ "name" : "minecraft:crimson_stem",
+ "id" : -225
+ },
+ {
+ "name" : "minecraft:crimson_trapdoor",
+ "id" : -246
+ },
+ {
+ "name" : "minecraft:crimson_wall_sign",
+ "id" : -252
+ },
+ {
+ "name" : "minecraft:crossbow",
+ "id" : 565
+ },
+ {
+ "name" : "minecraft:crying_obsidian",
+ "id" : -289
+ },
+ {
+ "name" : "minecraft:cyan_dye",
+ "id" : 399
+ },
+ {
+ "name" : "minecraft:cyan_glazed_terracotta",
+ "id" : 229
+ },
+ {
+ "name" : "minecraft:dark_oak_boat",
+ "id" : 378
+ },
+ {
+ "name" : "minecraft:dark_oak_button",
+ "id" : -142
+ },
+ {
+ "name" : "minecraft:dark_oak_door",
+ "id" : 547
+ },
+ {
+ "name" : "minecraft:dark_oak_fence_gate",
+ "id" : 186
+ },
+ {
+ "name" : "minecraft:dark_oak_pressure_plate",
+ "id" : -152
+ },
+ {
+ "name" : "minecraft:dark_oak_sign",
+ "id" : 570
+ },
+ {
+ "name" : "minecraft:dark_oak_stairs",
+ "id" : 164
+ },
+ {
+ "name" : "minecraft:dark_oak_trapdoor",
+ "id" : -147
+ },
+ {
+ "name" : "minecraft:dark_prismarine_stairs",
+ "id" : -3
+ },
+ {
+ "name" : "minecraft:darkoak_standing_sign",
+ "id" : -192
+ },
+ {
+ "name" : "minecraft:darkoak_wall_sign",
+ "id" : -193
+ },
+ {
+ "name" : "minecraft:daylight_detector",
+ "id" : 151
+ },
+ {
+ "name" : "minecraft:daylight_detector_inverted",
+ "id" : 178
+ },
+ {
+ "name" : "minecraft:deadbush",
+ "id" : 32
+ },
+ {
+ "name" : "minecraft:deny",
+ "id" : 211
+ },
+ {
+ "name" : "minecraft:detector_rail",
+ "id" : 28
+ },
+ {
+ "name" : "minecraft:diamond",
+ "id" : 304
+ },
+ {
+ "name" : "minecraft:diamond_axe",
+ "id" : 319
+ },
+ {
+ "name" : "minecraft:diamond_block",
+ "id" : 57
+ },
+ {
+ "name" : "minecraft:diamond_boots",
+ "id" : 350
+ },
+ {
+ "name" : "minecraft:diamond_chestplate",
+ "id" : 348
+ },
+ {
+ "name" : "minecraft:diamond_helmet",
+ "id" : 347
+ },
+ {
+ "name" : "minecraft:diamond_hoe",
+ "id" : 332
+ },
+ {
+ "name" : "minecraft:diamond_horse_armor",
+ "id" : 523
+ },
+ {
+ "name" : "minecraft:diamond_leggings",
+ "id" : 349
+ },
+ {
+ "name" : "minecraft:diamond_ore",
+ "id" : 56
+ },
+ {
+ "name" : "minecraft:diamond_pickaxe",
+ "id" : 318
+ },
+ {
+ "name" : "minecraft:diamond_shovel",
+ "id" : 317
+ },
+ {
+ "name" : "minecraft:diamond_sword",
+ "id" : 316
+ },
+ {
+ "name" : "minecraft:diorite_stairs",
+ "id" : -170
+ },
+ {
+ "name" : "minecraft:dirt",
+ "id" : 3
+ },
+ {
+ "name" : "minecraft:dispenser",
+ "id" : 23
+ },
+ {
+ "name" : "minecraft:dolphin_spawn_egg",
+ "id" : 482
+ },
+ {
+ "name" : "minecraft:donkey_spawn_egg",
+ "id" : 463
+ },
+ {
+ "name" : "minecraft:double_plant",
+ "id" : 175
+ },
+ {
+ "name" : "minecraft:double_stone_slab",
+ "id" : 44
+ },
+ {
+ "name" : "minecraft:double_stone_slab2",
+ "id" : 182
+ },
+ {
+ "name" : "minecraft:double_stone_slab3",
+ "id" : -162
+ },
+ {
+ "name" : "minecraft:double_stone_slab4",
+ "id" : -166
+ },
+ {
+ "name" : "minecraft:double_wooden_slab",
+ "id" : 157
+ },
+ {
+ "name" : "minecraft:dragon_breath",
+ "id" : 550
+ },
+ {
+ "name" : "minecraft:dragon_egg",
+ "id" : 122
+ },
+ {
+ "name" : "minecraft:dried_kelp",
+ "id" : 270
+ },
+ {
+ "name" : "minecraft:dried_kelp_block",
+ "id" : -139
+ },
+ {
+ "name" : "minecraft:dropper",
+ "id" : 125
+ },
+ {
+ "name" : "minecraft:drowned_spawn_egg",
+ "id" : 481
+ },
+ {
+ "name" : "minecraft:dye",
+ "id" : 612
+ },
+ {
+ "name" : "minecraft:egg",
+ "id" : 388
+ },
+ {
+ "name" : "minecraft:elder_guardian_spawn_egg",
+ "id" : 469
+ },
+ {
+ "name" : "minecraft:element_0",
+ "id" : 36
+ },
+ {
+ "name" : "minecraft:element_1",
+ "id" : -12
+ },
+ {
+ "name" : "minecraft:element_10",
+ "id" : -21
+ },
+ {
+ "name" : "minecraft:element_100",
+ "id" : -111
+ },
+ {
+ "name" : "minecraft:element_101",
+ "id" : -112
+ },
+ {
+ "name" : "minecraft:element_102",
+ "id" : -113
+ },
+ {
+ "name" : "minecraft:element_103",
+ "id" : -114
+ },
+ {
+ "name" : "minecraft:element_104",
+ "id" : -115
},
{
"name" : "minecraft:element_105",
@@ -2319,10 +979,6 @@
"name" : "minecraft:element_106",
"id" : -117
},
- {
- "name" : "minecraft:cyan_glazed_terracotta",
- "id" : 229
- },
{
"name" : "minecraft:element_107",
"id" : -118
@@ -2336,895 +992,2667 @@
"id" : -120
},
{
- "name" : "minecraft:element_112",
- "id" : -123
+ "name" : "minecraft:element_11",
+ "id" : -22
},
{
- "name" : "minecraft:warped_button",
- "id" : -261
+ "name" : "minecraft:element_110",
+ "id" : -121
+ },
+ {
+ "name" : "minecraft:element_111",
+ "id" : -122
+ },
+ {
+ "name" : "minecraft:element_112",
+ "id" : -123
},
{
"name" : "minecraft:element_113",
"id" : -124
},
- {
- "name" : "minecraft:birch_stairs",
- "id" : 135
- },
{
"name" : "minecraft:element_114",
"id" : -125
},
{
- "name" : "minecraft:composter",
- "id" : -213
+ "name" : "minecraft:element_115",
+ "id" : -126
},
{
- "name" : "minecraft:crying_obsidian",
- "id" : -289
+ "name" : "minecraft:element_116",
+ "id" : -127
},
{
- "name" : "minecraft:end_crystal",
- "id" : 426
+ "name" : "minecraft:element_117",
+ "id" : -128
},
{
- "name" : "minecraft:tripwire_hook",
- "id" : 131
+ "name" : "minecraft:element_118",
+ "id" : -129
},
{
- "name" : "minecraft:blue_glazed_terracotta",
- "id" : 231
+ "name" : "minecraft:element_12",
+ "id" : -23
},
{
- "name" : "minecraft:daylight_detector_inverted",
- "id" : 178
+ "name" : "minecraft:element_13",
+ "id" : -24
},
{
- "name" : "minecraft:warped_trapdoor",
- "id" : -247
+ "name" : "minecraft:element_14",
+ "id" : -25
},
{
- "name" : "minecraft:twisting_vines",
- "id" : -287
+ "name" : "minecraft:element_15",
+ "id" : -26
},
{
- "name" : "minecraft:noteblock",
- "id" : 25
+ "name" : "minecraft:element_16",
+ "id" : -27
},
{
- "name" : "minecraft:gravel",
- "id" : 13
+ "name" : "minecraft:element_17",
+ "id" : -28
},
{
- "name" : "minecraft:golden_rail",
- "id" : 27
+ "name" : "minecraft:element_18",
+ "id" : -29
},
{
- "name" : "minecraft:warped_wall_sign",
- "id" : -253
+ "name" : "minecraft:element_19",
+ "id" : -30
},
{
- "name" : "minecraft:oak_stairs",
- "id" : 53
+ "name" : "minecraft:element_2",
+ "id" : -13
},
{
- "name" : "minecraft:grass",
- "id" : 2
+ "name" : "minecraft:element_20",
+ "id" : -31
},
{
- "name" : "minecraft:acacia_button",
- "id" : -140
+ "name" : "minecraft:element_21",
+ "id" : -32
},
{
- "name" : "minecraft:snow",
- "id" : 80
+ "name" : "minecraft:element_22",
+ "id" : -33
},
{
- "name" : "minecraft:detector_rail",
- "id" : 28
+ "name" : "minecraft:element_23",
+ "id" : -34
},
{
- "name" : "minecraft:dark_oak_trapdoor",
- "id" : -147
+ "name" : "minecraft:element_24",
+ "id" : -35
},
{
- "name" : "minecraft:spruce_pressure_plate",
- "id" : -154
+ "name" : "minecraft:element_25",
+ "id" : -36
},
{
- "name" : "minecraft:water",
- "id" : 9
+ "name" : "minecraft:element_26",
+ "id" : -37
},
{
- "name" : "minecraft:furnace",
- "id" : 61
+ "name" : "minecraft:element_27",
+ "id" : -38
},
{
- "name" : "minecraft:item.wooden_door",
- "id" : 64
+ "name" : "minecraft:element_28",
+ "id" : -39
},
{
- "name" : "minecraft:gold_ore",
- "id" : 14
+ "name" : "minecraft:element_29",
+ "id" : -40
},
{
- "name" : "minecraft:web",
- "id" : 30
+ "name" : "minecraft:element_3",
+ "id" : -14
},
{
- "name" : "minecraft:unlit_redstone_torch",
- "id" : 75
+ "name" : "minecraft:element_30",
+ "id" : -41
},
{
- "name" : "minecraft:ladder",
- "id" : 65
+ "name" : "minecraft:element_31",
+ "id" : -42
},
{
- "name" : "minecraft:sweet_berry_bush",
- "id" : -207
+ "name" : "minecraft:element_32",
+ "id" : -43
},
{
- "name" : "minecraft:standing_sign",
- "id" : 63
+ "name" : "minecraft:element_33",
+ "id" : -44
},
{
- "name" : "minecraft:glass",
- "id" : 20
+ "name" : "minecraft:element_34",
+ "id" : -45
},
{
- "name" : "minecraft:lapis_ore",
- "id" : 21
+ "name" : "minecraft:element_35",
+ "id" : -46
},
{
- "name" : "minecraft:bookshelf",
- "id" : 47
+ "name" : "minecraft:element_36",
+ "id" : -47
},
{
- "name" : "minecraft:item.bed",
- "id" : 26
+ "name" : "minecraft:element_37",
+ "id" : -48
},
{
- "name" : "minecraft:stripped_warped_hyphae",
- "id" : -301
+ "name" : "minecraft:element_38",
+ "id" : -49
},
{
- "name" : "minecraft:wither_rose",
- "id" : -216
+ "name" : "minecraft:element_39",
+ "id" : -50
},
{
- "name" : "minecraft:wooden_pressure_plate",
- "id" : 72
+ "name" : "minecraft:element_4",
+ "id" : -15
},
{
- "name" : "minecraft:powered_comparator",
- "id" : 150
+ "name" : "minecraft:element_40",
+ "id" : -51
},
{
- "name" : "minecraft:lapis_block",
- "id" : 22
+ "name" : "minecraft:element_41",
+ "id" : -52
},
{
- "name" : "minecraft:dispenser",
- "id" : 23
+ "name" : "minecraft:element_42",
+ "id" : -53
},
{
- "name" : "minecraft:item.wheat",
- "id" : 59
+ "name" : "minecraft:element_43",
+ "id" : -54
},
{
- "name" : "minecraft:item.spruce_door",
- "id" : 193
+ "name" : "minecraft:element_44",
+ "id" : -55
},
{
- "name" : "minecraft:diamond_ore",
- "id" : 56
+ "name" : "minecraft:element_45",
+ "id" : -56
},
{
- "name" : "minecraft:deadbush",
- "id" : 32
+ "name" : "minecraft:element_46",
+ "id" : -57
},
{
- "name" : "minecraft:pistonarmcollision",
- "id" : 34
+ "name" : "minecraft:element_47",
+ "id" : -58
},
{
- "name" : "minecraft:blackstone_stairs",
- "id" : -276
+ "name" : "minecraft:element_48",
+ "id" : -59
},
{
- "name" : "minecraft:dried_kelp_block",
- "id" : -139
+ "name" : "minecraft:element_49",
+ "id" : -60
},
{
- "name" : "minecraft:item.soul_campfire",
- "id" : -290
+ "name" : "minecraft:element_5",
+ "id" : -16
},
{
- "name" : "minecraft:green_glazed_terracotta",
- "id" : 233
+ "name" : "minecraft:element_50",
+ "id" : -61
},
{
- "name" : "minecraft:crimson_pressure_plate",
- "id" : -262
+ "name" : "minecraft:element_51",
+ "id" : -62
},
{
- "name" : "minecraft:spruce_fence_gate",
- "id" : 183
+ "name" : "minecraft:element_52",
+ "id" : -63
},
{
- "name" : "minecraft:iron_block",
- "id" : 42
+ "name" : "minecraft:element_53",
+ "id" : -64
},
{
- "name" : "minecraft:lever",
- "id" : 69
+ "name" : "minecraft:element_54",
+ "id" : -65
},
{
- "name" : "minecraft:mossy_cobblestone",
- "id" : 48
+ "name" : "minecraft:element_55",
+ "id" : -66
},
{
- "name" : "minecraft:torch",
- "id" : 50
+ "name" : "minecraft:element_56",
+ "id" : -67
},
{
- "name" : "minecraft:acacia_fence_gate",
- "id" : 187
+ "name" : "minecraft:element_57",
+ "id" : -68
},
{
- "name" : "minecraft:quartz_stairs",
- "id" : 156
+ "name" : "minecraft:element_58",
+ "id" : -69
},
{
- "name" : "minecraft:dragon_egg",
- "id" : 122
+ "name" : "minecraft:element_59",
+ "id" : -70
},
{
- "name" : "minecraft:lava_cauldron",
- "id" : -210
+ "name" : "minecraft:element_6",
+ "id" : -17
},
{
- "name" : "minecraft:jungle_standing_sign",
- "id" : -188
+ "name" : "minecraft:element_60",
+ "id" : -71
},
{
- "name" : "minecraft:redstone_wire",
- "id" : 55
+ "name" : "minecraft:element_61",
+ "id" : -72
},
{
- "name" : "minecraft:jungle_wall_sign",
- "id" : -189
+ "name" : "minecraft:element_62",
+ "id" : -73
},
{
- "name" : "minecraft:lit_furnace",
- "id" : 62
+ "name" : "minecraft:element_63",
+ "id" : -74
},
{
- "name" : "minecraft:beehive",
- "id" : -219
+ "name" : "minecraft:element_64",
+ "id" : -75
},
{
- "name" : "minecraft:crimson_wall_sign",
- "id" : -252
+ "name" : "minecraft:element_65",
+ "id" : -76
},
{
- "name" : "minecraft:stone_stairs",
- "id" : 67
+ "name" : "minecraft:element_66",
+ "id" : -77
},
{
- "name" : "minecraft:orange_glazed_terracotta",
- "id" : 221
+ "name" : "minecraft:element_67",
+ "id" : -78
},
{
- "name" : "minecraft:brick_stairs",
- "id" : 108
+ "name" : "minecraft:element_68",
+ "id" : -79
},
{
- "name" : "minecraft:wall_sign",
- "id" : 68
+ "name" : "minecraft:element_69",
+ "id" : -80
},
{
- "name" : "minecraft:warped_nylium",
- "id" : -233
+ "name" : "minecraft:element_7",
+ "id" : -18
},
{
- "name" : "minecraft:quartz_bricks",
- "id" : -304
+ "name" : "minecraft:element_70",
+ "id" : -81
},
{
- "name" : "minecraft:item.iron_door",
- "id" : 71
+ "name" : "minecraft:element_71",
+ "id" : -82
},
{
- "name" : "minecraft:redstone_ore",
- "id" : 73
+ "name" : "minecraft:element_72",
+ "id" : -83
},
{
- "name" : "minecraft:lectern",
- "id" : -194
+ "name" : "minecraft:element_73",
+ "id" : -84
},
{
- "name" : "minecraft:gilded_blackstone",
- "id" : -281
+ "name" : "minecraft:element_74",
+ "id" : -85
},
{
- "name" : "minecraft:red_nether_brick_stairs",
- "id" : -184
+ "name" : "minecraft:element_75",
+ "id" : -86
},
{
- "name" : "minecraft:basalt",
- "id" : -234
+ "name" : "minecraft:element_76",
+ "id" : -87
},
{
- "name" : "minecraft:stone_button",
- "id" : 77
+ "name" : "minecraft:element_77",
+ "id" : -88
},
{
- "name" : "minecraft:netherrack",
- "id" : 87
+ "name" : "minecraft:element_78",
+ "id" : -89
},
{
- "name" : "minecraft:nether_brick_stairs",
- "id" : 114
+ "name" : "minecraft:element_79",
+ "id" : -90
},
{
- "name" : "minecraft:item.acacia_door",
- "id" : 196
+ "name" : "minecraft:element_8",
+ "id" : -19
},
{
- "name" : "minecraft:item.cake",
- "id" : 92
+ "name" : "minecraft:element_80",
+ "id" : -91
},
{
- "name" : "minecraft:unpowered_repeater",
- "id" : 93
+ "name" : "minecraft:element_81",
+ "id" : -92
},
{
- "name" : "minecraft:powered_repeater",
- "id" : 94
+ "name" : "minecraft:element_82",
+ "id" : -93
},
{
- "name" : "minecraft:trapdoor",
- "id" : 96
+ "name" : "minecraft:element_83",
+ "id" : -94
},
{
- "name" : "minecraft:coral_fan_hang3",
- "id" : -137
+ "name" : "minecraft:element_84",
+ "id" : -95
},
{
- "name" : "minecraft:item.jungle_door",
- "id" : 195
+ "name" : "minecraft:element_85",
+ "id" : -96
},
{
- "name" : "minecraft:glass_pane",
- "id" : 102
+ "name" : "minecraft:element_86",
+ "id" : -97
},
{
- "name" : "minecraft:emerald_ore",
- "id" : 129
+ "name" : "minecraft:element_87",
+ "id" : -98
},
{
- "name" : "minecraft:crimson_planks",
- "id" : -242
+ "name" : "minecraft:element_88",
+ "id" : -99
},
{
- "name" : "minecraft:crimson_stem",
- "id" : -225
+ "name" : "minecraft:element_89",
+ "id" : -100
},
{
- "name" : "minecraft:weeping_vines",
- "id" : -231
+ "name" : "minecraft:element_9",
+ "id" : -20
},
{
- "name" : "minecraft:pumpkin_stem",
- "id" : 104
+ "name" : "minecraft:element_90",
+ "id" : -101
+ },
+ {
+ "name" : "minecraft:element_91",
+ "id" : -102
+ },
+ {
+ "name" : "minecraft:element_92",
+ "id" : -103
+ },
+ {
+ "name" : "minecraft:element_93",
+ "id" : -104
+ },
+ {
+ "name" : "minecraft:element_94",
+ "id" : -105
+ },
+ {
+ "name" : "minecraft:element_95",
+ "id" : -106
+ },
+ {
+ "name" : "minecraft:element_96",
+ "id" : -107
+ },
+ {
+ "name" : "minecraft:element_97",
+ "id" : -108
+ },
+ {
+ "name" : "minecraft:element_98",
+ "id" : -109
+ },
+ {
+ "name" : "minecraft:element_99",
+ "id" : -110
+ },
+ {
+ "name" : "minecraft:elytra",
+ "id" : 554
+ },
+ {
+ "name" : "minecraft:emerald",
+ "id" : 502
},
{
"name" : "minecraft:emerald_block",
"id" : 133
},
{
- "name" : "minecraft:melon_stem",
- "id" : 105
+ "name" : "minecraft:emerald_ore",
+ "id" : 129
},
{
- "name" : "minecraft:chemical_heat",
- "id" : 192
+ "name" : "minecraft:empty_map",
+ "id" : 505
},
{
- "name" : "minecraft:warped_wart_block",
- "id" : -227
+ "name" : "minecraft:enchanted_book",
+ "id" : 511
},
{
- "name" : "minecraft:vine",
- "id" : 106
- },
- {
- "name" : "minecraft:bamboo_sapling",
- "id" : -164
- },
- {
- "name" : "minecraft:standing_banner",
- "id" : 176
- },
- {
- "name" : "minecraft:mycelium",
- "id" : 110
- },
- {
- "name" : "minecraft:nether_gold_ore",
- "id" : -288
- },
- {
- "name" : "minecraft:nether_brick",
- "id" : 112
- },
- {
- "name" : "minecraft:warped_double_slab",
- "id" : -267
- },
- {
- "name" : "minecraft:nether_brick_fence",
- "id" : 113
- },
- {
- "name" : "minecraft:sandstone_stairs",
- "id" : 128
- },
- {
- "name" : "minecraft:item.nether_wart",
- "id" : 115
+ "name" : "minecraft:enchanted_golden_apple",
+ "id" : 259
},
{
"name" : "minecraft:enchanting_table",
"id" : 116
},
+ {
+ "name" : "minecraft:end_brick_stairs",
+ "id" : -178
+ },
+ {
+ "name" : "minecraft:end_bricks",
+ "id" : 206
+ },
+ {
+ "name" : "minecraft:end_crystal",
+ "id" : 615
+ },
+ {
+ "name" : "minecraft:end_gateway",
+ "id" : 209
+ },
+ {
+ "name" : "minecraft:end_portal",
+ "id" : 119
+ },
+ {
+ "name" : "minecraft:end_portal_frame",
+ "id" : 120
+ },
+ {
+ "name" : "minecraft:end_rod",
+ "id" : 208
+ },
{
"name" : "minecraft:end_stone",
"id" : 121
},
{
- "name" : "minecraft:redstone_lamp",
- "id" : 123
+ "name" : "minecraft:ender_chest",
+ "id" : 130
},
{
- "name" : "minecraft:jungle_stairs",
- "id" : 136
+ "name" : "minecraft:ender_eye",
+ "id" : 431
},
{
- "name" : "minecraft:dropper",
- "id" : 125
+ "name" : "minecraft:ender_pearl",
+ "id" : 420
},
{
- "name" : "minecraft:activator_rail",
- "id" : 126
+ "name" : "minecraft:enderman_spawn_egg",
+ "id" : 440
},
{
- "name" : "minecraft:cocoa",
- "id" : 127
+ "name" : "minecraft:endermite_spawn_egg",
+ "id" : 458
},
{
- "name" : "minecraft:soul_torch",
- "id" : -268
+ "name" : "minecraft:evoker_spawn_egg",
+ "id" : 473
},
{
- "name" : "minecraft:info_update",
- "id" : 248
+ "name" : "minecraft:experience_bottle",
+ "id" : 498
},
{
- "name" : "minecraft:packed_ice",
- "id" : 174
+ "name" : "minecraft:farmland",
+ "id" : 60
},
{
- "name" : "minecraft:coral_fan_hang",
- "id" : -135
+ "name" : "minecraft:feather",
+ "id" : 327
},
{
- "name" : "minecraft:item.flower_pot",
- "id" : 140
+ "name" : "minecraft:fence",
+ "id" : 85
},
{
- "name" : "minecraft:potatoes",
- "id" : 142
+ "name" : "minecraft:fence_gate",
+ "id" : 107
},
{
- "name" : "minecraft:wooden_button",
- "id" : 143
+ "name" : "minecraft:fermented_spider_eye",
+ "id" : 426
},
{
- "name" : "minecraft:item.skull",
- "id" : 144
+ "name" : "minecraft:field_masoned_banner_pattern",
+ "id" : 575
},
{
- "name" : "minecraft:heavy_weighted_pressure_plate",
- "id" : 148
- },
- {
- "name" : "minecraft:purple_glazed_terracotta",
- "id" : 219
- },
- {
- "name" : "minecraft:stripped_jungle_log",
- "id" : -7
- },
- {
- "name" : "minecraft:hardened_clay",
- "id" : 172
- },
- {
- "name" : "minecraft:warped_planks",
- "id" : -243
- },
- {
- "name" : "minecraft:acacia_wall_sign",
- "id" : -191
- },
- {
- "name" : "minecraft:purpur_stairs",
- "id" : 203
- },
- {
- "name" : "minecraft:wall_banner",
- "id" : 177
- },
- {
- "name" : "minecraft:spruce_trapdoor",
- "id" : -149
- },
- {
- "name" : "minecraft:repeating_command_block",
- "id" : 188
- },
- {
- "name" : "minecraft:item.chain",
- "id" : -286
- },
- {
- "name" : "minecraft:item.birch_door",
- "id" : 194
- },
- {
- "name" : "minecraft:grass_path",
- "id" : 198
- },
- {
- "name" : "minecraft:blackstone",
- "id" : -273
- },
- {
- "name" : "minecraft:chorus_flower",
- "id" : 200
- },
- {
- "name" : "minecraft:normal_stone_stairs",
- "id" : -180
- },
- {
- "name" : "minecraft:barrier",
- "id" : -161
- },
- {
- "name" : "minecraft:frosted_ice",
- "id" : 207
- },
- {
- "name" : "minecraft:structure_block",
- "id" : 252
- },
- {
- "name" : "minecraft:allow",
- "id" : 210
- },
- {
- "name" : "minecraft:pink_glazed_terracotta",
- "id" : 226
- },
- {
- "name" : "minecraft:deny",
- "id" : 211
- },
- {
- "name" : "minecraft:border_block",
- "id" : 212
- },
- {
- "name" : "minecraft:movingblock",
- "id" : 250
- },
- {
- "name" : "minecraft:bone_block",
- "id" : 216
- },
- {
- "name" : "minecraft:structure_void",
- "id" : 217
- },
- {
- "name" : "minecraft:white_glazed_terracotta",
- "id" : 220
- },
- {
- "name" : "minecraft:magenta_glazed_terracotta",
- "id" : 222
- },
- {
- "name" : "minecraft:lime_glazed_terracotta",
- "id" : 225
- },
- {
- "name" : "minecraft:gray_glazed_terracotta",
- "id" : 227
- },
- {
- "name" : "minecraft:brown_glazed_terracotta",
- "id" : 232
- },
- {
- "name" : "minecraft:red_glazed_terracotta",
- "id" : 234
- },
- {
- "name" : "minecraft:crimson_nylium",
- "id" : -232
- },
- {
- "name" : "minecraft:acacia_trapdoor",
- "id" : -145
- },
- {
- "name" : "minecraft:smooth_sandstone_stairs",
- "id" : -177
- },
- {
- "name" : "minecraft:item.camera",
- "id" : 242
- },
- {
- "name" : "minecraft:podzol",
- "id" : 243
- },
- {
- "name" : "minecraft:stonecutter",
- "id" : 245
- },
- {
- "name" : "minecraft:netherreactor",
- "id" : 247
- },
- {
- "name" : "minecraft:prismarine_stairs",
- "id" : -2
- },
- {
- "name" : "minecraft:dark_prismarine_stairs",
- "id" : -3
- },
- {
- "name" : "minecraft:stripped_spruce_log",
- "id" : -5
- },
- {
- "name" : "minecraft:stripped_birch_log",
- "id" : -6
- },
- {
- "name" : "minecraft:stripped_dark_oak_log",
- "id" : -9
+ "name" : "minecraft:filled_map",
+ "id" : 418
},
{
"name" : "minecraft:fire",
"id" : 51
},
{
- "name" : "minecraft:hard_glass",
- "id" : 253
+ "name" : "minecraft:fire_charge",
+ "id" : 499
},
{
- "name" : "minecraft:acacia_standing_sign",
- "id" : -190
+ "name" : "minecraft:firework_rocket",
+ "id" : 509
+ },
+ {
+ "name" : "minecraft:firework_star",
+ "id" : 510
+ },
+ {
+ "name" : "minecraft:fishing_rod",
+ "id" : 390
+ },
+ {
+ "name" : "minecraft:fletching_table",
+ "id" : -201
+ },
+ {
+ "name" : "minecraft:flint",
+ "id" : 356
+ },
+ {
+ "name" : "minecraft:flint_and_steel",
+ "id" : 299
+ },
+ {
+ "name" : "minecraft:flower_banner_pattern",
+ "id" : 571
+ },
+ {
+ "name" : "minecraft:flower_pot",
+ "id" : 504
+ },
+ {
+ "name" : "minecraft:flowing_lava",
+ "id" : 10
+ },
+ {
+ "name" : "minecraft:flowing_water",
+ "id" : 8
+ },
+ {
+ "name" : "minecraft:fox_spawn_egg",
+ "id" : 488
+ },
+ {
+ "name" : "minecraft:frame",
+ "id" : 503
+ },
+ {
+ "name" : "minecraft:frosted_ice",
+ "id" : 207
+ },
+ {
+ "name" : "minecraft:furnace",
+ "id" : 61
+ },
+ {
+ "name" : "minecraft:ghast_spawn_egg",
+ "id" : 452
+ },
+ {
+ "name" : "minecraft:ghast_tear",
+ "id" : 422
+ },
+ {
+ "name" : "minecraft:gilded_blackstone",
+ "id" : -281
+ },
+ {
+ "name" : "minecraft:glass",
+ "id" : 20
+ },
+ {
+ "name" : "minecraft:glass_bottle",
+ "id" : 425
+ },
+ {
+ "name" : "minecraft:glass_pane",
+ "id" : 102
+ },
+ {
+ "name" : "minecraft:glistering_melon_slice",
+ "id" : 432
+ },
+ {
+ "name" : "minecraft:glow_stick",
+ "id" : 166
+ },
+ {
+ "name" : "minecraft:glowingobsidian",
+ "id" : 246
+ },
+ {
+ "name" : "minecraft:glowstone",
+ "id" : 89
+ },
+ {
+ "name" : "minecraft:glowstone_dust",
+ "id" : 392
+ },
+ {
+ "name" : "minecraft:gold_block",
+ "id" : 41
+ },
+ {
+ "name" : "minecraft:gold_ingot",
+ "id" : 306
+ },
+ {
+ "name" : "minecraft:gold_nugget",
+ "id" : 423
+ },
+ {
+ "name" : "minecraft:gold_ore",
+ "id" : 14
+ },
+ {
+ "name" : "minecraft:golden_apple",
+ "id" : 258
+ },
+ {
+ "name" : "minecraft:golden_axe",
+ "id" : 325
+ },
+ {
+ "name" : "minecraft:golden_boots",
+ "id" : 354
+ },
+ {
+ "name" : "minecraft:golden_carrot",
+ "id" : 283
+ },
+ {
+ "name" : "minecraft:golden_chestplate",
+ "id" : 352
+ },
+ {
+ "name" : "minecraft:golden_helmet",
+ "id" : 351
+ },
+ {
+ "name" : "minecraft:golden_hoe",
+ "id" : 333
+ },
+ {
+ "name" : "minecraft:golden_horse_armor",
+ "id" : 522
+ },
+ {
+ "name" : "minecraft:golden_leggings",
+ "id" : 353
+ },
+ {
+ "name" : "minecraft:golden_pickaxe",
+ "id" : 324
+ },
+ {
+ "name" : "minecraft:golden_rail",
+ "id" : 27
+ },
+ {
+ "name" : "minecraft:golden_shovel",
+ "id" : 323
+ },
+ {
+ "name" : "minecraft:golden_sword",
+ "id" : 322
+ },
+ {
+ "name" : "minecraft:granite_stairs",
+ "id" : -169
+ },
+ {
+ "name" : "minecraft:grass",
+ "id" : 2
+ },
+ {
+ "name" : "minecraft:grass_path",
+ "id" : 198
+ },
+ {
+ "name" : "minecraft:gravel",
+ "id" : 13
+ },
+ {
+ "name" : "minecraft:gray_dye",
+ "id" : 401
+ },
+ {
+ "name" : "minecraft:gray_glazed_terracotta",
+ "id" : 227
+ },
+ {
+ "name" : "minecraft:green_dye",
+ "id" : 395
+ },
+ {
+ "name" : "minecraft:green_glazed_terracotta",
+ "id" : 233
+ },
+ {
+ "name" : "minecraft:grindstone",
+ "id" : -195
+ },
+ {
+ "name" : "minecraft:guardian_spawn_egg",
+ "id" : 459
+ },
+ {
+ "name" : "minecraft:gunpowder",
+ "id" : 328
+ },
+ {
+ "name" : "minecraft:hard_glass",
+ "id" : 253
},
{
"name" : "minecraft:hard_glass_pane",
"id" : 190
},
{
- "name" : "minecraft:mossy_cobblestone_stairs",
- "id" : -179
+ "name" : "minecraft:hard_stained_glass",
+ "id" : 254
},
{
- "name" : "minecraft:crimson_fence_gate",
- "id" : -258
+ "name" : "minecraft:hard_stained_glass_pane",
+ "id" : 191
},
{
- "name" : "minecraft:mossy_stone_brick_stairs",
- "id" : -175
+ "name" : "minecraft:hardened_clay",
+ "id" : 172
},
{
- "name" : "minecraft:item.nether_sprouts",
- "id" : -238
+ "name" : "minecraft:hay_block",
+ "id" : 170
},
{
- "name" : "minecraft:polished_blackstone_brick_double_slab",
- "id" : -285
+ "name" : "minecraft:heart_of_the_sea",
+ "id" : 561
},
{
- "name" : "minecraft:cracked_polished_blackstone_bricks",
- "id" : -280
+ "name" : "minecraft:heavy_weighted_pressure_plate",
+ "id" : 148
},
{
- "name" : "minecraft:smooth_red_sandstone_stairs",
- "id" : -176
+ "name" : "minecraft:hoglin_spawn_egg",
+ "id" : 494
},
{
- "name" : "minecraft:shroomlight",
- "id" : -230
+ "name" : "minecraft:honey_block",
+ "id" : -220
},
{
- "name" : "minecraft:stripped_crimson_hyphae",
- "id" : -300
+ "name" : "minecraft:honey_bottle",
+ "id" : 581
},
{
- "name" : "minecraft:crimson_button",
- "id" : -260
+ "name" : "minecraft:honeycomb",
+ "id" : 580
},
{
- "name" : "minecraft:soul_fire",
- "id" : -237
+ "name" : "minecraft:honeycomb_block",
+ "id" : -221
},
{
- "name" : "minecraft:polished_basalt",
- "id" : -235
+ "name" : "minecraft:hopper",
+ "id" : 517
},
{
- "name" : "minecraft:jungle_button",
- "id" : -143
+ "name" : "minecraft:hopper_minecart",
+ "id" : 516
},
{
- "name" : "minecraft:birch_pressure_plate",
- "id" : -151
+ "name" : "minecraft:horse_spawn_egg",
+ "id" : 456
},
{
- "name" : "minecraft:stripped_warped_stem",
- "id" : -241
+ "name" : "minecraft:husk_spawn_egg",
+ "id" : 461
},
{
- "name" : "minecraft:birch_wall_sign",
- "id" : -187
+ "name" : "minecraft:ice",
+ "id" : 79
},
{
- "name" : "minecraft:jungle_trapdoor",
- "id" : -148
+ "name" : "minecraft:ice_bomb",
+ "id" : 584
},
{
- "name" : "minecraft:item.kelp",
- "id" : -138
+ "name" : "minecraft:info_update",
+ "id" : 248
},
{
- "name" : "minecraft:birch_button",
- "id" : -141
+ "name" : "minecraft:info_update2",
+ "id" : 249
},
{
- "name" : "minecraft:birch_trapdoor",
- "id" : -146
+ "name" : "minecraft:ink_sac",
+ "id" : 411
},
{
- "name" : "minecraft:bubble_column",
- "id" : -160
+ "name" : "minecraft:invisiblebedrock",
+ "id" : 95
},
{
- "name" : "minecraft:polished_granite_stairs",
- "id" : -172
+ "name" : "minecraft:iron_axe",
+ "id" : 298
},
{
- "name" : "minecraft:polished_andesite_stairs",
- "id" : -174
+ "name" : "minecraft:iron_bars",
+ "id" : 101
},
{
- "name" : "minecraft:end_brick_stairs",
- "id" : -178
+ "name" : "minecraft:iron_block",
+ "id" : 42
},
{
- "name" : "minecraft:spruce_wall_sign",
- "id" : -182
+ "name" : "minecraft:iron_boots",
+ "id" : 346
},
{
- "name" : "minecraft:chiseled_polished_blackstone",
- "id" : -279
+ "name" : "minecraft:iron_chestplate",
+ "id" : 344
},
{
- "name" : "minecraft:birch_standing_sign",
- "id" : -186
+ "name" : "minecraft:iron_door",
+ "id" : 370
},
{
- "name" : "minecraft:darkoak_standing_sign",
- "id" : -192
+ "name" : "minecraft:iron_helmet",
+ "id" : 343
},
{
- "name" : "minecraft:darkoak_wall_sign",
- "id" : -193
+ "name" : "minecraft:iron_hoe",
+ "id" : 331
},
{
- "name" : "minecraft:lit_smoker",
- "id" : -199
+ "name" : "minecraft:iron_horse_armor",
+ "id" : 521
+ },
+ {
+ "name" : "minecraft:iron_ingot",
+ "id" : 305
+ },
+ {
+ "name" : "minecraft:iron_leggings",
+ "id" : 345
+ },
+ {
+ "name" : "minecraft:iron_nugget",
+ "id" : 559
+ },
+ {
+ "name" : "minecraft:iron_ore",
+ "id" : 15
+ },
+ {
+ "name" : "minecraft:iron_pickaxe",
+ "id" : 297
+ },
+ {
+ "name" : "minecraft:iron_shovel",
+ "id" : 296
+ },
+ {
+ "name" : "minecraft:iron_sword",
+ "id" : 307
+ },
+ {
+ "name" : "minecraft:iron_trapdoor",
+ "id" : 167
+ },
+ {
+ "name" : "minecraft:item.acacia_door",
+ "id" : 196
+ },
+ {
+ "name" : "minecraft:item.bed",
+ "id" : 26
+ },
+ {
+ "name" : "minecraft:item.beetroot",
+ "id" : 244
+ },
+ {
+ "name" : "minecraft:item.birch_door",
+ "id" : 194
+ },
+ {
+ "name" : "minecraft:item.cake",
+ "id" : 92
+ },
+ {
+ "name" : "minecraft:item.camera",
+ "id" : 242
},
{
"name" : "minecraft:item.campfire",
"id" : -209
},
{
- "name" : "minecraft:bee_nest",
- "id" : -218
+ "name" : "minecraft:item.cauldron",
+ "id" : 118
},
{
- "name" : "minecraft:warped_fence_gate",
- "id" : -259
+ "name" : "minecraft:item.chain",
+ "id" : -286
},
{
- "name" : "minecraft:warped_stem",
- "id" : -226
+ "name" : "minecraft:item.crimson_door",
+ "id" : -244
},
{
- "name" : "minecraft:blackstone_double_slab",
- "id" : -283
+ "name" : "minecraft:item.dark_oak_door",
+ "id" : 197
},
{
- "name" : "minecraft:target",
- "id" : -239
+ "name" : "minecraft:item.flower_pot",
+ "id" : 140
},
{
- "name" : "minecraft:crimson_trapdoor",
- "id" : -246
+ "name" : "minecraft:item.frame",
+ "id" : 199
},
{
- "name" : "minecraft:polished_blackstone_brick_wall",
- "id" : -278
+ "name" : "minecraft:item.hopper",
+ "id" : 154
},
{
- "name" : "minecraft:warped_standing_sign",
- "id" : -251
+ "name" : "minecraft:item.iron_door",
+ "id" : 71
},
{
- "name" : "minecraft:warped_stairs",
- "id" : -255
+ "name" : "minecraft:item.jungle_door",
+ "id" : 195
},
{
- "name" : "minecraft:crimson_fence",
- "id" : -256
+ "name" : "minecraft:item.kelp",
+ "id" : -138
},
{
- "name" : "minecraft:warped_pressure_plate",
- "id" : -263
+ "name" : "minecraft:nether_brick",
+ "id" : 112
},
{
- "name" : "minecraft:soul_lantern",
- "id" : -269
+ "name" : "minecraft:item.nether_sprouts",
+ "id" : -238
},
{
- "name" : "minecraft:blackstone_wall",
- "id" : -277
+ "name" : "minecraft:item.nether_wart",
+ "id" : 115
+ },
+ {
+ "name" : "minecraft:item.reeds",
+ "id" : 83
+ },
+ {
+ "name" : "minecraft:item.skull",
+ "id" : 144
+ },
+ {
+ "name" : "minecraft:item.soul_campfire",
+ "id" : -290
+ },
+ {
+ "name" : "minecraft:item.spruce_door",
+ "id" : 193
+ },
+ {
+ "name" : "minecraft:item.warped_door",
+ "id" : -245
+ },
+ {
+ "name" : "minecraft:item.wheat",
+ "id" : 59
+ },
+ {
+ "name" : "minecraft:item.wooden_door",
+ "id" : 64
+ },
+ {
+ "name" : "minecraft:jigsaw",
+ "id" : -211
+ },
+ {
+ "name" : "minecraft:jukebox",
+ "id" : 84
+ },
+ {
+ "name" : "minecraft:jungle_boat",
+ "id" : 375
+ },
+ {
+ "name" : "minecraft:jungle_button",
+ "id" : -143
+ },
+ {
+ "name" : "minecraft:jungle_door",
+ "id" : 545
+ },
+ {
+ "name" : "minecraft:jungle_fence_gate",
+ "id" : 185
+ },
+ {
+ "name" : "minecraft:jungle_pressure_plate",
+ "id" : -153
+ },
+ {
+ "name" : "minecraft:jungle_sign",
+ "id" : 568
+ },
+ {
+ "name" : "minecraft:jungle_stairs",
+ "id" : 136
+ },
+ {
+ "name" : "minecraft:jungle_standing_sign",
+ "id" : -188
+ },
+ {
+ "name" : "minecraft:jungle_trapdoor",
+ "id" : -148
+ },
+ {
+ "name" : "minecraft:jungle_wall_sign",
+ "id" : -189
+ },
+ {
+ "name" : "minecraft:kelp",
+ "id" : 380
+ },
+ {
+ "name" : "minecraft:ladder",
+ "id" : 65
+ },
+ {
+ "name" : "minecraft:lantern",
+ "id" : -208
+ },
+ {
+ "name" : "minecraft:lapis_block",
+ "id" : 22
+ },
+ {
+ "name" : "minecraft:lapis_lazuli",
+ "id" : 412
+ },
+ {
+ "name" : "minecraft:lapis_ore",
+ "id" : 21
+ },
+ {
+ "name" : "minecraft:lava",
+ "id" : 11
+ },
+ {
+ "name" : "minecraft:lava_bucket",
+ "id" : 363
+ },
+ {
+ "name" : "minecraft:lava_cauldron",
+ "id" : -210
+ },
+ {
+ "name" : "minecraft:lead",
+ "id" : 537
+ },
+ {
+ "name" : "minecraft:leather",
+ "id" : 379
+ },
+ {
+ "name" : "minecraft:leather_boots",
+ "id" : 338
+ },
+ {
+ "name" : "minecraft:leather_chestplate",
+ "id" : 336
+ },
+ {
+ "name" : "minecraft:leather_helmet",
+ "id" : 335
+ },
+ {
+ "name" : "minecraft:leather_horse_armor",
+ "id" : 520
+ },
+ {
+ "name" : "minecraft:leather_leggings",
+ "id" : 337
+ },
+ {
+ "name" : "minecraft:leaves",
+ "id" : 18
+ },
+ {
+ "name" : "minecraft:leaves2",
+ "id" : 161
+ },
+ {
+ "name" : "minecraft:lectern",
+ "id" : -194
+ },
+ {
+ "name" : "minecraft:lever",
+ "id" : 69
+ },
+ {
+ "name" : "minecraft:light_block",
+ "id" : -215
+ },
+ {
+ "name" : "minecraft:light_blue_dye",
+ "id" : 405
+ },
+ {
+ "name" : "minecraft:light_blue_glazed_terracotta",
+ "id" : 223
+ },
+ {
+ "name" : "minecraft:light_gray_dye",
+ "id" : 400
+ },
+ {
+ "name" : "minecraft:light_weighted_pressure_plate",
+ "id" : 147
+ },
+ {
+ "name" : "minecraft:lime_dye",
+ "id" : 403
+ },
+ {
+ "name" : "minecraft:lime_glazed_terracotta",
+ "id" : 225
+ },
+ {
+ "name" : "minecraft:lingering_potion",
+ "id" : 552
+ },
+ {
+ "name" : "minecraft:lit_blast_furnace",
+ "id" : -214
+ },
+ {
+ "name" : "minecraft:lit_furnace",
+ "id" : 62
+ },
+ {
+ "name" : "minecraft:lit_pumpkin",
+ "id" : 91
+ },
+ {
+ "name" : "minecraft:lit_redstone_lamp",
+ "id" : 124
+ },
+ {
+ "name" : "minecraft:lit_redstone_ore",
+ "id" : 74
+ },
+ {
+ "name" : "minecraft:lit_smoker",
+ "id" : -199
+ },
+ {
+ "name" : "minecraft:llama_spawn_egg",
+ "id" : 471
+ },
+ {
+ "name" : "minecraft:lodestone",
+ "id" : -222
+ },
+ {
+ "name" : "minecraft:lodestone_compass",
+ "id" : 590
+ },
+ {
+ "name" : "minecraft:log",
+ "id" : 17
+ },
+ {
+ "name" : "minecraft:log2",
+ "id" : 162
+ },
+ {
+ "name" : "minecraft:loom",
+ "id" : -204
+ },
+ {
+ "name" : "minecraft:magenta_dye",
+ "id" : 406
+ },
+ {
+ "name" : "minecraft:magenta_glazed_terracotta",
+ "id" : 222
+ },
+ {
+ "name" : "minecraft:magma",
+ "id" : 213
+ },
+ {
+ "name" : "minecraft:magma_cream",
+ "id" : 428
+ },
+ {
+ "name" : "minecraft:magma_cube_spawn_egg",
+ "id" : 453
+ },
+ {
+ "name" : "minecraft:medicine",
+ "id" : 588
+ },
+ {
+ "name" : "minecraft:melon_block",
+ "id" : 103
+ },
+ {
+ "name" : "minecraft:melon_seeds",
+ "id" : 293
+ },
+ {
+ "name" : "minecraft:melon_slice",
+ "id" : 272
+ },
+ {
+ "name" : "minecraft:melon_stem",
+ "id" : 105
+ },
+ {
+ "name" : "minecraft:milk_bucket",
+ "id" : 361
+ },
+ {
+ "name" : "minecraft:minecart",
+ "id" : 368
+ },
+ {
+ "name" : "minecraft:mob_spawner",
+ "id" : 52
+ },
+ {
+ "name" : "minecraft:mojang_banner_pattern",
+ "id" : 574
+ },
+ {
+ "name" : "minecraft:monster_egg",
+ "id" : 97
+ },
+ {
+ "name" : "minecraft:mooshroom_spawn_egg",
+ "id" : 438
+ },
+ {
+ "name" : "minecraft:mossy_cobblestone",
+ "id" : 48
+ },
+ {
+ "name" : "minecraft:mossy_cobblestone_stairs",
+ "id" : -179
+ },
+ {
+ "name" : "minecraft:mossy_stone_brick_stairs",
+ "id" : -175
+ },
+ {
+ "name" : "minecraft:movingblock",
+ "id" : 250
+ },
+ {
+ "name" : "minecraft:mule_spawn_egg",
+ "id" : 464
+ },
+ {
+ "name" : "minecraft:mushroom_stew",
+ "id" : 260
+ },
+ {
+ "name" : "minecraft:music_disc_11",
+ "id" : 534
+ },
+ {
+ "name" : "minecraft:music_disc_13",
+ "id" : 524
+ },
+ {
+ "name" : "minecraft:music_disc_blocks",
+ "id" : 526
+ },
+ {
+ "name" : "minecraft:music_disc_cat",
+ "id" : 525
+ },
+ {
+ "name" : "minecraft:music_disc_chirp",
+ "id" : 527
+ },
+ {
+ "name" : "minecraft:music_disc_far",
+ "id" : 528
+ },
+ {
+ "name" : "minecraft:music_disc_mall",
+ "id" : 529
+ },
+ {
+ "name" : "minecraft:music_disc_mellohi",
+ "id" : 530
+ },
+ {
+ "name" : "minecraft:music_disc_pigstep",
+ "id" : 608
+ },
+ {
+ "name" : "minecraft:music_disc_stal",
+ "id" : 531
+ },
+ {
+ "name" : "minecraft:music_disc_strad",
+ "id" : 532
+ },
+ {
+ "name" : "minecraft:music_disc_wait",
+ "id" : 535
+ },
+ {
+ "name" : "minecraft:music_disc_ward",
+ "id" : 533
+ },
+ {
+ "name" : "minecraft:mutton",
+ "id" : 540
+ },
+ {
+ "name" : "minecraft:mycelium",
+ "id" : 110
+ },
+ {
+ "name" : "minecraft:name_tag",
+ "id" : 538
+ },
+ {
+ "name" : "minecraft:nautilus_shell",
+ "id" : 560
+ },
+ {
+ "name" : "minecraft:netherbrick",
+ "id" : 513
+ },
+ {
+ "name" : "minecraft:nether_brick_fence",
+ "id" : 113
+ },
+ {
+ "name" : "minecraft:nether_brick_stairs",
+ "id" : 114
+ },
+ {
+ "name" : "minecraft:nether_gold_ore",
+ "id" : -288
+ },
+ {
+ "name" : "minecraft:nether_sprouts",
+ "id" : 609
+ },
+ {
+ "name" : "minecraft:nether_star",
+ "id" : 508
+ },
+ {
+ "name" : "minecraft:nether_wart",
+ "id" : 294
+ },
+ {
+ "name" : "minecraft:nether_wart_block",
+ "id" : 214
+ },
+ {
+ "name" : "minecraft:netherite_axe",
+ "id" : 595
+ },
+ {
+ "name" : "minecraft:netherite_block",
+ "id" : -270
+ },
+ {
+ "name" : "minecraft:netherite_boots",
+ "id" : 600
+ },
+ {
+ "name" : "minecraft:netherite_chestplate",
+ "id" : 598
+ },
+ {
+ "name" : "minecraft:netherite_helmet",
+ "id" : 597
+ },
+ {
+ "name" : "minecraft:netherite_hoe",
+ "id" : 596
+ },
+ {
+ "name" : "minecraft:netherite_ingot",
+ "id" : 591
+ },
+ {
+ "name" : "minecraft:netherite_leggings",
+ "id" : 599
+ },
+ {
+ "name" : "minecraft:netherite_pickaxe",
+ "id" : 594
+ },
+ {
+ "name" : "minecraft:netherite_scrap",
+ "id" : 601
+ },
+ {
+ "name" : "minecraft:netherite_shovel",
+ "id" : 593
+ },
+ {
+ "name" : "minecraft:netherite_sword",
+ "id" : 592
+ },
+ {
+ "name" : "minecraft:netherrack",
+ "id" : 87
+ },
+ {
+ "name" : "minecraft:netherreactor",
+ "id" : 247
+ },
+ {
+ "name" : "minecraft:normal_stone_stairs",
+ "id" : -180
+ },
+ {
+ "name" : "minecraft:noteblock",
+ "id" : 25
+ },
+ {
+ "name" : "minecraft:npc_spawn_egg",
+ "id" : 468
+ },
+ {
+ "name" : "minecraft:oak_boat",
+ "id" : 373
+ },
+ {
+ "name" : "minecraft:oak_sign",
+ "id" : 358
+ },
+ {
+ "name" : "minecraft:oak_stairs",
+ "id" : 53
+ },
+ {
+ "name" : "minecraft:observer",
+ "id" : 251
+ },
+ {
+ "name" : "minecraft:obsidian",
+ "id" : 49
+ },
+ {
+ "name" : "minecraft:ocelot_spawn_egg",
+ "id" : 449
+ },
+ {
+ "name" : "minecraft:orange_dye",
+ "id" : 407
+ },
+ {
+ "name" : "minecraft:orange_glazed_terracotta",
+ "id" : 221
+ },
+ {
+ "name" : "minecraft:packed_ice",
+ "id" : 174
+ },
+ {
+ "name" : "minecraft:painting",
+ "id" : 357
+ },
+ {
+ "name" : "minecraft:panda_spawn_egg",
+ "id" : 487
+ },
+ {
+ "name" : "minecraft:paper",
+ "id" : 384
+ },
+ {
+ "name" : "minecraft:parrot_spawn_egg",
+ "id" : 476
+ },
+ {
+ "name" : "minecraft:phantom_membrane",
+ "id" : 564
+ },
+ {
+ "name" : "minecraft:phantom_spawn_egg",
+ "id" : 484
+ },
+ {
+ "name" : "minecraft:pig_spawn_egg",
+ "id" : 435
+ },
+ {
+ "name" : "minecraft:piglin_banner_pattern",
+ "id" : 577
+ },
+ {
+ "name" : "minecraft:piglin_brute_spawn_egg",
+ "id" : 497
+ },
+ {
+ "name" : "minecraft:piglin_spawn_egg",
+ "id" : 495
+ },
+ {
+ "name" : "minecraft:pillager_spawn_egg",
+ "id" : 489
+ },
+ {
+ "name" : "minecraft:pink_dye",
+ "id" : 402
+ },
+ {
+ "name" : "minecraft:pink_glazed_terracotta",
+ "id" : 226
+ },
+ {
+ "name" : "minecraft:piston",
+ "id" : 33
+ },
+ {
+ "name" : "minecraft:pistonarmcollision",
+ "id" : 34
+ },
+ {
+ "name" : "minecraft:planks",
+ "id" : 5
+ },
+ {
+ "name" : "minecraft:podzol",
+ "id" : 243
+ },
+ {
+ "name" : "minecraft:poisonous_potato",
+ "id" : 282
+ },
+ {
+ "name" : "minecraft:polar_bear_spawn_egg",
+ "id" : 470
+ },
+ {
+ "name" : "minecraft:polished_andesite_stairs",
+ "id" : -174
+ },
+ {
+ "name" : "minecraft:polished_basalt",
+ "id" : -235
},
{
"name" : "minecraft:polished_blackstone",
"id" : -291
},
{
- "name" : "minecraft:polished_blackstone_stairs",
- "id" : -292
+ "name" : "minecraft:polished_blackstone_brick_double_slab",
+ "id" : -285
+ },
+ {
+ "name" : "minecraft:polished_blackstone_brick_slab",
+ "id" : -284
+ },
+ {
+ "name" : "minecraft:polished_blackstone_brick_stairs",
+ "id" : -275
+ },
+ {
+ "name" : "minecraft:polished_blackstone_brick_wall",
+ "id" : -278
+ },
+ {
+ "name" : "minecraft:polished_blackstone_bricks",
+ "id" : -274
+ },
+ {
+ "name" : "minecraft:polished_blackstone_button",
+ "id" : -296
+ },
+ {
+ "name" : "minecraft:polished_blackstone_double_slab",
+ "id" : -294
},
{
"name" : "minecraft:polished_blackstone_pressure_plate",
"id" : -295
},
+ {
+ "name" : "minecraft:polished_blackstone_slab",
+ "id" : -293
+ },
+ {
+ "name" : "minecraft:polished_blackstone_stairs",
+ "id" : -292
+ },
+ {
+ "name" : "minecraft:polished_blackstone_wall",
+ "id" : -297
+ },
+ {
+ "name" : "minecraft:polished_diorite_stairs",
+ "id" : -173
+ },
+ {
+ "name" : "minecraft:polished_granite_stairs",
+ "id" : -172
+ },
+ {
+ "name" : "minecraft:popped_chorus_fruit",
+ "id" : 549
+ },
+ {
+ "name" : "minecraft:porkchop",
+ "id" : 262
+ },
+ {
+ "name" : "minecraft:portal",
+ "id" : 90
+ },
+ {
+ "name" : "minecraft:potato",
+ "id" : 280
+ },
+ {
+ "name" : "minecraft:potatoes",
+ "id" : 142
+ },
+ {
+ "name" : "minecraft:potion",
+ "id" : 424
+ },
+ {
+ "name" : "minecraft:powered_comparator",
+ "id" : 150
+ },
+ {
+ "name" : "minecraft:powered_repeater",
+ "id" : 94
+ },
+ {
+ "name" : "minecraft:prismarine",
+ "id" : 168
+ },
+ {
+ "name" : "minecraft:prismarine_bricks_stairs",
+ "id" : -4
+ },
+ {
+ "name" : "minecraft:prismarine_crystals",
+ "id" : 539
+ },
+ {
+ "name" : "minecraft:prismarine_shard",
+ "id" : 555
+ },
+ {
+ "name" : "minecraft:prismarine_stairs",
+ "id" : -2
+ },
+ {
+ "name" : "minecraft:pufferfish",
+ "id" : 267
+ },
+ {
+ "name" : "minecraft:pufferfish_bucket",
+ "id" : 367
+ },
+ {
+ "name" : "minecraft:pufferfish_spawn_egg",
+ "id" : 479
+ },
+ {
+ "name" : "minecraft:pumpkin",
+ "id" : 86
+ },
+ {
+ "name" : "minecraft:pumpkin_pie",
+ "id" : 284
+ },
+ {
+ "name" : "minecraft:pumpkin_seeds",
+ "id" : 292
+ },
+ {
+ "name" : "minecraft:pumpkin_stem",
+ "id" : 104
+ },
+ {
+ "name" : "minecraft:purple_dye",
+ "id" : 398
+ },
+ {
+ "name" : "minecraft:purple_glazed_terracotta",
+ "id" : 219
+ },
+ {
+ "name" : "minecraft:purpur_block",
+ "id" : 201
+ },
+ {
+ "name" : "minecraft:purpur_stairs",
+ "id" : 203
+ },
+ {
+ "name" : "minecraft:quartz",
+ "id" : 514
+ },
+ {
+ "name" : "minecraft:quartz_block",
+ "id" : 155
+ },
+ {
+ "name" : "minecraft:quartz_bricks",
+ "id" : -304
+ },
+ {
+ "name" : "minecraft:quartz_ore",
+ "id" : 153
+ },
+ {
+ "name" : "minecraft:quartz_stairs",
+ "id" : 156
+ },
+ {
+ "name" : "minecraft:rabbit",
+ "id" : 288
+ },
+ {
+ "name" : "minecraft:rabbit_foot",
+ "id" : 518
+ },
+ {
+ "name" : "minecraft:rabbit_hide",
+ "id" : 519
+ },
+ {
+ "name" : "minecraft:rabbit_spawn_egg",
+ "id" : 457
+ },
+ {
+ "name" : "minecraft:rabbit_stew",
+ "id" : 290
+ },
+ {
+ "name" : "minecraft:rail",
+ "id" : 66
+ },
+ {
+ "name" : "minecraft:rapid_fertilizer",
+ "id" : 586
+ },
+ {
+ "name" : "minecraft:ravager_spawn_egg",
+ "id" : 491
+ },
+ {
+ "name" : "minecraft:real_double_stone_slab",
+ "id" : 43
+ },
+ {
+ "name" : "minecraft:real_double_stone_slab2",
+ "id" : 181
+ },
+ {
+ "name" : "minecraft:real_double_stone_slab3",
+ "id" : -167
+ },
+ {
+ "name" : "minecraft:real_double_stone_slab4",
+ "id" : -168
+ },
+ {
+ "name" : "minecraft:red_dye",
+ "id" : 394
+ },
+ {
+ "name" : "minecraft:red_flower",
+ "id" : 38
+ },
+ {
+ "name" : "minecraft:red_glazed_terracotta",
+ "id" : 234
+ },
+ {
+ "name" : "minecraft:red_mushroom",
+ "id" : 40
+ },
+ {
+ "name" : "minecraft:red_mushroom_block",
+ "id" : 100
+ },
+ {
+ "name" : "minecraft:red_nether_brick",
+ "id" : 215
+ },
+ {
+ "name" : "minecraft:red_nether_brick_stairs",
+ "id" : -184
+ },
+ {
+ "name" : "minecraft:red_sandstone",
+ "id" : 179
+ },
+ {
+ "name" : "minecraft:red_sandstone_stairs",
+ "id" : 180
+ },
+ {
+ "name" : "minecraft:redstone",
+ "id" : 371
+ },
+ {
+ "name" : "minecraft:redstone_block",
+ "id" : 152
+ },
+ {
+ "name" : "minecraft:redstone_lamp",
+ "id" : 123
+ },
+ {
+ "name" : "minecraft:redstone_ore",
+ "id" : 73
+ },
+ {
+ "name" : "minecraft:redstone_torch",
+ "id" : 76
+ },
+ {
+ "name" : "minecraft:redstone_wire",
+ "id" : 55
+ },
+ {
+ "name" : "minecraft:repeater",
+ "id" : 417
+ },
+ {
+ "name" : "minecraft:repeating_command_block",
+ "id" : 188
+ },
+ {
+ "name" : "minecraft:reserved6",
+ "id" : 255
+ },
+ {
+ "name" : "minecraft:respawn_anchor",
+ "id" : -272
+ },
+ {
+ "name" : "minecraft:rotten_flesh",
+ "id" : 277
+ },
+ {
+ "name" : "minecraft:saddle",
+ "id" : 369
+ },
+ {
+ "name" : "minecraft:salmon",
+ "id" : 265
+ },
+ {
+ "name" : "minecraft:salmon_bucket",
+ "id" : 365
+ },
+ {
+ "name" : "minecraft:salmon_spawn_egg",
+ "id" : 480
+ },
+ {
+ "name" : "minecraft:sand",
+ "id" : 12
+ },
+ {
+ "name" : "minecraft:sandstone",
+ "id" : 24
+ },
+ {
+ "name" : "minecraft:sandstone_stairs",
+ "id" : 128
+ },
+ {
+ "name" : "minecraft:sapling",
+ "id" : 6
+ },
+ {
+ "name" : "minecraft:scaffolding",
+ "id" : -165
+ },
+ {
+ "name" : "minecraft:scute",
+ "id" : 562
+ },
+ {
+ "name" : "minecraft:sea_pickle",
+ "id" : -156
+ },
+ {
+ "name" : "minecraft:seagrass",
+ "id" : -130
+ },
+ {
+ "name" : "minecraft:sealantern",
+ "id" : 169
+ },
+ {
+ "name" : "minecraft:shears",
+ "id" : 419
+ },
+ {
+ "name" : "minecraft:sheep_spawn_egg",
+ "id" : 436
+ },
+ {
+ "name" : "minecraft:shield",
+ "id" : 355
+ },
+ {
+ "name" : "minecraft:shroomlight",
+ "id" : -230
+ },
+ {
+ "name" : "minecraft:shulker_box",
+ "id" : 218
+ },
+ {
+ "name" : "minecraft:shulker_shell",
+ "id" : 556
+ },
+ {
+ "name" : "minecraft:shulker_spawn_egg",
+ "id" : 467
+ },
+ {
+ "name" : "minecraft:silver_glazed_terracotta",
+ "id" : 228
+ },
+ {
+ "name" : "minecraft:silverfish_spawn_egg",
+ "id" : 441
+ },
+ {
+ "name" : "minecraft:skeleton_horse_spawn_egg",
+ "id" : 465
+ },
+ {
+ "name" : "minecraft:skeleton_spawn_egg",
+ "id" : 442
+ },
+ {
+ "name" : "minecraft:skull",
+ "id" : 506
+ },
+ {
+ "name" : "minecraft:skull_banner_pattern",
+ "id" : 573
+ },
+ {
+ "name" : "minecraft:slime",
+ "id" : 165
+ },
+ {
+ "name" : "minecraft:slime_ball",
+ "id" : 386
+ },
+ {
+ "name" : "minecraft:slime_spawn_egg",
+ "id" : 443
+ },
+ {
+ "name" : "minecraft:smithing_table",
+ "id" : -202
+ },
+ {
+ "name" : "minecraft:smoker",
+ "id" : -198
+ },
+ {
+ "name" : "minecraft:smooth_quartz_stairs",
+ "id" : -185
+ },
+ {
+ "name" : "minecraft:smooth_red_sandstone_stairs",
+ "id" : -176
+ },
+ {
+ "name" : "minecraft:smooth_sandstone_stairs",
+ "id" : -177
+ },
+ {
+ "name" : "minecraft:smooth_stone",
+ "id" : -183
+ },
+ {
+ "name" : "minecraft:snow",
+ "id" : 80
+ },
+ {
+ "name" : "minecraft:snow_layer",
+ "id" : 78
+ },
+ {
+ "name" : "minecraft:snowball",
+ "id" : 372
+ },
+ {
+ "name" : "minecraft:soul_campfire",
+ "id" : 610
+ },
+ {
+ "name" : "minecraft:soul_fire",
+ "id" : -237
+ },
+ {
+ "name" : "minecraft:soul_lantern",
+ "id" : -269
+ },
+ {
+ "name" : "minecraft:soul_sand",
+ "id" : 88
+ },
+ {
+ "name" : "minecraft:soul_soil",
+ "id" : -236
+ },
+ {
+ "name" : "minecraft:soul_torch",
+ "id" : -268
+ },
+ {
+ "name" : "minecraft:sparkler",
+ "id" : 589
+ },
+ {
+ "name" : "minecraft:spawn_egg",
+ "id" : 614
+ },
+ {
+ "name" : "minecraft:spider_eye",
+ "id" : 278
+ },
+ {
+ "name" : "minecraft:spider_spawn_egg",
+ "id" : 444
+ },
+ {
+ "name" : "minecraft:splash_potion",
+ "id" : 551
+ },
+ {
+ "name" : "minecraft:sponge",
+ "id" : 19
+ },
+ {
+ "name" : "minecraft:spruce_boat",
+ "id" : 376
+ },
+ {
+ "name" : "minecraft:spruce_button",
+ "id" : -144
+ },
+ {
+ "name" : "minecraft:spruce_door",
+ "id" : 543
+ },
+ {
+ "name" : "minecraft:spruce_fence_gate",
+ "id" : 183
+ },
+ {
+ "name" : "minecraft:spruce_pressure_plate",
+ "id" : -154
+ },
+ {
+ "name" : "minecraft:spruce_sign",
+ "id" : 566
+ },
+ {
+ "name" : "minecraft:spruce_stairs",
+ "id" : 134
+ },
+ {
+ "name" : "minecraft:spruce_standing_sign",
+ "id" : -181
+ },
+ {
+ "name" : "minecraft:spruce_trapdoor",
+ "id" : -149
+ },
+ {
+ "name" : "minecraft:spruce_wall_sign",
+ "id" : -182
+ },
+ {
+ "name" : "minecraft:squid_spawn_egg",
+ "id" : 448
+ },
+ {
+ "name" : "minecraft:stained_glass",
+ "id" : 241
+ },
+ {
+ "name" : "minecraft:stained_glass_pane",
+ "id" : 160
+ },
+ {
+ "name" : "minecraft:stained_hardened_clay",
+ "id" : 159
+ },
+ {
+ "name" : "minecraft:standing_banner",
+ "id" : 176
+ },
+ {
+ "name" : "minecraft:standing_sign",
+ "id" : 63
+ },
+ {
+ "name" : "minecraft:stick",
+ "id" : 320
+ },
+ {
+ "name" : "minecraft:sticky_piston",
+ "id" : 29
+ },
+ {
+ "name" : "minecraft:stickypistonarmcollision",
+ "id" : -217
+ },
+ {
+ "name" : "minecraft:stone",
+ "id" : 1
+ },
+ {
+ "name" : "minecraft:stone_axe",
+ "id" : 315
+ },
+ {
+ "name" : "minecraft:stone_brick_stairs",
+ "id" : 109
+ },
+ {
+ "name" : "minecraft:stone_button",
+ "id" : 77
+ },
+ {
+ "name" : "minecraft:stone_hoe",
+ "id" : 330
+ },
+ {
+ "name" : "minecraft:stone_pickaxe",
+ "id" : 314
+ },
+ {
+ "name" : "minecraft:stone_pressure_plate",
+ "id" : 70
+ },
+ {
+ "name" : "minecraft:stone_shovel",
+ "id" : 313
+ },
+ {
+ "name" : "minecraft:stone_stairs",
+ "id" : 67
+ },
+ {
+ "name" : "minecraft:stone_sword",
+ "id" : 312
+ },
+ {
+ "name" : "minecraft:stonebrick",
+ "id" : 98
+ },
+ {
+ "name" : "minecraft:stonecutter",
+ "id" : 245
+ },
+ {
+ "name" : "minecraft:stonecutter_block",
+ "id" : -197
+ },
+ {
+ "name" : "minecraft:stray_spawn_egg",
+ "id" : 460
+ },
+ {
+ "name" : "minecraft:strider_spawn_egg",
+ "id" : 493
+ },
+ {
+ "name" : "minecraft:string",
+ "id" : 326
+ },
+ {
+ "name" : "minecraft:stripped_acacia_log",
+ "id" : -8
+ },
+ {
+ "name" : "minecraft:stripped_birch_log",
+ "id" : -6
+ },
+ {
+ "name" : "minecraft:stripped_crimson_hyphae",
+ "id" : -300
+ },
+ {
+ "name" : "minecraft:stripped_crimson_stem",
+ "id" : -240
+ },
+ {
+ "name" : "minecraft:stripped_dark_oak_log",
+ "id" : -9
+ },
+ {
+ "name" : "minecraft:stripped_jungle_log",
+ "id" : -7
+ },
+ {
+ "name" : "minecraft:stripped_oak_log",
+ "id" : -10
+ },
+ {
+ "name" : "minecraft:stripped_spruce_log",
+ "id" : -5
+ },
+ {
+ "name" : "minecraft:stripped_warped_hyphae",
+ "id" : -301
+ },
+ {
+ "name" : "minecraft:stripped_warped_stem",
+ "id" : -241
+ },
+ {
+ "name" : "minecraft:structure_block",
+ "id" : 252
+ },
+ {
+ "name" : "minecraft:structure_void",
+ "id" : 217
+ },
+ {
+ "name" : "minecraft:sugar",
+ "id" : 414
+ },
+ {
+ "name" : "minecraft:sugar_cane",
+ "id" : 383
+ },
+ {
+ "name" : "minecraft:suspicious_stew",
+ "id" : 579
+ },
+ {
+ "name" : "minecraft:sweet_berries",
+ "id" : 287
+ },
+ {
+ "name" : "minecraft:sweet_berry_bush",
+ "id" : -207
+ },
+ {
+ "name" : "minecraft:tallgrass",
+ "id" : 31
+ },
+ {
+ "name" : "minecraft:target",
+ "id" : -239
+ },
+ {
+ "name" : "minecraft:tnt",
+ "id" : 46
+ },
+ {
+ "name" : "minecraft:tnt_minecart",
+ "id" : 515
+ },
+ {
+ "name" : "minecraft:torch",
+ "id" : 50
+ },
+ {
+ "name" : "minecraft:totem_of_undying",
+ "id" : 558
+ },
+ {
+ "name" : "minecraft:trapdoor",
+ "id" : 96
+ },
+ {
+ "name" : "minecraft:trapped_chest",
+ "id" : 146
+ },
+ {
+ "name" : "minecraft:trident",
+ "id" : 536
+ },
+ {
+ "name" : "minecraft:tripwire",
+ "id" : 132
+ },
+ {
+ "name" : "minecraft:tripwire_hook",
+ "id" : 131
+ },
+ {
+ "name" : "minecraft:tropical_fish",
+ "id" : 266
+ },
+ {
+ "name" : "minecraft:tropical_fish_bucket",
+ "id" : 366
+ },
+ {
+ "name" : "minecraft:tropical_fish_spawn_egg",
+ "id" : 477
+ },
+ {
+ "name" : "minecraft:turtle_egg",
+ "id" : -159
+ },
+ {
+ "name" : "minecraft:turtle_helmet",
+ "id" : 563
+ },
+ {
+ "name" : "minecraft:turtle_spawn_egg",
+ "id" : 483
+ },
+ {
+ "name" : "minecraft:twisting_vines",
+ "id" : -287
+ },
+ {
+ "name" : "minecraft:underwater_torch",
+ "id" : 239
+ },
+ {
+ "name" : "minecraft:undyed_shulker_box",
+ "id" : 205
+ },
+ {
+ "name" : "minecraft:unknown",
+ "id" : -305
+ },
+ {
+ "name" : "minecraft:unlit_redstone_torch",
+ "id" : 75
+ },
+ {
+ "name" : "minecraft:unpowered_comparator",
+ "id" : 149
+ },
+ {
+ "name" : "minecraft:unpowered_repeater",
+ "id" : 93
+ },
+ {
+ "name" : "minecraft:vex_spawn_egg",
+ "id" : 474
+ },
+ {
+ "name" : "minecraft:villager_spawn_egg",
+ "id" : 447
+ },
+ {
+ "name" : "minecraft:vindicator_spawn_egg",
+ "id" : 472
+ },
+ {
+ "name" : "minecraft:vine",
+ "id" : 106
+ },
+ {
+ "name" : "minecraft:wall_banner",
+ "id" : 177
+ },
+ {
+ "name" : "minecraft:wall_sign",
+ "id" : 68
+ },
+ {
+ "name" : "minecraft:wandering_trader_spawn_egg",
+ "id" : 490
+ },
+ {
+ "name" : "minecraft:warped_button",
+ "id" : -261
+ },
+ {
+ "name" : "minecraft:warped_door",
+ "id" : 605
+ },
+ {
+ "name" : "minecraft:warped_double_slab",
+ "id" : -267
+ },
+ {
+ "name" : "minecraft:warped_fence",
+ "id" : -257
+ },
+ {
+ "name" : "minecraft:warped_fence_gate",
+ "id" : -259
+ },
+ {
+ "name" : "minecraft:warped_fungus",
+ "id" : -229
+ },
+ {
+ "name" : "minecraft:warped_fungus_on_a_stick",
+ "id" : 606
+ },
{
"name" : "minecraft:warped_hyphae",
"id" : -298
},
{
- "name" : "minecraft:crimson_hyphae",
- "id" : -299
+ "name" : "minecraft:warped_nylium",
+ "id" : -233
},
{
- "name" : "minecraft:cracked_nether_bricks",
- "id" : -303
+ "name" : "minecraft:warped_planks",
+ "id" : -243
+ },
+ {
+ "name" : "minecraft:warped_pressure_plate",
+ "id" : -263
+ },
+ {
+ "name" : "minecraft:warped_roots",
+ "id" : -224
+ },
+ {
+ "name" : "minecraft:warped_sign",
+ "id" : 603
+ },
+ {
+ "name" : "minecraft:warped_slab",
+ "id" : -265
+ },
+ {
+ "name" : "minecraft:warped_stairs",
+ "id" : -255
+ },
+ {
+ "name" : "minecraft:warped_standing_sign",
+ "id" : -251
+ },
+ {
+ "name" : "minecraft:warped_stem",
+ "id" : -226
+ },
+ {
+ "name" : "minecraft:warped_trapdoor",
+ "id" : -247
+ },
+ {
+ "name" : "minecraft:warped_wall_sign",
+ "id" : -253
+ },
+ {
+ "name" : "minecraft:warped_wart_block",
+ "id" : -227
+ },
+ {
+ "name" : "minecraft:water",
+ "id" : 9
+ },
+ {
+ "name" : "minecraft:water_bucket",
+ "id" : 362
+ },
+ {
+ "name" : "minecraft:waterlily",
+ "id" : 111
+ },
+ {
+ "name" : "minecraft:web",
+ "id" : 30
+ },
+ {
+ "name" : "minecraft:weeping_vines",
+ "id" : -231
+ },
+ {
+ "name" : "minecraft:wheat",
+ "id" : 334
+ },
+ {
+ "name" : "minecraft:wheat_seeds",
+ "id" : 291
+ },
+ {
+ "name" : "minecraft:white_dye",
+ "id" : 408
+ },
+ {
+ "name" : "minecraft:white_glazed_terracotta",
+ "id" : 220
+ },
+ {
+ "name" : "minecraft:witch_spawn_egg",
+ "id" : 450
+ },
+ {
+ "name" : "minecraft:wither_rose",
+ "id" : -216
+ },
+ {
+ "name" : "minecraft:wither_skeleton_spawn_egg",
+ "id" : 462
+ },
+ {
+ "name" : "minecraft:wolf_spawn_egg",
+ "id" : 437
+ },
+ {
+ "name" : "minecraft:wood",
+ "id" : -212
+ },
+ {
+ "name" : "minecraft:wooden_axe",
+ "id" : 311
+ },
+ {
+ "name" : "minecraft:wooden_button",
+ "id" : 143
+ },
+ {
+ "name" : "minecraft:wooden_door",
+ "id" : 359
+ },
+ {
+ "name" : "minecraft:wooden_hoe",
+ "id" : 329
+ },
+ {
+ "name" : "minecraft:wooden_pickaxe",
+ "id" : 310
+ },
+ {
+ "name" : "minecraft:wooden_pressure_plate",
+ "id" : 72
+ },
+ {
+ "name" : "minecraft:wooden_shovel",
+ "id" : 309
+ },
+ {
+ "name" : "minecraft:wooden_slab",
+ "id" : 158
+ },
+ {
+ "name" : "minecraft:wooden_sword",
+ "id" : 308
+ },
+ {
+ "name" : "minecraft:wool",
+ "id" : 35
+ },
+ {
+ "name" : "minecraft:writable_book",
+ "id" : 500
+ },
+ {
+ "name" : "minecraft:written_book",
+ "id" : 501
+ },
+ {
+ "name" : "minecraft:yellow_dye",
+ "id" : 404
+ },
+ {
+ "name" : "minecraft:yellow_flower",
+ "id" : 37
+ },
+ {
+ "name" : "minecraft:yellow_glazed_terracotta",
+ "id" : 224
+ },
+ {
+ "name" : "minecraft:zoglin_spawn_egg",
+ "id" : 496
+ },
+ {
+ "name" : "minecraft:zombie_horse_spawn_egg",
+ "id" : 466
+ },
+ {
+ "name" : "minecraft:zombie_pigman_spawn_egg",
+ "id" : 446
+ },
+ {
+ "name" : "minecraft:zombie_spawn_egg",
+ "id" : 445
+ },
+ {
+ "name" : "minecraft:zombie_villager_spawn_egg",
+ "id" : 475
}
]
\ No newline at end of file
diff --git a/connector/src/main/resources/config.yml b/connector/src/main/resources/config.yml
index 6be502a73..7dc9766fb 100644
--- a/connector/src/main/resources/config.yml
+++ b/connector/src/main/resources/config.yml
@@ -117,6 +117,11 @@ above-bedrock-nether-building: false
# want to download the resource packs
force-resource-packs: true
+# Allows Xbox achievements to be unlocked.
+# This disables certain commands so the Bedrock client can't to "cheat" to get them.
+# Commands such as /gamemode and /give will not work from Bedrock with this enabled
+xbox-achievements-enabled: false
+
# bStats is a stat tracker that is entirely anonymous and tracks only basic information
# about Geyser, such as how many people are online, how many servers are using Geyser,
# what OS is being used, etc. You can learn more about bStats here: https://bstats.org/.
diff --git a/connector/src/main/resources/languages b/connector/src/main/resources/languages
index a4125be98..bf4b0b710 160000
--- a/connector/src/main/resources/languages
+++ b/connector/src/main/resources/languages
@@ -1 +1 @@
-Subproject commit a4125be98fefea6cefd43dc52ccb2ade4e70573e
+Subproject commit bf4b0b7103193154dd0b06e0459dc375c753069a
diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings
index c87cc5fb0..618a9b981 160000
--- a/connector/src/main/resources/mappings
+++ b/connector/src/main/resources/mappings
@@ -1 +1 @@
-Subproject commit c87cc5fb05eb92beac638234906d836f9f1178ed
+Subproject commit 618a9b981398647125b1b63494cb49ad93433243
diff --git a/connector/src/test/java/org/geysermc/connector/network/translators/chat/MessageTranslatorTest.java b/connector/src/test/java/org/geysermc/connector/network/translators/chat/MessageTranslatorTest.java
new file mode 100644
index 000000000..5d52c79b9
--- /dev/null
+++ b/connector/src/test/java/org/geysermc/connector/network/translators/chat/MessageTranslatorTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019-2020 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.connector.network.translators.chat;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MessageTranslatorTest {
+
+ private Map messages = new HashMap<>();
+
+ @Before
+ public void setUp() throws Exception {
+ messages.put("{\"text\":\"\",\"extra\":[{\"text\":\"DoctorMad9952 joined the game\",\"color\":\"yellow\"}]}",
+ "§eDoctorMad9952 joined the game");
+
+ messages.put("{\"text\":\"\",\"extra\":[\"Plugins (3): \",{\"text\":\"WorldEdit\",\"color\":\"green\"},{\"text\":\", \",\"color\":\"white\"},{\"text\":\"ViaVersion\",\"color\":\"green\"},{\"text\":\", \",\"color\":\"white\"},{\"text\":\"Geyser-Spigot\",\"color\":\"green\"}]}",
+ "Plugins (3): §aWorldEdit§f, §aViaVersion§f, §aGeyser-Spigot");
+
+ // RGB downgrade test
+ messages.put("{\"extra\":[{\"text\":\" \"},{\"color\":\"gold\",\"text\":\"The \"},{\"color\":\"#E14248\",\"obfuscated\":true,\"text\":\"||\"},{\"color\":\"#3AA9FF\",\"bold\":true,\"text\":\"CubeCraft\"},{\"color\":\"#E14248\",\"obfuscated\":true,\"text\":\"||\"},{\"color\":\"gold\",\"text\":\" Network \"},{\"color\":\"green\",\"text\":\"[1.8/1.9+]\\n \"},{\"color\":\"#f5e342\",\"text\":\"✦ \"},{\"color\":\"#b042f5\",\"bold\":true,\"text\":\"N\"},{\"color\":\"#c142f5\",\"bold\":true,\"text\":\"E\"},{\"color\":\"#d342f5\",\"bold\":true,\"text\":\"W\"},{\"color\":\"#e442f5\",\"bold\":true,\"text\":\":\"},{\"color\":\"#f542f5\",\"bold\":true,\"text\":\" \"},{\"color\":\"#bcf542\",\"bold\":true,\"text\":\"A\"},{\"color\":\"#acee3f\",\"bold\":true,\"text\":\"M\"},{\"color\":\"#9ce73c\",\"bold\":true,\"text\":\"O\"},{\"color\":\"#8ce039\",\"bold\":true,\"text\":\"N\"},{\"color\":\"#7cd936\",\"bold\":true,\"text\":\"G\"},{\"color\":\"#6cd233\",\"bold\":true,\"text\":\" \"},{\"color\":\"#5ccb30\",\"bold\":true,\"text\":\"S\"},{\"color\":\"#4cc42d\",\"bold\":true,\"text\":\"L\"},{\"color\":\"#3cbd2a\",\"bold\":true,\"text\":\"I\"},{\"color\":\"#2cb627\",\"bold\":true,\"text\":\"M\"},{\"color\":\"#1caf24\",\"bold\":true,\"text\":\"E\"},{\"color\":\"#0ca821\",\"bold\":true,\"text\":\"S\"},{\"color\":\"#f5e342\",\"text\":\" \"},{\"color\":\"#6d7c87\",\"text\":\"(kinda sus) \"},{\"color\":\"#f5e342\",\"text\":\"✦\"}],\"text\":\"\"}",
+ " §6The §c§k||§r§3§lCubeCraft§r§c§k||§r§6 Network §a[1.8/1.9+]\n" +
+ " §e✦ §d§lN§r§d§lE§r§d§lW§r§d§l:§r§d§l §r§e§lA§r§e§lM§r§a§lO§r§a§lN§r§a§lG§r§a§l §r§a§lS§r§a§lL§r§2§lI§r§2§lM§r§2§lE§r§2§lS§r§e §8(kinda sus) §e✦");
+ }
+
+ @Test
+ public void convertMessage() {
+ for (Map.Entry entry : messages.entrySet()) {
+ String bedrockMessage = MessageTranslator.convertMessage(entry.getKey(), "en_US");
+ Assert.assertEquals("Translation of messages is incorrect", bedrockMessage, entry.getValue());
+ }
+ }
+
+ @Test
+ public void convertMessageLenient() {
+ Assert.assertEquals("All newline message is not handled properly", "\n\n\n\n", MessageTranslator.convertMessageLenient("\n\n\n\n"));
+ Assert.assertEquals("Empty message is not handled properly", "", MessageTranslator.convertMessageLenient(""));
+ Assert.assertEquals("Reset before message is not handled properly", "§r§eGame Selector", MessageTranslator.convertMessageLenient("§r§eGame Selector"));
+ }
+}
diff --git a/pom.xml b/pom.xml
index 345933ac5..1b544f9ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0
org.geysermc
geyser-parent
- parent
+ 1.2.0-SNAPSHOT
pom
Geyser
Allows for players from Minecraft Bedrock Edition to join Minecraft Java Edition servers.