diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 4a570df5..9cb0726c 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -29,12 +29,12 @@ jobs: with: name: Geyser Standalone path: bootstrap/standalone/target/Geyser.jar - - name: Archive artifacts (Geyser Bukkit) + - name: Archive artifacts (Geyser Spigot) uses: actions/upload-artifact@v2 if: success() with: - name: Geyser Bukkit - path: bootstrap/bukkit/target/Geyser-Bukkit.jar + name: Geyser Spigot + path: bootstrap/spigot/target/Geyser-Spigot.jar - name: Archive artifacts (Geyser BungeeCord) uses: actions/upload-artifact@v2 if: success() diff --git a/.gitmodules b/.gitmodules index 0090e64a..35887822 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "connector/src/main/resources/mappings"] path = connector/src/main/resources/mappings url = https://github.com/GeyserMC/mappings.git + branch = feature/1.16 +[submodule "connector/src/main/resources/languages"] + path = connector/src/main/resources/languages + url = https://github.com/GeyserMC/languages.git diff --git a/README.md b/README.md index b8f8749b..a22a7a8d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,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.14.6(0) and Minecraft Java v1.15.2. +### Currently supporting Minecraft Bedrock v1.16.0/1 and Minecraft Java v1.16.1. ## 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 dd66db32..565264f0 100644 --- a/bootstrap/bungeecord/pom.xml +++ b/bootstrap/bungeecord/pom.xml @@ -6,7 +6,7 @@ org.geysermc bootstrap-parent - 1.0-SNAPSHOT + 1.0.0 ../ bootstrap-bungeecord @@ -14,7 +14,7 @@ org.geysermc connector - 1.0-SNAPSHOT + 1.0.0 compile @@ -65,6 +65,10 @@ io.netty org.geysermc.platform.bungeecord.shaded.netty + + org.reflections.reflections + org.geysermc.platform.bungeecord.shaded.reflections + diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeDumpInfo.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeDumpInfo.java new file mode 100644 index 00000000..54701116 --- /dev/null +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeDumpInfo.java @@ -0,0 +1,63 @@ +/* + * 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.platform.bungeecord; + +import lombok.Getter; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.plugin.Plugin; +import org.geysermc.connector.dump.BootstrapDumpInfo; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@Getter +public class GeyserBungeeDumpInfo extends BootstrapDumpInfo { + + private String platformName; + private String platformVersion; + private boolean onlineMode; + private List listeners; + private List plugins; + + GeyserBungeeDumpInfo(ProxyServer proxy) { + super(); + this.platformName = proxy.getName(); + this.platformVersion = proxy.getVersion(); + this.onlineMode = proxy.getConfig().isOnlineMode(); + this.listeners = new ArrayList<>(); + this.plugins = new ArrayList<>(); + + for (net.md_5.bungee.api.config.ListenerInfo listener : proxy.getConfig().getListeners()) { + this.listeners.add(new ListenerInfo(listener.getHost().getHostString(), listener.getHost().getPort())); + } + + for (Plugin plugin : proxy.getPluginManager().getPlugins()) { + this.plugins.add(new PluginInfo(true, plugin.getDescription().getName(), plugin.getDescription().getVersion(), plugin.getDescription().getMain(), Arrays.asList(plugin.getDescription().getAuthor()))); + } + } +} diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java index eabbcc69..999b29ea 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeeMain.java @@ -26,7 +26,7 @@ package org.geysermc.platform.bungeecord; -import org.geysermc.common.main.IGeyserMain; +import org.geysermc.connector.common.main.IGeyserMain; public class GeyserBungeeMain extends IGeyserMain { diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java index c7f8f276..f2166aad 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePingPassthrough.java @@ -35,7 +35,7 @@ import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.event.ProxyPingEvent; import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.protocol.ProtocolConstants; -import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.common.ping.GeyserPingInfo; import org.geysermc.connector.ping.IGeyserPingPassthrough; import java.net.Inet4Address; @@ -60,14 +60,15 @@ public class GeyserBungeePingPassthrough implements IGeyserPingPassthrough, List else future.complete(event); })); ProxyPingEvent event = future.join(); + ServerPing response = event.getResponse(); GeyserPingInfo geyserPingInfo = new GeyserPingInfo( - event.getResponse().getDescription(), - event.getResponse().getPlayers().getOnline(), - event.getResponse().getPlayers().getMax() + response.getDescriptionComponent().toLegacyText(), + new GeyserPingInfo.Players(response.getPlayers().getMax(), response.getPlayers().getOnline()), + new GeyserPingInfo.Version(response.getVersion().getName(), response.getVersion().getProtocol()) ); if (event.getResponse().getPlayers().getSample() != null) { Arrays.stream(event.getResponse().getPlayers().getSample()).forEach(proxiedPlayer -> { - geyserPingInfo.addPlayer(proxiedPlayer.getName()); + geyserPingInfo.getPlayerList().add(proxiedPlayer.getName()); }); } return geyserPingInfo; 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 1cf519c0..38d319e1 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 @@ -30,14 +30,16 @@ import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.config.Configuration; import net.md_5.bungee.config.ConfigurationProvider; import net.md_5.bungee.config.YamlConfiguration; -import org.geysermc.common.PlatformType; +import org.geysermc.connector.common.PlatformType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.configuration.GeyserConfiguration; +import org.geysermc.connector.dump.BootstrapDumpInfo; import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.connector.utils.LanguageUtils; import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandExecutor; import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandManager; @@ -70,7 +72,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBungeeConfiguration.class); configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(new File(getDataFolder(), "config.yml")); } catch (IOException ex) { - getLogger().log(Level.WARNING, "Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex); + getLogger().log(Level.WARNING, LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex); ex.printStackTrace(); } @@ -92,7 +94,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); if (geyserConfig.getRemote().getAuthType().equals("floodgate") && getProxy().getPluginManager().getPlugin("floodgate-bungee") == null) { - geyserLogger.severe("Auth type set to Floodgate but Floodgate not found! Disabling..."); + geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.disabling")); return; } @@ -140,4 +142,9 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { public Path getConfigFolder() { return getDataFolder().toPath(); } + + @Override + public BootstrapDumpInfo getDumpInfo() { + return new GeyserBungeeDumpInfo(getProxy()); + } } diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java index d1c8473b..3b051c5c 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/command/GeyserBungeeCommandExecutor.java @@ -33,6 +33,8 @@ import net.md_5.bungee.api.plugin.TabExecutor; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.LanguageUtils; import java.util.ArrayList; import java.util.Arrays; @@ -52,7 +54,14 @@ public class GeyserBungeeCommandExecutor extends Command implements TabExecutor if (args.length > 0) { if (getCommand(args[0]) != null) { if (!sender.hasPermission(getCommand(args[0]).getPermission())) { - sender.sendMessage(TextComponent.fromLegacyText(ChatColor.RED + "You do not have permission to execute this command!")); + String message = ""; + if (sender instanceof GeyserSession) { + message = LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", ((GeyserSession) sender).getClientData().getLanguageCode()); + } else { + message = LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail"); + } + + sender.sendMessage(TextComponent.fromLegacyText(ChatColor.RED + message)); return; } getCommand(args[0]).execute(new BungeeCommandSender(sender), args); diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml index 6d12b673..85ede346 100644 --- a/bootstrap/pom.xml +++ b/bootstrap/pom.xml @@ -10,7 +10,7 @@ ../ bootstrap-parent - 1.0-SNAPSHOT + 1.0.0 pom @@ -35,8 +35,8 @@ - bukkit bungeecord + spigot sponge standalone velocity diff --git a/bootstrap/bukkit/pom.xml b/bootstrap/spigot/pom.xml similarity index 82% rename from bootstrap/bukkit/pom.xml rename to bootstrap/spigot/pom.xml index 95926854..e05ad7f0 100644 --- a/bootstrap/bukkit/pom.xml +++ b/bootstrap/spigot/pom.xml @@ -6,15 +6,15 @@ org.geysermc bootstrap-parent - 1.0-SNAPSHOT + 1.0.0 ../ - bootstrap-bukkit + bootstrap-spigot org.geysermc connector - 1.0-SNAPSHOT + 1.0.0 compile @@ -26,12 +26,12 @@ us.myles viaversion - 3.0.0-SNAPSHOT + 3.0.1 provided - ${outputName}-Bukkit + ${outputName}-Spigot src/main/resources/ @@ -46,7 +46,7 @@ - org.geysermc.platform.bukkit.GeyserBukkitMain + org.geysermc.platform.spigot.GeyserSpigotMain @@ -65,15 +65,19 @@ io.netty - org.geysermc.platform.bukkit.shaded.netty + org.geysermc.platform.spigot.shaded.netty it.unimi.dsi.fastutil - org.geysermc.platform.bukkit.shaded.fastutil + org.geysermc.platform.spigot.shaded.fastutil com.fasterxml.jackson - org.geysermc.platform.bukkit.shaded.jackson + org.geysermc.platform.spigot.shaded.jackson + + + org.reflections.reflections + org.geysermc.platform.spigot.shaded.reflections diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotConfiguration.java similarity index 93% rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotConfiguration.java index 327c41da..9a681156 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitConfiguration.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotConfiguration.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.platform.bukkit; +package org.geysermc.platform.spigot; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; @@ -38,14 +38,14 @@ import java.nio.file.Paths; @Getter @JsonIgnoreProperties(ignoreUnknown = true) -public class GeyserBukkitConfiguration extends GeyserJacksonConfiguration { +public class GeyserSpigotConfiguration extends GeyserJacksonConfiguration { @JsonProperty("floodgate-key-file") private String floodgateKeyFile; private Path floodgateKey; - public void loadFloodgate(GeyserBukkitPlugin plugin) { + public void loadFloodgate(GeyserSpigotPlugin plugin) { Plugin floodgate = Bukkit.getPluginManager().getPlugin("floodgate-bukkit"); floodgateKey = FloodgateKeyLoader.getKey(plugin.getGeyserLogger(), this, Paths.get(plugin.getDataFolder().toString(), plugin.getConfig().getString("floodgate-key-file", "public-key.pem")), floodgate, floodgate != null ? floodgate.getDataFolder().toPath() : null); } diff --git a/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotDumpInfo.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotDumpInfo.java new file mode 100644 index 00000000..01d513fa --- /dev/null +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotDumpInfo.java @@ -0,0 +1,62 @@ +/* + * 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.platform.spigot; + +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.geysermc.connector.dump.BootstrapDumpInfo; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public class GeyserSpigotDumpInfo extends BootstrapDumpInfo { + + private String platformName; + private String platformVersion; + private String platformAPIVersion; + private boolean onlineMode; + private String serverIP; + private int serverPort; + private List plugins; + + GeyserSpigotDumpInfo() { + super(); + this.platformName = Bukkit.getName(); + this.platformVersion = Bukkit.getVersion(); + this.platformAPIVersion = Bukkit.getBukkitVersion(); + this.onlineMode = Bukkit.getOnlineMode(); + this.serverIP = Bukkit.getIp(); + this.serverPort = Bukkit.getPort(); + this.plugins = new ArrayList<>(); + + for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { + this.plugins.add(new PluginInfo(plugin.isEnabled(), plugin.getName(), plugin.getDescription().getVersion(), plugin.getDescription().getMain(), plugin.getDescription().getAuthors())); + } + } +} diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitLogger.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotLogger.java similarity index 95% rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitLogger.java rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotLogger.java index 08822568..252d6bbe 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitLogger.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotLogger.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.platform.bukkit; +package org.geysermc.platform.spigot; import lombok.AllArgsConstructor; @@ -33,7 +33,7 @@ import java.util.logging.Level; import java.util.logging.Logger; @AllArgsConstructor -public class GeyserBukkitLogger implements GeyserLogger { +public class GeyserSpigotLogger implements GeyserLogger { private Logger logger; private boolean debugMode; diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitMain.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotMain.java similarity index 88% rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitMain.java rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotMain.java index b6da66c1..15826d33 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitMain.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotMain.java @@ -24,14 +24,14 @@ * */ -package org.geysermc.platform.bukkit; +package org.geysermc.platform.spigot; -import org.geysermc.common.main.IGeyserMain; +import org.geysermc.connector.common.main.IGeyserMain; -public class GeyserBukkitMain extends IGeyserMain { +public class GeyserSpigotMain extends IGeyserMain { public static void main(String[] args) { - new GeyserBukkitMain().displayMessage(); + new GeyserSpigotMain().displayMessage(); } public String getPluginType() { diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPingPassthrough.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPingPassthrough.java similarity index 79% rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPingPassthrough.java rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPingPassthrough.java index 812467be..9658a68d 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPingPassthrough.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPingPassthrough.java @@ -24,14 +24,15 @@ * */ -package org.geysermc.platform.bukkit; +package org.geysermc.platform.spigot; +import com.github.steveice10.mc.protocol.MinecraftConstants; import lombok.AllArgsConstructor; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.server.ServerListPingEvent; import org.bukkit.util.CachedServerIcon; -import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.common.ping.GeyserPingInfo; import org.geysermc.connector.ping.IGeyserPingPassthrough; import java.net.InetAddress; @@ -39,23 +40,24 @@ import java.util.Collections; import java.util.Iterator; @AllArgsConstructor -public class GeyserBukkitPingPassthrough implements IGeyserPingPassthrough { +public class GeyserSpigotPingPassthrough implements IGeyserPingPassthrough { - private final GeyserBukkitLogger logger; + private final GeyserSpigotLogger logger; @Override public GeyserPingInfo getPingInformation() { try { ServerListPingEvent event = new GeyserPingEvent(InetAddress.getLocalHost(), Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), Bukkit.getMaxPlayers()); Bukkit.getPluginManager().callEvent(event); - GeyserPingInfo geyserPingInfo = new GeyserPingInfo(event.getMotd(), event.getNumPlayers(), event.getMaxPlayers()); - Bukkit.getOnlinePlayers().forEach(player -> { - geyserPingInfo.addPlayer(player.getName()); - }); + GeyserPingInfo geyserPingInfo = new GeyserPingInfo(event.getMotd(), + new GeyserPingInfo.Players(event.getMaxPlayers(), event.getNumPlayers()), + new GeyserPingInfo.Version(Bukkit.getVersion(), MinecraftConstants.PROTOCOL_VERSION) // thanks Spigot for not exposing this, just default to latest + ); + Bukkit.getOnlinePlayers().stream().map(Player::getName).forEach(geyserPingInfo.getPlayerList()::add); return geyserPingInfo; } catch (Exception e) { logger.debug("Error while getting Bukkit ping passthrough: " + e.toString()); - return new GeyserPingInfo(null, 0, 0); + return new GeyserPingInfo(null, null, null); } } diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java similarity index 68% rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java index 3a13777b..38141c52 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/GeyserSpigotPlugin.java @@ -23,39 +23,41 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.platform.bukkit; +package org.geysermc.platform.spigot; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; -import org.geysermc.common.PlatformType; +import org.geysermc.connector.common.PlatformType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.configuration.GeyserConfiguration; +import org.geysermc.connector.dump.BootstrapDumpInfo; import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.utils.FileUtils; -import org.geysermc.platform.bukkit.command.GeyserBukkitCommandExecutor; -import org.geysermc.platform.bukkit.command.GeyserBukkitCommandManager; -import org.geysermc.platform.bukkit.world.GeyserBukkitBlockPlaceListener; -import org.geysermc.platform.bukkit.world.GeyserBukkitWorldManager; -import us.myles.ViaVersion.api.Via; +import org.geysermc.connector.utils.LanguageUtils; +import org.geysermc.platform.spigot.command.GeyserSpigotCommandExecutor; +import org.geysermc.platform.spigot.command.GeyserSpigotCommandManager; +import org.geysermc.platform.spigot.world.GeyserSpigotBlockPlaceListener; +import org.geysermc.platform.spigot.world.GeyserSpigotWorldManager; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.UUID; import java.util.logging.Level; -public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { +public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { - private GeyserBukkitCommandManager geyserCommandManager; - private GeyserBukkitConfiguration geyserConfig; - private GeyserBukkitLogger geyserLogger; - private IGeyserPingPassthrough geyserBukkitPingPassthrough; - private GeyserBukkitBlockPlaceListener blockPlaceListener; - private GeyserBukkitWorldManager geyserWorldManager; + private GeyserSpigotCommandManager geyserCommandManager; + private GeyserSpigotConfiguration geyserConfig; + private GeyserSpigotLogger geyserLogger; + private IGeyserPingPassthrough geyserSpigotPingPassthrough; + private GeyserSpigotBlockPlaceListener blockPlaceListener; + private GeyserSpigotWorldManager geyserWorldManager; private GeyserConnector connector; @@ -63,12 +65,19 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { public void onEnable() { // This is manually done instead of using Bukkit methods to save the config because otherwise comments get removed try { - if (!getDataFolder().exists()) + if (!getDataFolder().exists()) { getDataFolder().mkdir(); + File bukkitConfig = new File("plugins/Geyser-Bukkit/config.yml"); + if (bukkitConfig.exists()) { // Copy over old configs + getLogger().log(Level.INFO, LanguageUtils.getLocaleStringLog("geyser.bootstrap.config.copy_bukkit_config")); + Files.copy(bukkitConfig.toPath(), new File(getDataFolder().toString() + "/config.yml").toPath()); + getLogger().log(Level.INFO, LanguageUtils.getLocaleStringLog("geyser.bootstrap.config.copied_bukkit_config")); + } + } File configFile = FileUtils.fileOrCopiedFromResource(new File(getDataFolder(), "config.yml"), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString())); - this.geyserConfig = FileUtils.loadConfig(configFile, GeyserBukkitConfiguration.class); + this.geyserConfig = FileUtils.loadConfig(configFile, GeyserSpigotConfiguration.class); } catch (IOException ex) { - getLogger().log(Level.WARNING, "Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex); + getLogger().log(Level.WARNING, LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex); ex.printStackTrace(); } @@ -80,48 +89,39 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { geyserConfig.getRemote().setPort(Bukkit.getPort()); - this.geyserLogger = new GeyserBukkitLogger(getLogger(), geyserConfig.isDebugMode()); + this.geyserLogger = new GeyserSpigotLogger(getLogger(), geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); if (geyserConfig.getRemote().getAuthType().equals("floodgate") && Bukkit.getPluginManager().getPlugin("floodgate-bukkit") == null) { - geyserLogger.severe("Auth type set to Floodgate but Floodgate not found! Disabling..."); + geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.disabling")); this.getPluginLoader().disablePlugin(this); return; } geyserConfig.loadFloodgate(this); - this.connector = GeyserConnector.start(PlatformType.BUKKIT, this); + this.connector = GeyserConnector.start(PlatformType.SPIGOT, this); if (geyserConfig.isLegacyPingPassthrough()) { - this.geyserBukkitPingPassthrough = GeyserLegacyPingPassthrough.init(connector); + this.geyserSpigotPingPassthrough = GeyserLegacyPingPassthrough.init(connector); } else { - this.geyserBukkitPingPassthrough = new GeyserBukkitPingPassthrough(geyserLogger); + this.geyserSpigotPingPassthrough = new GeyserSpigotPingPassthrough(geyserLogger); } - this.geyserCommandManager = new GeyserBukkitCommandManager(this, connector); + this.geyserCommandManager = new GeyserSpigotCommandManager(this, connector); - boolean isViaVersion = false; + boolean isViaVersion = (Bukkit.getPluginManager().getPlugin("ViaVersion") != null); // Used to determine if Block.getBlockData() is present. boolean isLegacy = !isCompatible(Bukkit.getServer().getVersion(), "1.13.0"); if (isLegacy) geyserLogger.debug("Legacy version of Minecraft (1.12.2 or older) detected."); - if (Bukkit.getPluginManager().getPlugin("ViaVersion") != null) { - // TODO: Update when ViaVersion updates - // API changes between 2.2.3 and 3.0.0-SNAPSHOT require this check - if (!Via.getAPI().getVersion().equals("3.0.0-SNAPSHOT") && isLegacy) { - geyserLogger.info("ViaVersion detected but not ViaVersion-ABSTRACTION. Please update your ViaVersion plugin for compatibility with Geyser."); - } else { - isViaVersion = true; - } - } + this.geyserWorldManager = new GeyserSpigotWorldManager(isLegacy, isViaVersion); + this.blockPlaceListener = new GeyserSpigotBlockPlaceListener(connector, isLegacy, isViaVersion); - this.geyserWorldManager = new GeyserBukkitWorldManager(isLegacy, isViaVersion); - this.blockPlaceListener = new GeyserBukkitBlockPlaceListener(connector, isLegacy, isViaVersion); Bukkit.getServer().getPluginManager().registerEvents(blockPlaceListener, this); - this.getCommand("geyser").setExecutor(new GeyserBukkitCommandExecutor(connector)); + this.getCommand("geyser").setExecutor(new GeyserSpigotCommandExecutor(connector)); } @Override @@ -131,12 +131,12 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { } @Override - public GeyserBukkitConfiguration getGeyserConfig() { + public GeyserSpigotConfiguration getGeyserConfig() { return geyserConfig; } @Override - public GeyserBukkitLogger getGeyserLogger() { + public GeyserSpigotLogger getGeyserLogger() { return geyserLogger; } @@ -147,7 +147,7 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { @Override public IGeyserPingPassthrough getGeyserPingPassthrough() { - return geyserBukkitPingPassthrough; + return geyserSpigotPingPassthrough; } @Override @@ -194,4 +194,8 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { return temp; } + @Override + public BootstrapDumpInfo getDumpInfo() { + return new GeyserSpigotDumpInfo(); + } } diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandExecutor.java similarity index 74% rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandExecutor.java index d2603f7c..38187275 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandExecutor.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandExecutor.java @@ -23,23 +23,24 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.platform.bukkit.command; +package org.geysermc.platform.spigot.command; import lombok.AllArgsConstructor; - import org.bukkit.ChatColor; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.LanguageUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @AllArgsConstructor -public class GeyserBukkitCommandExecutor implements TabExecutor { +public class GeyserSpigotCommandExecutor implements TabExecutor { private GeyserConnector connector; @@ -48,14 +49,21 @@ public class GeyserBukkitCommandExecutor implements TabExecutor { if (args.length > 0) { if (getCommand(args[0]) != null) { if (!sender.hasPermission(getCommand(args[0]).getPermission())) { - sender.sendMessage(ChatColor.RED + "You do not have permission to execute this command!"); + String message = ""; + if (sender instanceof GeyserSession) { + message = LanguageUtils.getPlayerLocaleString("geyser.bootstrap.command.permission_fail", ((GeyserSession) sender).getClientData().getLanguageCode()); + } else { + message = LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail"); + } + + sender.sendMessage(ChatColor.RED + message); return true; } - getCommand(args[0]).execute(new BukkitCommandSender(sender), args); + getCommand(args[0]).execute(new SpigotCommandSender(sender), args); return true; } } else { - getCommand("help").execute(new BukkitCommandSender(sender), args); + getCommand("help").execute(new SpigotCommandSender(sender), args); return true; } return true; diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandManager.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandManager.java similarity index 88% rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandManager.java rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandManager.java index b826ab1f..2fbec156 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/GeyserBukkitCommandManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/GeyserSpigotCommandManager.java @@ -23,18 +23,18 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.platform.bukkit.command; +package org.geysermc.platform.spigot.command; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandMap; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandManager; -import org.geysermc.platform.bukkit.GeyserBukkitPlugin; +import org.geysermc.platform.spigot.GeyserSpigotPlugin; import java.lang.reflect.Field; -public class GeyserBukkitCommandManager extends CommandManager { +public class GeyserSpigotCommandManager extends CommandManager { private static CommandMap COMMAND_MAP; @@ -48,9 +48,9 @@ public class GeyserBukkitCommandManager extends CommandManager { } } - private GeyserBukkitPlugin plugin; + private GeyserSpigotPlugin plugin; - public GeyserBukkitCommandManager(GeyserBukkitPlugin plugin, GeyserConnector connector) { + public GeyserSpigotCommandManager(GeyserSpigotPlugin plugin, GeyserConnector connector) { super(connector); this.plugin = plugin; diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/BukkitCommandSender.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/SpigotCommandSender.java similarity index 94% rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/BukkitCommandSender.java rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/SpigotCommandSender.java index 05e371e5..55475a30 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/command/BukkitCommandSender.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/command/SpigotCommandSender.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.platform.bukkit.command; +package org.geysermc.platform.spigot.command; import lombok.AllArgsConstructor; @@ -31,7 +31,7 @@ import org.bukkit.command.ConsoleCommandSender; import org.geysermc.connector.command.CommandSender; @AllArgsConstructor -public class BukkitCommandSender implements CommandSender { +public class SpigotCommandSender implements CommandSender { private org.bukkit.command.CommandSender handle; diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotBlockPlaceListener.java similarity index 93% rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotBlockPlaceListener.java index 76d1564e..4fe93d45 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitBlockPlaceListener.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotBlockPlaceListener.java @@ -24,7 +24,7 @@ * */ -package org.geysermc.platform.bukkit.world; +package org.geysermc.platform.spigot.world; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.SoundEvent; @@ -39,7 +39,7 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.block.BlockTranslator; @AllArgsConstructor -public class GeyserBukkitBlockPlaceListener implements Listener { +public class GeyserSpigotBlockPlaceListener implements Listener { private final GeyserConnector connector; private final boolean isLegacy; @@ -47,7 +47,7 @@ public class GeyserBukkitBlockPlaceListener implements Listener { @EventHandler public void place(final BlockPlaceEvent event) { - for (GeyserSession session : connector.getPlayers().values()) { + for (GeyserSession session : connector.getPlayers()) { if (event.getPlayer() == Bukkit.getPlayer(session.getPlayerEntity().getUsername())) { LevelSoundEventPacket placeBlockSoundPacket = new LevelSoundEventPacket(); placeBlockSoundPacket.setSound(SoundEvent.PLACE); @@ -55,7 +55,7 @@ public class GeyserBukkitBlockPlaceListener implements Listener { placeBlockSoundPacket.setBabySound(false); String javaBlockId; if (isLegacy) { - javaBlockId = BlockTranslator.getJavaIdBlockMap().inverse().get(GeyserBukkitWorldManager.getLegacyBlock(session, + javaBlockId = BlockTranslator.getJavaIdBlockMap().inverse().get(GeyserSpigotWorldManager.getLegacyBlock(session, event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ(), isViaVersion)); } else { javaBlockId = event.getBlockPlaced().getBlockData().getAsString(); diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotWorldManager.java similarity index 83% rename from bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java rename to bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotWorldManager.java index fbdf2a47..d785fabc 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/world/GeyserBukkitWorldManager.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/platform/spigot/world/GeyserSpigotWorldManager.java @@ -24,23 +24,19 @@ * */ -package org.geysermc.platform.bukkit.world; - -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +package org.geysermc.platform.spigot.world; import lombok.AllArgsConstructor; -import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.block.Block; 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 org.geysermc.platform.bukkit.GeyserBukkitPlugin; import us.myles.ViaVersion.protocols.protocol1_13_1to1_13.Protocol1_13_1To1_13; -import us.myles.ViaVersion.protocols.protocol1_15to1_14_4.data.MappingData; +import us.myles.ViaVersion.protocols.protocol1_16to1_15_2.data.MappingData; @AllArgsConstructor -public class GeyserBukkitWorldManager extends WorldManager { +public class GeyserSpigotWorldManager extends WorldManager { private final boolean isLegacy; // You need ViaVersion to connect to an older server with Geyser. @@ -48,7 +44,7 @@ public class GeyserBukkitWorldManager extends WorldManager { private final boolean isViaVersion; @Override - public BlockState getBlockAt(GeyserSession session, int x, int y, int z) { + public int getBlockAt(GeyserSession session, int x, int y, int z) { if (session.getPlayerEntity() == null) { return BlockTranslator.AIR; } @@ -59,16 +55,17 @@ public class GeyserBukkitWorldManager extends WorldManager { } @SuppressWarnings("deprecation") - public static BlockState getLegacyBlock(GeyserSession session, int x, int y, int z, boolean isViaVersion) { + public static int getLegacyBlock(GeyserSession session, int x, int y, int z, boolean isViaVersion) { if (isViaVersion) { Block block = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().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 + // Convert block state from old version -> 1.13 -> 1.13.1 -> 1.14 -> 1.15 -> 1.16 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); - return new BlockState(MappingData.blockStateMappings.getNewId(fourteenBlockId)); + int fifteenBlockId = us.myles.ViaVersion.protocols.protocol1_15to1_14_4.data.MappingData.blockStateMappings.getNewId(fourteenBlockId); + return MappingData.blockStateMappings.getNewId(fifteenBlockId); } else { return BlockTranslator.AIR; } diff --git a/bootstrap/bukkit/src/main/resources/plugin.yml b/bootstrap/spigot/src/main/resources/plugin.yml similarity index 67% rename from bootstrap/bukkit/src/main/resources/plugin.yml rename to bootstrap/spigot/src/main/resources/plugin.yml index 89c90789..fee71ab1 100644 --- a/bootstrap/bukkit/src/main/resources/plugin.yml +++ b/bootstrap/spigot/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ -main: org.geysermc.platform.bukkit.GeyserBukkitPlugin -name: ${outputName}-Bukkit +main: org.geysermc.platform.spigot.GeyserSpigotPlugin +name: ${outputName}-Spigot author: ${project.organization.name} website: ${project.organization.url} version: ${project.version} diff --git a/bootstrap/sponge/pom.xml b/bootstrap/sponge/pom.xml index c9abbe3e..cca3fcaa 100644 --- a/bootstrap/sponge/pom.xml +++ b/bootstrap/sponge/pom.xml @@ -6,7 +6,7 @@ org.geysermc bootstrap-parent - 1.0-SNAPSHOT + 1.0.0 ../ bootstrap-sponge @@ -14,7 +14,7 @@ org.geysermc connector - 1.0-SNAPSHOT + 1.0.0 compile @@ -69,6 +69,10 @@ it.unimi.dsi.fastutil org.geysermc.platform.sponge.shaded.fastutil + + org.reflections.reflections + org.geysermc.platform.sponge.shaded.reflections + diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeDumpInfo.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeDumpInfo.java new file mode 100644 index 00000000..e8f0feae --- /dev/null +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeDumpInfo.java @@ -0,0 +1,63 @@ +/* + * 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.platform.sponge; + +import lombok.Getter; +import org.geysermc.connector.dump.BootstrapDumpInfo; +import org.spongepowered.api.Platform; +import org.spongepowered.api.Sponge; +import org.spongepowered.api.plugin.PluginContainer; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public class GeyserSpongeDumpInfo extends BootstrapDumpInfo { + + private String platformName; + private String platformVersion; + private boolean onlineMode; + private String serverIP; + private int serverPort; + private List plugins; + + GeyserSpongeDumpInfo() { + super(); + PluginContainer container = Sponge.getPlatform().getContainer(Platform.Component.IMPLEMENTATION); + this.platformName = container.getName(); + this.platformVersion = container.getVersion().get(); + this.onlineMode = Sponge.getServer().getOnlineMode(); + this.serverIP = Sponge.getServer().getBoundAddress().get().getHostString(); + this.serverPort = Sponge.getServer().getBoundAddress().get().getPort(); + this.plugins = new ArrayList<>(); + + for (PluginContainer plugin : Sponge.getPluginManager().getPlugins()) { + String pluginClass = plugin.getInstance().map((pl) -> pl.getClass().getName()).orElse("unknown"); + this.plugins.add(new PluginInfo(true, plugin.getName(), plugin.getVersion().get(), pluginClass, plugin.getAuthors())); + } + } +} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java index 11b9583f..1c9605d0 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeMain.java @@ -26,7 +26,7 @@ package org.geysermc.platform.sponge; -import org.geysermc.common.main.IGeyserMain; +import org.geysermc.connector.common.main.IGeyserMain; public class GeyserSpongeMain extends IGeyserMain { diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java index 31b6dc7f..862c744b 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePingPassthrough.java @@ -26,7 +26,8 @@ package org.geysermc.platform.sponge; -import org.geysermc.common.ping.GeyserPingInfo; +import com.github.steveice10.mc.protocol.MinecraftConstants; +import org.geysermc.connector.common.ping.GeyserPingInfo; import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.spongepowered.api.MinecraftVersion; import org.spongepowered.api.Sponge; @@ -35,6 +36,7 @@ import org.spongepowered.api.event.cause.Cause; import org.spongepowered.api.event.cause.EventContext; import org.spongepowered.api.event.server.ClientPingServerEvent; import org.spongepowered.api.network.status.StatusClient; +import org.spongepowered.api.profile.GameProfile; import java.lang.reflect.Method; import java.net.Inet4Address; @@ -68,11 +70,18 @@ public class GeyserSpongePingPassthrough implements IGeyserPingPassthrough { Sponge.getEventManager().post(event); GeyserPingInfo geyserPingInfo = new GeyserPingInfo( event.getResponse().getDescription().toPlain(), - event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getOnline(), - event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getMax()); - event.getResponse().getPlayers().get().getProfiles().forEach(player -> { - geyserPingInfo.addPlayer(player.getName().orElseThrow(IllegalStateException::new)); - }); + new GeyserPingInfo.Players( + event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getMax(), + event.getResponse().getPlayers().orElseThrow(IllegalStateException::new).getOnline() + ), + new GeyserPingInfo.Version( + event.getResponse().getVersion().getName(), + MinecraftConstants.PROTOCOL_VERSION) // thanks for also not exposing this sponge + ); + event.getResponse().getPlayers().get().getProfiles().stream() + .map(GameProfile::getName) + .map(op -> op.orElseThrow(IllegalStateException::new)) + .forEach(geyserPingInfo.getPlayerList()::add); return geyserPingInfo; } 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 c5f13b58..3151e973 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 @@ -29,14 +29,16 @@ import com.google.inject.Inject; import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.loader.ConfigurationLoader; import ninja.leaping.configurate.yaml.YAMLConfigurationLoader; -import org.geysermc.common.PlatformType; +import org.geysermc.connector.common.PlatformType; import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; +import org.geysermc.connector.dump.BootstrapDumpInfo; import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.connector.utils.LanguageUtils; import org.geysermc.platform.sponge.command.GeyserSpongeCommandExecutor; import org.geysermc.platform.sponge.command.GeyserSpongeCommandManager; import org.slf4j.Logger; @@ -79,7 +81,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap { try { configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml", (file) -> file.replaceAll("generateduuid", UUID.randomUUID().toString())); } catch (IOException ex) { - logger.warn("Failed to copy config.yml from jar path!"); + logger.warn(LanguageUtils.getLocaleStringLog("geyser.config.failed")); ex.printStackTrace(); } @@ -89,7 +91,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap { config = loader.load(); this.geyserConfig = new GeyserSpongeConfiguration(configDir, config); } catch (IOException ex) { - logger.warn("Failed to load config.yml!"); + logger.warn(LanguageUtils.getLocaleStringLog("geyser.config.failed")); ex.printStackTrace(); return; } @@ -162,4 +164,9 @@ public class GeyserSpongePlugin implements GeyserBootstrap { public void onServerStop(GameStoppedEvent event) { onDisable(); } + + @Override + public BootstrapDumpInfo getDumpInfo() { + return new GeyserSpongeDumpInfo(); + } } diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java index 91cb59b0..d37321ff 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/command/GeyserSpongeCommandExecutor.java @@ -26,10 +26,10 @@ package org.geysermc.platform.sponge.command; import lombok.AllArgsConstructor; - -import org.geysermc.common.ChatColor; import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.common.ChatColor; import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.utils.LanguageUtils; import org.spongepowered.api.command.CommandCallable; import org.spongepowered.api.command.CommandException; import org.spongepowered.api.command.CommandResult; @@ -55,7 +55,8 @@ public class GeyserSpongeCommandExecutor implements CommandCallable { if (args.length > 0) { if (getCommand(args[0]) != null) { if (!source.hasPermission(getCommand(args[0]).getPermission())) { - source.sendMessage(Text.of(ChatColor.RED + "You do not have permission to execute this command!")); + // Not ideal to use log here but we dont get a session + source.sendMessage(Text.of(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail"))); return CommandResult.success(); } getCommand(args[0]).execute(new SpongeCommandSender(source), args); diff --git a/bootstrap/standalone/pom.xml b/bootstrap/standalone/pom.xml index df75f753..468042b8 100644 --- a/bootstrap/standalone/pom.xml +++ b/bootstrap/standalone/pom.xml @@ -6,7 +6,7 @@ org.geysermc bootstrap-parent - 1.0-SNAPSHOT + 1.0.0 ../ bootstrap-standalone @@ -14,13 +14,13 @@ org.geysermc connector - 1.0-SNAPSHOT + 1.0.0 compile net.minecrell terminalconsoleappender - 1.1.1 + 1.2.0 org.apache.logging.log4j 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 0fca3503..5da4c37d 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,15 +25,24 @@ package org.geysermc.platform.standalone; -import org.geysermc.common.PlatformType; +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.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; -import org.geysermc.connector.configuration.GeyserConfiguration; +import org.geysermc.connector.common.PlatformType; import org.geysermc.connector.command.CommandManager; -import org.geysermc.connector.ping.IGeyserPingPassthrough; +import org.geysermc.connector.configuration.GeyserConfiguration; +import org.geysermc.connector.dump.BootstrapDumpInfo; import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; +import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.connector.utils.LanguageUtils; import org.geysermc.platform.standalone.command.GeyserCommandManager; +import org.geysermc.platform.standalone.gui.GeyserStandaloneGUI; import java.io.File; import java.io.IOException; @@ -48,14 +57,49 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { private GeyserStandaloneLogger geyserLogger; private IGeyserPingPassthrough geyserPingPassthrough; + private GeyserStandaloneGUI gui; + + @Getter + private boolean useGui = System.console() == null; + private GeyserConnector connector; public static void main(String[] args) { + for (String arg : args) { + // 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 + if (arg.equals("gui")) { + new GeyserStandaloneBootstrap().onEnable(true); + return; + } else if (arg.equals("nogui")) { + new GeyserStandaloneBootstrap().onEnable(false); + return; + } + } new GeyserStandaloneBootstrap().onEnable(); } + public void onEnable(boolean useGui) { + this.useGui = useGui; + this.onEnable(); + } + @Override public void onEnable() { + Logger logger = (Logger) LogManager.getRootLogger(); + for (Appender appender : logger.getAppenders().values()) { + // Remove the appender that is not in use + // Prevents multiple appenders/double logging and removes harmless errors + if ((useGui && appender instanceof TerminalConsoleAppender) || (!useGui && appender instanceof ConsoleAppender)) { + logger.removeAppender(appender); + } + } + if (useGui && gui == null) { + gui = new GeyserStandaloneGUI(); + gui.redirectSystemStreams(); + gui.startUpdateThread(); + } + geyserLogger = new GeyserStandaloneLogger(); LoopbackUtil.checkLoopback(geyserLogger); @@ -64,7 +108,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { File configFile = FileUtils.fileOrCopiedFromResource("config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString())); geyserConfig = FileUtils.loadConfig(configFile, GeyserStandaloneConfiguration.class); } catch (IOException ex) { - geyserLogger.severe("Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex); + geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex); System.exit(0); } GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); @@ -72,9 +116,15 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { connector = GeyserConnector.start(PlatformType.STANDALONE, this); geyserCommandManager = new GeyserCommandManager(connector); + if (gui != null) { + gui.setupInterface(geyserLogger, geyserCommandManager); + } + geyserPingPassthrough = GeyserLegacyPingPassthrough.init(connector); - geyserLogger.start(); + if (!useGui) { + geyserLogger.start(); // Throws an error otherwise + } } @Override @@ -108,4 +158,9 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { // Return the current working directory return Paths.get(System.getProperty("user.dir")); } + + @Override + public BootstrapDumpInfo getDumpInfo() { + return new BootstrapDumpInfo(); + } } diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java index 7102d206..ffc322dd 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java @@ -30,8 +30,9 @@ import lombok.extern.log4j.Log4j2; import net.minecrell.terminalconsole.SimpleTerminalConsole; +import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.config.Configurator; -import org.geysermc.common.ChatColor; +import org.geysermc.connector.common.ChatColor; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; @@ -96,7 +97,15 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements org @Override public void setDebug(boolean debug) { - Configurator.setLevel(log.getName(), debug ? org.apache.logging.log4j.Level.DEBUG : log.getLevel()); + Configurator.setLevel(log.getName(), debug ? Level.DEBUG : Level.INFO); + } + + /** + * Used for setting debug mode in GUI mode + * @return if debug is enabled + */ + public boolean isDebug() { + return log.isDebugEnabled(); } @Override diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java index 03c49705..8c54d141 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/LoopbackUtil.java @@ -1,12 +1,13 @@ package org.geysermc.platform.standalone; +import org.geysermc.connector.common.ChatColor; +import org.geysermc.connector.utils.LanguageUtils; + import java.io.InputStream; import java.nio.file.Files; import java.nio.file.OpenOption; import java.nio.file.Paths; -import org.geysermc.common.ChatColor; - public class LoopbackUtil { private static final String checkExemption = "powershell -Command \"CheckNetIsolation LoopbackExempt -s\""; // Java's Exec feature runs as CMD, NetIsolation is only accessible from PowerShell. private static final String loopbackCommand = "powershell -Command \"CheckNetIsolation LoopbackExempt -a -n='Microsoft.MinecraftUWP_8wekyb3d8bbwe'\""; @@ -31,12 +32,12 @@ public class LoopbackUtil { Files.write(Paths.get(System.getenv("temp") + "/loopback_minecraft.bat"), loopbackCommand.getBytes(), new OpenOption[0]); process = Runtime.getRuntime().exec(startScript); - geyserLogger.info(ChatColor.AQUA + "Added loopback exemption to Windows!"); + geyserLogger.info(ChatColor.AQUA + LanguageUtils.getLocaleStringLog("geyser.bootstrap.loopback.added")); } } catch (Exception e) { e.printStackTrace(); - geyserLogger.error("Couldn't auto add loopback exemption to Windows!"); + geyserLogger.error(LanguageUtils.getLocaleStringLog("geyser.bootstrap.loopback.failed")); } } } diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ANSIColor.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ANSIColor.java new file mode 100644 index 00000000..1f4ff998 --- /dev/null +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ANSIColor.java @@ -0,0 +1,79 @@ +/* + * 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.platform.standalone.gui; + +import lombok.Getter; + +import java.awt.*; +import java.util.regex.Pattern; + +public enum ANSIColor { + // Normal colors + BLACK("(0;)?30(0;)?m", Color.getHSBColor(0.000f, 0.000f, 0.000f)), + RED("(0;)?31(0;)?m", Color.getHSBColor(0.000f, 1.000f, 0.502f)), + GREEN("(0;)?32(0;)?m", Color.getHSBColor(0.333f, 1.000f, 0.502f)), + YELLOW("(0;)?33(0;)?m", Color.getHSBColor(0.167f, 1.000f, 0.502f)), + BLUE("(0;)?34(0;)?m", Color.getHSBColor(0.667f, 1.000f, 0.502f)), + MAGENTA("(0;)?35(0;)?m", Color.getHSBColor(0.833f, 1.000f, 0.502f)), + CYAN("(0;)?36(0;)?m", Color.getHSBColor(0.500f, 1.000f, 0.502f)), + WHITE("(0;)?37(0;)?m", Color.getHSBColor(0.000f, 0.000f, 0.753f)), + + // Bold colors + B_BLACK("(1;30|30;1)m", Color.getHSBColor(0.000f, 0.000f, 0.502f)), + B_RED("(1;31|31;1)m", Color.getHSBColor(0.000f, 1.000f, 1.000f)), + B_GREEN("(1;32|32;1)m", Color.getHSBColor(0.333f, 1.000f, 1.000f)), + B_YELLOW("(1;33|33;1)m", Color.getHSBColor(0.167f, 1.000f, 1.000f)), + B_BLUE("(1;34|34;1)m", Color.getHSBColor(0.667f, 1.000f, 1.000f)), + B_MAGENTA("(1;35|35;1)m", Color.getHSBColor(0.833f, 1.000f, 1.000f)), + B_CYAN("(1;36|36;1)m", Color.getHSBColor(0.500f, 1.000f, 1.000f)), + B_WHITE("(1;37|37;1)m", Color.getHSBColor(0.000f, 0.000f, 1.000f)), + + RESET("0m", Color.getHSBColor(0.000f, 0.000f, 1.000f)); + + private static final ANSIColor[] VALUES = values(); + private static final String PREFIX = Pattern.quote("\u001B["); + + private final String ANSICode; + + @Getter + private final Color color; + + ANSIColor(String ANSICode, Color color) { + this.ANSICode = ANSICode; + this.color = color; + } + + public static ANSIColor fromANSI(String code) { + for (ANSIColor value : VALUES) { + if (code.matches(PREFIX + value.ANSICode)) { + return value; + } + } + + return B_WHITE; + } +} diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ColorPane.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ColorPane.java new file mode 100644 index 00000000..f4586bbb --- /dev/null +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/ColorPane.java @@ -0,0 +1,118 @@ +/* + * 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.platform.standalone.gui; + +import javax.swing.*; +import javax.swing.text.*; +import java.awt.*; + +/** + * This class was based on this code: https://stackoverflow.com/a/6899478/5299903 + */ +public class ColorPane extends JTextPane { + private static Color colorCurrent = ANSIColor.RESET.getColor(); + private String remaining = ""; + + /** + * Append the given string in the given color to the text pane + * @param c The color + * @param s The text + */ + private void append(Color c, String s) { + StyleContext sc = StyleContext.getDefaultStyleContext(); + AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c); + int len = getDocument().getLength(); + + try { + getDocument().insertString(len, s, aset); + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** + * Extract the ANSI color codes from the string and add each part to the text pane + * + * @param s The text to parse + */ + public void appendANSI(String s) { // convert ANSI color codes first + int aPos = 0; // current char position in addString + int aIndex = 0; // index of next Escape sequence + int mIndex = 0; // index of "m" terminating Escape sequence + String tmpString = ""; + boolean stillSearching = true; // true until no more Escape sequences + String addString = remaining + s; + remaining = ""; + + if (addString.length() > 0) { + aIndex = addString.indexOf("\u001B"); // find first escape + if (aIndex == -1) { // no escape/color change in this string, so just send it with current color + append(colorCurrent, addString); + return; + } + // otherwise There is an escape character in the string, so we must process it + + if (aIndex > 0) { // Escape is not first char, so send text up to first escape + tmpString = addString.substring(0, aIndex); + append(colorCurrent, tmpString); + aPos = aIndex; // aPos is now at the beginning of the first escape sequence + } + + + // while there's text in the input buffer + stillSearching = true; + while (stillSearching) { + mIndex = addString.indexOf("m", aPos); // find the end of the escape sequence + if (mIndex < 0) { // the buffer ends halfway through the ansi string! + remaining = addString.substring(aPos, addString.length()); + stillSearching = false; + continue; + } else { + tmpString = addString.substring(aPos, mIndex+1); + colorCurrent = ANSIColor.fromANSI(tmpString).getColor(); + } + aPos = mIndex + 1; + // now we have the color, send text that is in that color (up to next escape) + + aIndex = addString.indexOf("\u001B", aPos); + + if (aIndex == -1) { // if that was the last sequence of the input, send remaining text + tmpString = addString.substring(aPos, addString.length()); + append(colorCurrent, tmpString); + stillSearching = false; + continue; // jump out of loop early, as the whole string has been sent now + } + + // there is another escape sequence, so send part of the string and prepare for the next + tmpString = addString.substring(aPos, aIndex); + aPos = aIndex; + append(colorCurrent, tmpString); + + } + } + } +} diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GeyserStandaloneGUI.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GeyserStandaloneGUI.java new file mode 100644 index 00000000..0c0ec112 --- /dev/null +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GeyserStandaloneGUI.java @@ -0,0 +1,340 @@ +/* + * 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.platform.standalone.gui; + +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.LanguageUtils; +import org.geysermc.platform.standalone.GeyserStandaloneLogger; +import org.geysermc.platform.standalone.command.GeyserCommandManager; + +import javax.swing.*; +import javax.swing.table.DefaultTableModel; +import javax.swing.text.Document; +import java.awt.*; +import java.awt.event.*; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Vector; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class GeyserStandaloneGUI { + + private static final DefaultTableModel playerTableModel = new DefaultTableModel(); + private static final List ramValues = new ArrayList<>(); + + private static final ColorPane consolePane = new ColorPane(); + private static final GraphPanel ramGraph = new GraphPanel(); + private static final JTable playerTable = new JTable(playerTableModel); + private static final int originalFontSize = consolePane.getFont().getSize(); + + private static final long MEGABYTE = 1024L * 1024L; + + private final JMenu commandsMenu; + private final JMenu optionsMenu; + + public GeyserStandaloneGUI() { + // Create the frame and setup basic settings + JFrame frame = new JFrame(LanguageUtils.getLocaleStringLog("geyser.gui.title")); + frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + frame.setSize(800, 400); + frame.setMinimumSize(frame.getSize()); + + // Remove Java UI look + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception ignored) { } + + // Show a confirm dialog on close + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent we) + { + String[] buttons = {LanguageUtils.getLocaleStringLog("geyser.gui.exit.confirm"), LanguageUtils.getLocaleStringLog("geyser.gui.exit.deny")}; + int result = JOptionPane.showOptionDialog(frame, LanguageUtils.getLocaleStringLog("geyser.gui.exit.message"), frame.getTitle(), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, buttons, buttons[1]); + if (result == JOptionPane.YES_OPTION) { + System.exit(0); + } + } + }); + + Container cp = frame.getContentPane(); + + // Fetch and set the icon for the frame + URL image = getClass().getClassLoader().getResource("icon.png"); + if (image != null) { + ImageIcon icon = new ImageIcon(image); + frame.setIconImage(icon.getImage()); + } + + // Setup the split pane and event listeners + JSplitPane splitPane = new JSplitPane(); + splitPane.setDividerLocation(600); + splitPane.addPropertyChangeListener("dividerLocation", e -> splitPaneLimit((JSplitPane)e.getSource())); + splitPane.addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent e) { + splitPaneLimit((JSplitPane)e.getSource()); + } + }); + + cp.add(splitPane, BorderLayout.CENTER); + + // Set the background and disable input for the text pane + consolePane.setBackground(Color.BLACK); + consolePane.setEditable(false); + + // Wrap the text pane in a scroll pane and add it to the form + JScrollPane consoleScrollPane = new JScrollPane(consolePane); + //cp.add(consoleScrollPane, BorderLayout.CENTER); + splitPane.setLeftComponent(consoleScrollPane); + + // Create a new menu bar for the top of the frame + JMenuBar menuBar = new JMenuBar(); + + // Create 'File' + JMenu fileMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.file")); + fileMenu.setMnemonic(KeyEvent.VK_F); + menuBar.add(fileMenu); + + // 'Open Geyser folder' button + JMenuItem openButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.file.open_folder"), KeyEvent.VK_O); + openButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); + openButton.addActionListener(e -> { + try { + Desktop.getDesktop().open(new File("./")); + } catch (IOException ignored) { } + }); + fileMenu.add(openButton); + + fileMenu.addSeparator(); + + // 'Exit' button + JMenuItem exitButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.file.exit"), KeyEvent.VK_X); + exitButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, InputEvent.ALT_MASK)); + exitButton.addActionListener(e -> System.exit(0)); + fileMenu.add(exitButton); + + // Create 'Commands' + commandsMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.commands")); + commandsMenu.setMnemonic(KeyEvent.VK_C); + menuBar.add(commandsMenu); + + // Create 'View' + JMenu viewMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view")); + viewMenu.setMnemonic(KeyEvent.VK_V); + menuBar.add(viewMenu); + + // 'Zoom in' button + JMenuItem zoomInButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view.zoom_in")); + zoomInButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, InputEvent.CTRL_DOWN_MASK)); + zoomInButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), consolePane.getFont().getSize() + 1))); + viewMenu.add(zoomInButton); + + // 'Zoom in' button + JMenuItem zoomOutButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view.zoom_out")); + zoomOutButton.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.CTRL_DOWN_MASK)); + zoomOutButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), consolePane.getFont().getSize() - 1))); + viewMenu.add(zoomOutButton); + + // 'Reset Zoom' button + JMenuItem resetZoomButton = new JMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.view.reset_zoom")); + resetZoomButton.addActionListener(e -> consolePane.setFont(new Font(consolePane.getFont().getName(), consolePane.getFont().getStyle(), originalFontSize))); + viewMenu.add(resetZoomButton); + + // create 'Options' + optionsMenu = new JMenu(LanguageUtils.getLocaleStringLog("geyser.gui.menu.options")); + viewMenu.setMnemonic(KeyEvent.VK_O); + menuBar.add(optionsMenu); + + // Set the frames menu bar + frame.setJMenuBar(menuBar); + + JPanel rightPane = new JPanel(); + rightPane.setLayout(new CardLayout(5, 5)); + //cp.add(rightPane, BorderLayout.EAST); + splitPane.setRightComponent(rightPane); + + JPanel rightContentPane = new JPanel(); + rightContentPane.setLayout(new GridLayout(2, 1, 5, 5)); + rightPane.add(rightContentPane); + + // Set the ram graph to 0 + for (int i = 0; i < 10; i++) { + ramValues.add(0); + } + ramGraph.setValues(ramValues); + ramGraph.setXLabel(LanguageUtils.getLocaleStringLog("geyser.gui.graph.loading")); + rightContentPane.add(ramGraph); + + playerTableModel.addColumn(LanguageUtils.getLocaleStringLog("geyser.gui.table.ip")); + playerTableModel.addColumn(LanguageUtils.getLocaleStringLog("geyser.gui.table.username")); + + JScrollPane playerScrollPane = new JScrollPane(playerTable); + rightContentPane.add(playerScrollPane); + + // This has to be done last + frame.setVisible(true); + } + + /** + * Queue up an update to the text pane so we don't block the main thread + * + * @param text The text to append + */ + private void updateTextPane(final String text) { + SwingUtilities.invokeLater(() -> { + consolePane.appendANSI(text); + Document doc = consolePane.getDocument(); + consolePane.setCaretPosition(doc.getLength()); + }); + } + + /** + * Redirect the default io streams to the text pane + */ + public void redirectSystemStreams() { + // Setup a new output stream to forward it to the text pane + OutputStream out = new OutputStream() { + @Override + public void write(final int b) { + updateTextPane(String.valueOf((char) b)); + } + + @Override + public void write(byte[] b, int off, int len) { + updateTextPane(new String(b, off, len)); + } + + @Override + public void write(byte[] b) { + write(b, 0, b.length); + } + }; + + // Override the system output streams + System.setOut(new PrintStream(out, true)); + System.setErr(new PrintStream(out, true)); + + } + + /** + * Add all the Geyser commands to the commands menu, and setup the debug mode toggle + * + * @param geyserStandaloneLogger The current logger + * @param geyserCommandManager The commands manager + */ + public void setupInterface(GeyserStandaloneLogger geyserStandaloneLogger, GeyserCommandManager geyserCommandManager) { + commandsMenu.removeAll(); + optionsMenu.removeAll(); + + for (Map.Entry command : geyserCommandManager.getCommands().entrySet()) { + // Remove the offhand command and any alias commands to prevent duplicates in the list + if ("offhand".equals(command.getValue().getName()) || command.getValue().getAliases().contains(command.getKey())) { + continue; + } + + // Create the button that runs the command + JMenuItem commandButton = new JMenuItem(command.getValue().getName()); + commandButton.getAccessibleContext().setAccessibleDescription(command.getValue().getDescription()); + commandButton.addActionListener(e -> command.getValue().execute(geyserStandaloneLogger, new String[]{ })); + commandsMenu.add(commandButton); + } + + // 'Debug Mode' toggle + JCheckBoxMenuItem debugMode = new JCheckBoxMenuItem(LanguageUtils.getLocaleStringLog("geyser.gui.menu.options.toggle_debug_mode")); + debugMode.setSelected(geyserStandaloneLogger.isDebug()); + debugMode.addActionListener(e -> geyserStandaloneLogger.setDebug(!geyserStandaloneLogger.isDebug())); + optionsMenu.add(debugMode); + } + + /** + * Start the thread to update the form information every 1s + */ + public void startUpdateThread() { + ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); + + Runnable periodicTask = () -> { + if (GeyserConnector.getInstance() != null) { + // Update player table + playerTableModel.getDataVector().removeAllElements(); + + for (GeyserSession player : GeyserConnector.getInstance().getPlayers()) { + Vector row = new Vector(); + row.add(player.getSocketAddress().getHostName()); + row.add(player.getPlayerEntity().getUsername()); + + playerTableModel.addRow(row); + } + + playerTableModel.fireTableDataChanged(); + } + + // Update ram graph + final long freeMemory = Runtime.getRuntime().freeMemory(); + final long totalMemory = Runtime.getRuntime().totalMemory(); + final int freePercent = (int)(freeMemory * 100.0 / totalMemory + 0.5); + ramValues.add(100 - freePercent); + + ramGraph.setXLabel(LanguageUtils.getLocaleStringLog("geyser.gui.graph.usage", String.format("%,d", (totalMemory - freeMemory) / MEGABYTE), freePercent)); + + // Trim the list + int k = ramValues.size(); + if ( k > 10 ) + ramValues.subList(0, k - 10).clear(); + + // Update the graph + ramGraph.setValues(ramValues); + }; + + // SwingUtilities.invokeLater is called so we don't run into threading issues with the GUI + executor.scheduleAtFixedRate(() -> SwingUtilities.invokeLater(periodicTask), 0, 1, TimeUnit.SECONDS); + } + + /** + * Make sure the JSplitPane divider is within a set of bounds + * + * @param splitPane The JSplitPane to check + */ + private void splitPaneLimit(JSplitPane splitPane) { + JRootPane frame = splitPane.getRootPane(); + int location = splitPane.getDividerLocation(); + if (location < frame.getWidth() - frame.getWidth() * 0.4f) { + splitPane.setDividerLocation(Math.round(frame.getWidth() - frame.getWidth() * 0.4f)); + } else if (location > frame.getWidth() - 200) { + splitPane.setDividerLocation(frame.getWidth() - 200); + } + } +} diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GraphPanel.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GraphPanel.java new file mode 100644 index 00000000..0e336132 --- /dev/null +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/gui/GraphPanel.java @@ -0,0 +1,188 @@ +/* + * 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.platform.standalone.gui; + +import lombok.Setter; + +import javax.swing.*; +import java.awt.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * This has been modified to fit Geyser more but is based on + * https://gist.github.com/roooodcastro/6325153#gistcomment-3107524 + */ +public final class GraphPanel extends JPanel { + private final static int padding = 10; + private final static int labelPadding = 25; + private final static int pointWidth = 4; + private final static int numberYDivisions = 10; + private final static Color lineColor = new Color(44, 102, 230, 255); + private final static Color pointColor = new Color(100, 100, 100, 255); + private final static Color gridColor = new Color(200, 200, 200, 255); + private static final Stroke graphStroke = new BasicStroke(2f); + private List values = new ArrayList<>(10); + + @Setter + private String xLabel = ""; + + public GraphPanel() { + setPreferredSize(new Dimension(200 - (padding * 2), 150 - (padding * 2))); + } + + public void setValues(Collection newValues) { + values.clear(); + addValues(newValues); + } + + public void addValues(Collection newValues) { + values.addAll(newValues); + updateUI(); + } + + @Override + protected void paintComponent(Graphics graphics) { + super.paintComponent(graphics); + if (!(graphics instanceof Graphics2D)) { + graphics.drawString("Graphics is not Graphics2D, unable to render", 0, 0); + return; + } + final Graphics2D g = (Graphics2D) graphics; + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + final int length = values.size(); + final int width = getWidth(); + final int height = getHeight(); + final int maxScore = getMaxScore(); + final int minScore = getMinScore(); + final int scoreRange = maxScore - minScore; + + // draw white background + g.setColor(Color.WHITE); + g.fillRect( + padding + labelPadding, + padding, + width - (2 * padding) - labelPadding, + height - 2 * padding - labelPadding); + g.setColor(Color.BLACK); + + final FontMetrics fontMetrics = g.getFontMetrics(); + final int fontHeight = fontMetrics.getHeight(); + + // create hatch marks and grid lines for y axis. + for (int i = 0; i < numberYDivisions + 1; i++) { + final int x1 = padding + labelPadding; + final int x2 = pointWidth + padding + labelPadding; + final int y = height - ((i * (height - padding * 2 - labelPadding)) / numberYDivisions + padding + labelPadding); + if (length > 0) { + g.setColor(gridColor); + g.drawLine(padding + labelPadding + 1 + pointWidth, y, width - padding, y); + + g.setColor(Color.BLACK); + final int tickValue = (int) (minScore + ((scoreRange * i) / numberYDivisions)); + final String yLabel = tickValue + ""; + final int labelWidth = fontMetrics.stringWidth(yLabel); + g.drawString(yLabel, x1 - labelWidth - 5, y + (fontHeight / 2) - 3); + } + g.drawLine(x1, y, x2, y); + } + + // and for x axis + if (length > 1) { + for (int i = 0; i < length; i++) { + final int x = i * (width - padding * 2 - labelPadding) / (length - 1) + padding + labelPadding; + final int y1 = height - padding - labelPadding; + final int y2 = y1 - pointWidth; + if ((i % ((int) ((length / 20.0)) + 1)) == 0) { + g.setColor(gridColor); + g.drawLine(x, height - padding - labelPadding - 1 - pointWidth, x, padding); + + g.setColor(Color.BLACK); + + /*g.setColor(Color.BLACK); + final String xLabel = i + ""; + final int labelWidth = fontMetrics.stringWidth(xLabel); + g.drawString(xLabel, x - labelWidth / 2, y1 + fontHeight + 3);*/ + } + g.drawLine(x, y1, x, y2); + } + } + + // create x and y axes + g.drawLine(padding + labelPadding, height - padding - labelPadding, padding + labelPadding, padding); + g.drawLine(padding + labelPadding, height - padding - labelPadding, width - padding, height - padding - labelPadding); + + g.setColor(Color.BLACK); + final int labelWidth = fontMetrics.stringWidth(xLabel); + final int labelX = ((padding + labelPadding) + (width - padding)) / 2; + final int labelY = height - padding - labelPadding; + g.drawString(xLabel, labelX - labelWidth / 2, labelY + fontHeight + 3); + + final Stroke oldStroke = g.getStroke(); + g.setColor(lineColor); + g.setStroke(graphStroke); + + final double xScale = ((double) width - (2 * padding) - labelPadding) / (length - 1); + final double yScale = ((double) height - 2 * padding - labelPadding) / scoreRange; + + final List graphPoints = new ArrayList<>(length); + for (int i = 0; i < length; i++) { + final int x1 = (int) (i * xScale + padding + labelPadding); + final int y1 = (int) ((maxScore - values.get(i)) * yScale + padding); + graphPoints.add(new Point(x1, y1)); + } + + for (int i = 0; i < graphPoints.size() - 1; i++) { + final int x1 = graphPoints.get(i).x; + final int y1 = graphPoints.get(i).y; + final int x2 = graphPoints.get(i + 1).x; + final int y2 = graphPoints.get(i + 1).y; + g.drawLine(x1, y1, x2, y2); + } + + boolean drawDots = width > (length * pointWidth); + if (drawDots) { + g.setStroke(oldStroke); + g.setColor(pointColor); + for (Point graphPoint : graphPoints) { + final int x = graphPoint.x - pointWidth / 2; + final int y = graphPoint.y - pointWidth / 2; + g.fillOval(x, y, pointWidth, pointWidth); + } + } + } + + private int getMinScore() { + return 0; + } + + private int getMaxScore() { + return 100; + } +} diff --git a/bootstrap/standalone/src/main/resources/icon.png b/bootstrap/standalone/src/main/resources/icon.png new file mode 100644 index 00000000..4e6a38a7 Binary files /dev/null and b/bootstrap/standalone/src/main/resources/icon.png differ diff --git a/bootstrap/standalone/src/main/resources/log4j2.xml b/bootstrap/standalone/src/main/resources/log4j2.xml index 95741540..238a27da 100644 --- a/bootstrap/standalone/src/main/resources/log4j2.xml +++ b/bootstrap/standalone/src/main/resources/log4j2.xml @@ -1,9 +1,12 @@ - + + + + @@ -14,6 +17,7 @@ + diff --git a/bootstrap/velocity/pom.xml b/bootstrap/velocity/pom.xml index fb06767e..7c42ba33 100644 --- a/bootstrap/velocity/pom.xml +++ b/bootstrap/velocity/pom.xml @@ -6,7 +6,7 @@ org.geysermc bootstrap-parent - 1.0-SNAPSHOT + 1.0.0 ../ bootstrap-velocity @@ -14,7 +14,7 @@ org.geysermc connector - 1.0-SNAPSHOT + 1.0.0 compile @@ -61,6 +61,10 @@ it.unimi.dsi.fastutil org.geysermc.platform.velocity.shaded.fastutil + + org.reflections.reflections + org.geysermc.platform.velocity.shaded.reflections + diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityDumpInfo.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityDumpInfo.java new file mode 100644 index 00000000..906a0414 --- /dev/null +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityDumpInfo.java @@ -0,0 +1,63 @@ +/* + * 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.platform.velocity; + +import com.velocitypowered.api.plugin.PluginContainer; +import com.velocitypowered.api.proxy.ProxyServer; +import lombok.Getter; +import org.geysermc.connector.dump.BootstrapDumpInfo; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public class GeyserVelocityDumpInfo extends BootstrapDumpInfo { + + private String platformName; + private String platformVersion; + private String platformVendor; + private boolean onlineMode; + private String serverIP; + private int serverPort; + private List plugins; + + GeyserVelocityDumpInfo(ProxyServer proxy) { + super(); + this.platformName = proxy.getVersion().getName(); + this.platformVersion = proxy.getVersion().getVersion(); + this.platformVendor = proxy.getVersion().getVendor(); + this.onlineMode = proxy.getConfiguration().isOnlineMode(); + this.serverIP = proxy.getBoundAddress().getHostString(); + this.serverPort = proxy.getBoundAddress().getPort(); + this.plugins = new ArrayList<>(); + + for (PluginContainer plugin : proxy.getPluginManager().getPlugins()) { + String pluginClass = plugin.getInstance().map((pl) -> pl.getClass().getName()).orElse("unknown"); + this.plugins.add(new PluginInfo(true, plugin.getDescription().getName().get(), plugin.getDescription().getVersion().get(), pluginClass, plugin.getDescription().getAuthors())); + } + } +} diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java index 73eaddf0..b5c79cc2 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityMain.java @@ -26,7 +26,7 @@ package org.geysermc.platform.velocity; -import org.geysermc.common.main.IGeyserMain; +import org.geysermc.connector.common.main.IGeyserMain; public class GeyserVelocityMain extends IGeyserMain { diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java index 01be949b..980c5b3e 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPingPassthrough.java @@ -32,9 +32,8 @@ import com.velocitypowered.api.proxy.InboundConnection; import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.proxy.server.ServerPing; import lombok.AllArgsConstructor; -import net.kyori.text.TextComponent; import net.kyori.text.serializer.legacy.LegacyComponentSerializer; -import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.common.ping.GeyserPingInfo; import org.geysermc.connector.ping.IGeyserPingPassthrough; import java.net.Inet4Address; @@ -60,13 +59,17 @@ public class GeyserVelocityPingPassthrough implements IGeyserPingPassthrough { throw new RuntimeException(e); } GeyserPingInfo geyserPingInfo = new GeyserPingInfo( - LegacyComponentSerializer.INSTANCE.serialize(event.getPing().getDescription(), '§'), - event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getOnline(), - event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getMax() + LegacyComponentSerializer.legacy().serialize(event.getPing().getDescription(), '§'), + new GeyserPingInfo.Players( + event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getMax(), + event.getPing().getPlayers().orElseThrow(IllegalStateException::new).getOnline() + ), + new GeyserPingInfo.Version( + event.getPing().getVersion().getName(), + event.getPing().getVersion().getProtocol() + ) ); - event.getPing().getPlayers().get().getSample().forEach(player -> { - geyserPingInfo.addPlayer(player.getName()); - }); + event.getPing().getPlayers().get().getSample().stream().map(ServerPing.SamplePlayer::getName).forEach(geyserPingInfo.getPlayerList()::add); return geyserPingInfo; } 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 5abf3c23..425aba18 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 @@ -35,13 +35,15 @@ import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.proxy.ProxyServer; import lombok.Getter; -import org.geysermc.common.PlatformType; +import org.geysermc.connector.common.PlatformType; import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.bootstrap.GeyserBootstrap; +import org.geysermc.connector.dump.BootstrapDumpInfo; import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.connector.utils.LanguageUtils; import org.geysermc.platform.velocity.command.GeyserVelocityCommandExecutor; import org.geysermc.platform.velocity.command.GeyserVelocityCommandManager; import org.slf4j.Logger; @@ -84,7 +86,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { File configFile = FileUtils.fileOrCopiedFromResource(configFolder.resolve("config.yml").toFile(), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString())); this.geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class); } catch (IOException ex) { - logger.warn("Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex); + logger.warn(LanguageUtils.getLocaleStringLog("geyser.config.failed"), ex); ex.printStackTrace(); } @@ -102,7 +104,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); if (geyserConfig.getRemote().getAuthType().equals("floodgate") && !proxyServer.getPluginManager().getPlugin("floodgate").isPresent()) { - geyserLogger.severe("Auth type set to Floodgate but Floodgate not found! Disabling..."); + geyserLogger.severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " + LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.disabling")); return; } @@ -153,4 +155,9 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { public void onShutdown(ProxyShutdownEvent event) { onDisable(); } + + @Override + public BootstrapDumpInfo getDumpInfo() { + return new GeyserVelocityDumpInfo(proxyServer); + } } diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java index 940c5224..fa3aaa3c 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/command/GeyserVelocityCommandExecutor.java @@ -32,9 +32,10 @@ import lombok.AllArgsConstructor; import net.kyori.text.TextComponent; -import org.geysermc.common.ChatColor; +import org.geysermc.connector.common.ChatColor; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.utils.LanguageUtils; @AllArgsConstructor public class GeyserVelocityCommandExecutor implements Command { @@ -46,7 +47,8 @@ public class GeyserVelocityCommandExecutor implements Command { if (args.length > 0) { if (getCommand(args[0]) != null) { if (!source.hasPermission(getCommand(args[0]).getPermission())) { - source.sendMessage(TextComponent.of(ChatColor.RED + "You do not have permission to execute this command!")); + // Not ideal to use log here but we dont get a session + source.sendMessage(TextComponent.of(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.bootstrap.command.permission_fail"))); return; } getCommand(args[0]).execute(new VelocityCommandSender(source), args); diff --git a/common/pom.xml b/common/pom.xml index 0a47fbca..0df8ef4b 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -10,7 +10,7 @@ ../ common - 1.0-SNAPSHOT + 1.0.0 com.google.code.gson diff --git a/common/src/main/java/org/geysermc/common/AuthType.java b/common/src/main/java/org/geysermc/common/AuthType.java deleted file mode 100644 index 8edbc4d5..00000000 --- a/common/src/main/java/org/geysermc/common/AuthType.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.geysermc.common; - -import lombok.Getter; - -@Getter -public enum AuthType { - OFFLINE, - ONLINE, - FLOODGATE; - - public static final AuthType[] VALUES = values(); - - public static AuthType getById(int id) { - return id < VALUES.length ? VALUES[id] : OFFLINE; - } - - /** - * Convert the AuthType string (from config) to the enum, OFFLINE on fail - * - * @param name AuthType string - * - * @return The converted AuthType - */ - public static AuthType getByName(String name) { - String upperCase = name.toUpperCase(); - for (AuthType type : VALUES) { - if (type.name().equals(upperCase)) { - return type; - } - } - return OFFLINE; - } -} \ No newline at end of file diff --git a/common/src/main/java/org/geysermc/common/PlatformType.java b/common/src/main/java/org/geysermc/common/PlatformType.java deleted file mode 100644 index fa6f57fd..00000000 --- a/common/src/main/java/org/geysermc/common/PlatformType.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.geysermc.common; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public enum PlatformType { - - BUKKIT("Bukkit"), - BUNGEECORD("BungeeCord"), - SPONGE("Sponge"), - STANDALONE("Standalone"), - VELOCITY("Velocity"); - - private String platformName; -} diff --git a/common/src/main/resources/help.txt b/common/src/main/resources/help.txt deleted file mode 100644 index 3512ed83..00000000 --- a/common/src/main/resources/help.txt +++ /dev/null @@ -1,18 +0,0 @@ - --------------------------------------------------------------------------------- - - Oops! You attempted to run a plugin version of Geyser directly! - - This jar file is a plugin for ${plugin_type}. You can run this file as a - plugin by dropping the jar file into the "${plugin_folder}" directory. - - There is also a standalone version available that doesn't need to - be installed as a plugin, you can find it on our build server: - - http://ci.geysermc.org/ - - If you need more help, you should check out our discord: - - http://discord.geysermc.org/ - --------------------------------------------------------------------------------- \ No newline at end of file diff --git a/connector/pom.xml b/connector/pom.xml index 91cf6f3d..3fdd5f37 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -10,12 +10,12 @@ ../ connector - 1.0-SNAPSHOT + 1.0.0 org.geysermc common - 1.0-SNAPSHOT + 1.0.0 compile @@ -32,8 +32,8 @@ com.nukkitx.protocol - bedrock-v390 - 2.5.6-SNAPSHOT + bedrock-v407 + 2.6.0-SNAPSHOT compile @@ -66,6 +66,12 @@ 8.3.1 compile + + com.nukkitx.fastutil + fastutil-int-byte-maps + 8.3.1 + compile + com.nukkitx.fastutil fastutil-int-double-maps @@ -99,7 +105,7 @@ com.github.steveice10 mcprotocollib - 4c315aa206 + 7545884a2d compile @@ -121,20 +127,20 @@ net.kyori - text-api - 3.0.3 + adventure-api + 4.0.0-SNAPSHOT compile net.kyori - text-serializer-gson - 3.0.3 + adventure-text-serializer-gson + 4.0.0-SNAPSHOT compile net.kyori - text-serializer-legacy - 3.0.3 + adventure-text-serializer-legacy + 4.0.0-SNAPSHOT compile @@ -164,6 +170,11 @@ false git.user.* + git.*.user.* + git.closest.* + git.commit.id.describe + git.commit.id.describe-short + git.commit.message.short flat diff --git a/connector/src/main/java/org/geysermc/connector/FloodgateKeyLoader.java b/connector/src/main/java/org/geysermc/connector/FloodgateKeyLoader.java index 617ac83e..d4413d68 100644 --- a/connector/src/main/java/org/geysermc/connector/FloodgateKeyLoader.java +++ b/connector/src/main/java/org/geysermc/connector/FloodgateKeyLoader.java @@ -26,6 +26,7 @@ package org.geysermc.connector; +import org.geysermc.connector.utils.LanguageUtils; import org.geysermc.connector.configuration.GeyserConfiguration; import java.nio.file.Files; @@ -37,13 +38,13 @@ public class FloodgateKeyLoader { if (floodgate != null) { Path autoKey = floodgateFolder.resolve("public-key.pem"); if (Files.exists(autoKey)) { - logger.info("Auto-loaded floodgate key"); + logger.info(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.auto_loaded")); floodgateKey = autoKey; } else { - logger.error("Auth-type set to floodgate and the public key is missing!"); + logger.error(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.missing_key")); } } else { - logger.error("Auth-type set to floodgate but floodgate is not installed!"); + logger.error(LanguageUtils.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed")); } } diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index d201656a..675c2b9a 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -29,11 +29,11 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.BedrockServer; -import com.nukkitx.protocol.bedrock.v390.Bedrock_v390; +import com.nukkitx.protocol.bedrock.v407.Bedrock_v407; import lombok.Getter; import lombok.Setter; -import org.geysermc.common.AuthType; -import org.geysermc.common.PlatformType; +import org.geysermc.connector.common.AuthType; +import org.geysermc.connector.common.PlatformType; import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.configuration.GeyserConfiguration; @@ -44,22 +44,23 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.BiomeTranslator; import org.geysermc.connector.network.translators.EntityIdentifierRegistry; import org.geysermc.connector.network.translators.PacketTranslatorRegistry; +import org.geysermc.connector.network.translators.effect.EffectRegistry; import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.network.translators.sound.SoundHandlerRegistry; +import org.geysermc.connector.network.translators.sound.SoundRegistry; import org.geysermc.connector.network.translators.world.WorldManager; +import org.geysermc.connector.utils.LanguageUtils; import org.geysermc.connector.network.translators.world.block.BlockTranslator; -import org.geysermc.connector.network.translators.effect.EffectRegistry; import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator; import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.DockerCheck; import org.geysermc.connector.utils.LocaleUtils; -import org.geysermc.connector.network.translators.sound.SoundRegistry; import java.net.InetSocketAddress; import java.text.DecimalFormat; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -70,12 +71,12 @@ public class GeyserConnector { public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES); - public static final BedrockPacketCodec BEDROCK_PACKET_CODEC = Bedrock_v390.V390_CODEC; + public static final BedrockPacketCodec BEDROCK_PACKET_CODEC = Bedrock_v407.V407_CODEC; public static final String NAME = "Geyser"; public static final String VERSION = "DEV"; // A fallback for running in IDEs - private final Map players = new HashMap<>(); + private final List players = new ArrayList<>(); private static GeyserConnector instance; @@ -107,7 +108,7 @@ public class GeyserConnector { logger.info("******************************************"); logger.info(""); - logger.info("Loading " + NAME + " version " + VERSION); + logger.info(LanguageUtils.getLocaleStringLog("geyser.core.load", NAME, VERSION)); logger.info(""); logger.info("******************************************"); @@ -143,9 +144,9 @@ public class GeyserConnector { bedrockServer.setHandler(new ConnectorServerEventHandler(this)); bedrockServer.bind().whenComplete((avoid, throwable) -> { if (throwable == null) { - logger.info("Started Geyser on " + config.getBedrock().getAddress() + ":" + config.getBedrock().getPort()); + logger.info(LanguageUtils.getLocaleStringLog("geyser.core.start", config.getBedrock().getAddress(), String.valueOf(config.getBedrock().getPort()))); } else { - logger.severe("Failed to start Geyser on " + config.getBedrock().getAddress() + ":" + config.getBedrock().getPort()); + logger.severe(LanguageUtils.getLocaleStringLog("geyser.core.fail", config.getBedrock().getAddress(), config.getBedrock().getPort())); throwable.printStackTrace(); } }).join(); @@ -158,19 +159,34 @@ public class GeyserConnector { metrics.addCustomChart(new Metrics.SimplePie("platform", platformType::getPlatformName)); } + boolean isGui = false; + // This will check if we are in standalone and get the 'useGui' variable from there + if (platformType == PlatformType.STANDALONE) { + try { + Class cls = Class.forName("org.geysermc.platform.standalone.GeyserStandaloneBootstrap"); + isGui = (boolean) cls.getMethod("isUseGui").invoke(cls.cast(bootstrap)); + } catch (Exception e) { e.printStackTrace(); } + } + double completeTime = (System.currentTimeMillis() - startupTime) / 1000D; - logger.info(String.format("Done (%ss)! Run /geyser help for help!", new DecimalFormat("#.###").format(completeTime))); + String message = LanguageUtils.getLocaleStringLog("geyser.core.finish.done", new DecimalFormat("#.###").format(completeTime)) + " "; + if (isGui) { + message += LanguageUtils.getLocaleStringLog("geyser.core.finish.gui"); + } else { + message += LanguageUtils.getLocaleStringLog("geyser.core.finish.console"); + } + logger.info(message); } public void shutdown() { - bootstrap.getGeyserLogger().info("Shutting down Geyser."); + bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown")); shuttingDown = true; if (players.size() >= 1) { - bootstrap.getGeyserLogger().info("Kicking " + players.size() + " player(s)"); + bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.kick.log", players.size())); - for (GeyserSession playerSession : players.values()) { - playerSession.disconnect("Geyser Proxy shutting down."); + for (GeyserSession playerSession : players) { + playerSession.disconnect(LanguageUtils.getPlayerLocaleString("geyser.core.shutdown.kick.message", playerSession.getClientData().getLanguageCode())); } CompletableFuture future = CompletableFuture.runAsync(new Runnable() { @@ -194,7 +210,7 @@ public class GeyserConnector { // Block and wait for the future to complete try { future.get(); - bootstrap.getGeyserLogger().info("Kicked all players"); + bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.kick.done")); } catch (Exception e) { // Quietly fail } @@ -207,15 +223,15 @@ public class GeyserConnector { authType = null; this.getCommandManager().getCommands().clear(); - bootstrap.getGeyserLogger().info("Geyser shutdown successfully."); + bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.done")); } public void addPlayer(GeyserSession player) { - players.put(player.getSocketAddress(), player); + players.add(player); } public void removePlayer(GeyserSession player) { - players.remove(player.getSocketAddress()); + players.remove(player); } public static GeyserConnector start(PlatformType platformType, GeyserBootstrap bootstrap) { diff --git a/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java b/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java index 8683f80c..f089350f 100644 --- a/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java +++ b/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java @@ -26,6 +26,7 @@ package org.geysermc.connector.bootstrap; +import org.geysermc.connector.dump.BootstrapDumpInfo; import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.GeyserLogger; @@ -92,4 +93,11 @@ public interface GeyserBootstrap { * @return Path location of data folder */ Path getConfigFolder(); + + /** + * Information used for the bootstrap section of the debug dump + * + * @return The info about the bootstrap + */ + BootstrapDumpInfo getDumpInfo(); } diff --git a/connector/src/main/java/org/geysermc/connector/command/CommandManager.java b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java index 8b1d0bc7..afa75503 100644 --- a/connector/src/main/java/org/geysermc/connector/command/CommandManager.java +++ b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java @@ -29,6 +29,7 @@ import lombok.Getter; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.defaults.*; +import org.geysermc.connector.utils.LanguageUtils; import java.util.Collections; import java.util.HashMap; @@ -44,16 +45,18 @@ public abstract class CommandManager { public CommandManager(GeyserConnector connector) { this.connector = connector; - registerCommand(new HelpCommand(connector, "help", "Shows help for all registered commands.", "geyser.command.help")); - registerCommand(new ListCommand(connector, "list", "List all players connected through Geyser.", "geyser.command.list")); - registerCommand(new ReloadCommand(connector, "reload", "Reloads the Geyser configurations. Kicks all players when used!", "geyser.command.reload")); - registerCommand(new StopCommand(connector, "stop", "Shuts down Geyser.", "geyser.command.stop")); - registerCommand(new OffhandCommand(connector, "offhand", "Puts an items in your offhand.", "geyser.command.offhand")); + registerCommand(new HelpCommand(connector, "help", LanguageUtils.getLocaleStringLog("geyser.commands.help.desc"), "geyser.command.help")); + registerCommand(new ListCommand(connector, "list", LanguageUtils.getLocaleStringLog("geyser.commands.list.desc"), "geyser.command.list")); + registerCommand(new ReloadCommand(connector, "reload", LanguageUtils.getLocaleStringLog("geyser.commands.reload.desc"), "geyser.command.reload")); + registerCommand(new StopCommand(connector, "stop", LanguageUtils.getLocaleStringLog("geyser.commands.stop.desc"), "geyser.command.stop")); + registerCommand(new OffhandCommand(connector, "offhand", LanguageUtils.getLocaleStringLog("geyser.commands.offhand.desc"), "geyser.command.offhand")); + registerCommand(new DumpCommand(connector, "dump", LanguageUtils.getLocaleStringLog("geyser.commands.dump.desc"), "geyser.command.dump")); + registerCommand(new VersionCommand(connector, "version", LanguageUtils.getLocaleStringLog("geyser.commands.version.desc"), "geyser.command.version")); } public void registerCommand(GeyserCommand command) { commands.put(command.getName(), command); - connector.getLogger().debug("Registered command " + command.getName()); + connector.getLogger().debug(LanguageUtils.getLocaleStringLog("geyser.commands.registered", command.getName())); if (command.getAliases().isEmpty()) return; @@ -81,7 +84,7 @@ public abstract class CommandManager { GeyserCommand cmd = commands.get(label); if (cmd == null) { - connector.getLogger().error("Invalid Command! Try /geyser help for a list of commands."); + connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.invalid")); return; } diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/DumpCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/DumpCommand.java new file mode 100644 index 00000000..6566ecc1 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/DumpCommand.java @@ -0,0 +1,94 @@ +/* + * 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.command.defaults; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; +import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; +import org.geysermc.connector.common.ChatColor; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandSender; +import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.dump.DumpInfo; +import org.geysermc.connector.utils.LanguageUtils; +import org.geysermc.connector.utils.WebUtils; + +import java.io.IOException; + +public class DumpCommand extends GeyserCommand { + + private final GeyserConnector connector; + private static final ObjectMapper MAPPER = new ObjectMapper(); + private static final String DUMP_URL = "https://dump.geysermc.org/"; + + public DumpCommand(GeyserConnector connector, String name, String description, String permission) { + super(name, description, permission); + + this.connector = connector; + + final SimpleFilterProvider filter = new SimpleFilterProvider(); + filter.addFilter("dump_user_auth", SimpleBeanPropertyFilter.serializeAllExcept(new String[] {"password"})); + + MAPPER.setFilterProvider(filter); + } + + @Override + public void execute(CommandSender sender, String[] args) { + sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.collecting")); + String dumpData = ""; + try { + dumpData = MAPPER.writeValueAsString(new DumpInfo()); + } catch (IOException e) { + sender.sendMessage(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.commands.dump.collect_error")); + connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.dump.collect_error_short"), e); + return; + } + + sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.uploading")); + String response; + JsonNode responseNode; + try { + response = WebUtils.post(DUMP_URL + "documents", dumpData); + responseNode = MAPPER.readTree(response); + } catch (IOException e) { + sender.sendMessage(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.commands.dump.upload_error")); + connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.dump.upload_error_short"), e); + return; + } + + if (!responseNode.has("key")) { + sender.sendMessage(ChatColor.RED + LanguageUtils.getLocaleStringLog("geyser.commands.dump.upload_error_short") + ": " + (responseNode.has("message") ? responseNode.get("message").asText() : response)); + return; + } + + String uploadedDumpUrl = DUMP_URL + responseNode.get("key").asText(); + sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.dump.message") + " " + ChatColor.DARK_AQUA + uploadedDumpUrl); + if (!sender.isConsole()) { + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.commands.dump.created", sender.getName(), uploadedDumpUrl)); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java index 6acb7822..0407cf6e 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/HelpCommand.java @@ -25,10 +25,12 @@ package org.geysermc.connector.command.defaults; -import org.geysermc.common.ChatColor; +import org.geysermc.connector.common.ChatColor; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.LanguageUtils; import java.util.Collections; import java.util.List; @@ -48,7 +50,17 @@ public class HelpCommand extends GeyserCommand { @Override public void execute(CommandSender sender, String[] args) { - sender.sendMessage("---- Showing Help For: Geyser (Page 1/1) ----"); + int page = 1; + int maxPage = 1; + String header = ""; + + if (sender instanceof GeyserSession) { + header = LanguageUtils.getPlayerLocaleString("geyser.commands.help.header", ((GeyserSession) sender).getClientData().getLanguageCode(), page, maxPage); + } else { + header = LanguageUtils.getLocaleStringLog("geyser.commands.help.header", page, maxPage); + } + + sender.sendMessage(header); Map cmds = connector.getCommandManager().getCommands(); List commands = connector.getCommandManager().getCommands().keySet().stream().sorted().collect(Collectors.toList()); commands.forEach(cmd -> sender.sendMessage(ChatColor.YELLOW + "/geyser " + cmd + ChatColor.WHITE + ": " + cmds.get(cmd).getDescription())); diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java index 21fa4253..3c78c554 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/ListCommand.java @@ -25,11 +25,11 @@ package org.geysermc.connector.command.defaults; -import org.geysermc.common.ChatColor; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.GeyserCommand; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.LanguageUtils; import java.util.stream.Collectors; @@ -45,6 +45,13 @@ public class ListCommand extends GeyserCommand { @Override public void execute(CommandSender sender, String[] args) { - sender.sendMessage(ChatColor.YELLOW + "Online Players (" + connector.getPlayers().size() + "): " + ChatColor.WHITE + connector.getPlayers().values().stream().map(GeyserSession::getName).collect(Collectors.joining(" "))); + String message = ""; + if (sender instanceof GeyserSession) { + message = LanguageUtils.getPlayerLocaleString("geyser.commands.list.message", ((GeyserSession) sender).getClientData().getLanguageCode(), connector.getPlayers().size(), connector.getPlayers().stream().map(GeyserSession::getName).collect(Collectors.joining(" "))); + } else { + message = LanguageUtils.getLocaleStringLog("geyser.commands.list.message", connector.getPlayers().size(), connector.getPlayers().stream().map(GeyserSession::getName).collect(Collectors.joining(" "))); + } + + sender.sendMessage(message); } } diff --git a/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java index a49506b0..b1b60132 100644 --- a/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/OffhandCommand.java @@ -59,7 +59,7 @@ public class OffhandCommand extends GeyserCommand { return; } // Needed for Bukkit - sender is not an instance of GeyserSession - for (GeyserSession session : connector.getPlayers().values()) { + for (GeyserSession session : connector.getPlayers()) { if (sender.getName().equals(session.getPlayerEntity().getUsername())) { ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.SWAP_HANDS, new Position(0,0,0), BlockFace.DOWN); 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 c38a0c23..9c24fa2b 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,12 +25,12 @@ package org.geysermc.connector.command.defaults; -import org.geysermc.common.ChatColor; -import org.geysermc.common.PlatformType; +import org.geysermc.connector.common.PlatformType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.command.GeyserCommand; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.LanguageUtils; public class ReloadCommand extends GeyserCommand { @@ -46,9 +46,18 @@ public class ReloadCommand extends GeyserCommand { if (!sender.isConsole() && connector.getPlatformType() == PlatformType.STANDALONE) { return; } - sender.sendMessage(ChatColor.YELLOW + "Reloading Geyser configurations... all connected bedrock clients will be kicked."); - for (GeyserSession session : connector.getPlayers().values()) { - session.disconnect("Geyser has been reloaded... sorry for the inconvenience!"); + + String message = ""; + if (sender instanceof GeyserSession) { + message = LanguageUtils.getPlayerLocaleString("geyser.commands.reload.message", ((GeyserSession) sender).getClientData().getLanguageCode()); + } else { + message = LanguageUtils.getLocaleStringLog("geyser.commands.reload.message"); + } + + sender.sendMessage(message); + + for (GeyserSession session : connector.getPlayers()) { + session.disconnect(LanguageUtils.getPlayerLocaleString("geyser.commands.reload.kick", session.getClientData().getLanguageCode())); } connector.reload(); } 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 2222cdef..636058a0 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.common.PlatformType; +import org.geysermc.connector.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/VersionCommand.java b/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java new file mode 100644 index 00000000..7dd59712 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/command/defaults/VersionCommand.java @@ -0,0 +1,80 @@ +/* + * 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.command.defaults; + +import com.github.steveice10.mc.protocol.MinecraftConstants; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.command.CommandSender; +import org.geysermc.connector.command.GeyserCommand; +import org.geysermc.connector.utils.FileUtils; +import org.geysermc.connector.utils.LanguageUtils; +import org.geysermc.connector.utils.WebUtils; + +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Properties; + +public class VersionCommand extends GeyserCommand { + + public GeyserConnector connector; + + public VersionCommand(GeyserConnector connector, String name, String description, String permission) { + super(name, description, permission); + this.connector = connector; + } + + @Override + public void execute(CommandSender sender, String[] args) { + sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.version", GeyserConnector.NAME, GeyserConnector.VERSION, MinecraftConstants.GAME_VERSION, GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion())); + + // Disable update checking in dev mode + //noinspection ConstantConditions - changes in production + if (!GeyserConnector.VERSION.equals("DEV")) { + sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.checking")); + try { + Properties gitProp = new Properties(); + gitProp.load(FileUtils.getResource("git.properties")); + + String buildXML = WebUtils.getBody("https://ci.nukkitx.com/job/GeyserMC/job/Geyser/job/" + URLEncoder.encode(gitProp.getProperty("git.branch"), StandardCharsets.UTF_8.toString()) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber"); + if (buildXML.startsWith("")) { + int latestBuildNum = Integer.parseInt(buildXML.replaceAll("<(\\\\)?(/)?buildNumber>", "").trim()); + int buildNum = Integer.parseInt(gitProp.getProperty("git.build.number")); + if (latestBuildNum != buildNum) { + sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.no_updates")); + } else { + sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.outdated", (latestBuildNum - buildNum), "http://ci.geysermc.org/")); + } + } else { + throw new AssertionError("buildNumber missing"); + } + } catch (IOException | AssertionError | NumberFormatException e) { + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.commands.version.failed"), e); + sender.sendMessage(LanguageUtils.getLocaleStringLog("geyser.commands.version.failed")); + } + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/common/AuthType.java b/connector/src/main/java/org/geysermc/connector/common/AuthType.java new file mode 100644 index 00000000..f15e3ff5 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/common/AuthType.java @@ -0,0 +1,59 @@ +/* + * 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.common; + +import lombok.Getter; + +@Getter +public enum AuthType { + OFFLINE, + ONLINE, + FLOODGATE; + + public static final AuthType[] VALUES = values(); + + public static AuthType getById(int id) { + return id < VALUES.length ? VALUES[id] : OFFLINE; + } + + /** + * Convert the AuthType string (from config) to the enum, OFFLINE on fail + * + * @param name AuthType string + * + * @return The converted AuthType + */ + public static AuthType getByName(String name) { + String upperCase = name.toUpperCase(); + for (AuthType type : VALUES) { + if (type.name().equals(upperCase)) { + return type; + } + } + return OFFLINE; + } +} \ No newline at end of file diff --git a/common/src/main/java/org/geysermc/common/ChatColor.java b/connector/src/main/java/org/geysermc/connector/common/ChatColor.java similarity index 75% rename from common/src/main/java/org/geysermc/common/ChatColor.java rename to connector/src/main/java/org/geysermc/connector/common/ChatColor.java index 8868b063..1397f88c 100644 --- a/common/src/main/java/org/geysermc/common/ChatColor.java +++ b/connector/src/main/java/org/geysermc/connector/common/ChatColor.java @@ -1,29 +1,30 @@ /* * 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: + * 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 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. + * 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 * - * @author GeyserMC - * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.common; +package org.geysermc.connector.common; public class ChatColor { diff --git a/common/src/main/java/org/geysermc/common/ping/GeyserPingInfo.java b/connector/src/main/java/org/geysermc/connector/common/PlatformType.java similarity index 75% rename from common/src/main/java/org/geysermc/common/ping/GeyserPingInfo.java rename to connector/src/main/java/org/geysermc/connector/common/PlatformType.java index 40ef6da6..ee68b6d7 100644 --- a/common/src/main/java/org/geysermc/common/ping/GeyserPingInfo.java +++ b/connector/src/main/java/org/geysermc/connector/common/PlatformType.java @@ -24,25 +24,20 @@ * */ -package org.geysermc.common.ping; +package org.geysermc.connector.common; -import lombok.Data; +import lombok.AllArgsConstructor; import lombok.Getter; -import java.util.ArrayList; -import java.util.Collection; +@Getter +@AllArgsConstructor +public enum PlatformType { -@Data -public class GeyserPingInfo { + BUNGEECORD("BungeeCord"), + SPIGOT("Spigot"), + SPONGE("Sponge"), + STANDALONE("Standalone"), + VELOCITY("Velocity"); - public final String motd; - public final int currentPlayerCount; - public final int maxPlayerCount; - - @Getter - private Collection players = new ArrayList<>(); - - public void addPlayer(String username) { - players.add(username); - } + private String platformName; } diff --git a/common/src/main/java/org/geysermc/common/main/IGeyserMain.java b/connector/src/main/java/org/geysermc/connector/common/main/IGeyserMain.java similarity index 61% rename from common/src/main/java/org/geysermc/common/main/IGeyserMain.java rename to connector/src/main/java/org/geysermc/connector/common/main/IGeyserMain.java index 75da4e6b..a3e99ccb 100644 --- a/common/src/main/java/org/geysermc/common/main/IGeyserMain.java +++ b/connector/src/main/java/org/geysermc/connector/common/main/IGeyserMain.java @@ -24,28 +24,43 @@ * */ -package org.geysermc.common.main; +package org.geysermc.connector.common.main; import javax.swing.*; import java.io.InputStream; +import java.lang.reflect.Method; +import java.util.Locale; import java.util.Scanner; public class IGeyserMain { + /** + * Displays the run help message in the console and a message box if running with a gui + */ public void displayMessage() { String message = createMessage(); - if (System.console() == null) { + if (System.console() == null && !isHeadless()) { JOptionPane.showMessageDialog(null, message, "GeyserMC Plugin: " + this.getPluginType(), JOptionPane.ERROR_MESSAGE); } printMessage(message); } + /** + * Load and format the run help text + * + * @return The formatted message + */ private String createMessage() { String message = ""; - InputStream helpStream = IGeyserMain.class.getClassLoader().getResourceAsStream("help.txt"); + InputStream helpStream = IGeyserMain.class.getClassLoader().getResourceAsStream("languages/run-help/" + Locale.getDefault().toString() + ".txt"); + + if (helpStream == null) { + helpStream = IGeyserMain.class.getClassLoader().getResourceAsStream("languages/run-help/en_US.txt"); + } + Scanner help = new Scanner(helpStream).useDelimiter("\\Z"); String line = ""; while (help.hasNext()) { @@ -60,14 +75,44 @@ public class IGeyserMain { return message; } + /** + * Check if we are in a headless environment + * + * @return Are we in a headless environment? + */ + private boolean isHeadless() { + try { + Class graphicsEnvironment = Class.forName("java.awt.GraphicsEnvironment"); + Method isHeadless = graphicsEnvironment.getDeclaredMethod("isHeadless"); + return (Boolean)isHeadless.invoke(null); + } catch (Exception ex) { } + + return true; + } + + /** + * Simply print a message to console + * + * @param message The message to print + */ private void printMessage(String message) { System.out.print(message); } + /** + * Get the platform the plugin is for + * + * @return The string representation of the plugin platforms name + */ public String getPluginType() { return "unknown"; } + /** + * Get the folder name the plugin should go into + * + * @return The string representation of the folder + */ public String getPluginFolder() { return "unknown"; } diff --git a/connector/src/main/java/org/geysermc/connector/common/ping/GeyserPingInfo.java b/connector/src/main/java/org/geysermc/connector/common/ping/GeyserPingInfo.java new file mode 100644 index 00000000..246a3c6e --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/common/ping/GeyserPingInfo.java @@ -0,0 +1,94 @@ +/* + * 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.common.ping; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.databind.JsonNode; +import lombok.Data; + +import java.util.ArrayList; +import java.util.Collection; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class GeyserPingInfo { + + private String description; + + private Players players; + private Version version; + + @JsonIgnore + private Collection playerList = new ArrayList<>(); + + public GeyserPingInfo() { + } + + public GeyserPingInfo(String description, Players players, Version version) { + this.description = description; + this.players = players; + this.version = version; + } + + @JsonSetter("description") + void setDescription(JsonNode description) { + this.description = description.toString(); + } + + @Data + @JsonIgnoreProperties(ignoreUnknown = true) + public static class Players { + + private int max; + private int online; + + public Players() { + } + + public Players(int max, int online) { + this.max = max; + this.online = online; + } + } + + @Data + public static class Version { + + private String name; + private int protocol; + + public Version() { + } + + public Version(String name, int protocol) { + this.name = name; + this.protocol = protocol; + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/common/serializer/AsteriskSerializer.java b/connector/src/main/java/org/geysermc/connector/common/serializer/AsteriskSerializer.java new file mode 100644 index 00000000..3fac2e08 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/common/serializer/AsteriskSerializer.java @@ -0,0 +1,76 @@ +/* + * 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.common.serializer; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.ContextualSerializer; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +import java.io.IOException; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Optional; + +public class AsteriskSerializer extends StdSerializer implements ContextualSerializer { + @Target({ElementType.FIELD}) + @Retention(RetentionPolicy.RUNTIME) + @JacksonAnnotationsInside + @JsonSerialize(using = AsteriskSerializer.class) + public @interface Asterisk { + String value() default "***"; + } + + String asterisk; + + public AsteriskSerializer() { + super(Object.class); + } + + public AsteriskSerializer(String asterisk) { + super(Object.class); + this.asterisk = asterisk; + } + + @Override + public JsonSerializer createContextual(SerializerProvider serializerProvider, BeanProperty property) { + Optional anno = Optional.ofNullable(property) + .map(prop -> prop.getAnnotation(Asterisk.class)); + return new AsteriskSerializer(anno.map(Asterisk::value).orElse(null)); + } + + @Override + public void serialize(Object obj, JsonGenerator gen, SerializerProvider prov) throws IOException { + gen.writeString(asterisk); + } +} 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 5ea942c1..5727a902 100644 --- a/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java @@ -28,6 +28,8 @@ package org.geysermc.connector.configuration; import org.geysermc.connector.GeyserLogger; +import org.geysermc.connector.utils.LanguageUtils; + import java.nio.file.Path; import java.util.Map; @@ -111,9 +113,9 @@ public interface GeyserConfiguration { static void checkGeyserConfiguration(GeyserConfiguration geyserConfig, GeyserLogger geyserLogger) { if (geyserConfig.getConfigVersion() < CURRENT_CONFIG_VERSION) { - geyserLogger.warning("Your Geyser config is out of date! Please regenerate your config when possible."); + geyserLogger.warning(LanguageUtils.getLocaleStringLog("geyser.bootstrap.config.outdated")); } else if (geyserConfig.getConfigVersion() > CURRENT_CONFIG_VERSION) { - geyserLogger.warning("Your Geyser config is too new! Errors may occur."); + geyserLogger.warning(LanguageUtils.getLocaleStringLog("geyser.bootstrap.config.too_new")); } } } 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 576e5ed0..867de9ad 100644 --- a/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java @@ -30,6 +30,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.Setter; +import org.geysermc.connector.common.serializer.AsteriskSerializer; import java.nio.file.Path; import java.util.Map; @@ -111,16 +112,16 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration @Setter private int port; - private String motd1; - private String motd2; - @JsonProperty("auth-type") private String authType; } @Getter public static class UserAuthenticationInfo implements IUserAuthenticationInfo { + @AsteriskSerializer.Asterisk() private String email; + + @AsteriskSerializer.Asterisk() private String password; } diff --git a/connector/src/main/java/org/geysermc/connector/dump/BootstrapDumpInfo.java b/connector/src/main/java/org/geysermc/connector/dump/BootstrapDumpInfo.java new file mode 100644 index 00000000..04495b49 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/dump/BootstrapDumpInfo.java @@ -0,0 +1,63 @@ +/* + * 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.dump; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.geysermc.connector.common.PlatformType; +import org.geysermc.connector.GeyserConnector; + +import java.util.List; + +@Getter +public class BootstrapDumpInfo { + + private PlatformType platform; + + public BootstrapDumpInfo() { + this.platform = GeyserConnector.getInstance().getPlatformType(); + } + + @Getter + @AllArgsConstructor + public class PluginInfo { + + public boolean enabled; + public String name; + public String version; + public String main; + public List authors; + } + + @Getter + @AllArgsConstructor + public class ListenerInfo { + + public String ip; + public int port; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/dump/DumpInfo.java b/connector/src/main/java/org/geysermc/connector/dump/DumpInfo.java new file mode 100644 index 00000000..6d4b83db --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/dump/DumpInfo.java @@ -0,0 +1,125 @@ +/* + * 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.dump; + +import com.github.steveice10.mc.protocol.MinecraftConstants; +import lombok.Getter; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.configuration.GeyserConfiguration; +import org.geysermc.connector.utils.DockerCheck; +import org.geysermc.connector.utils.FileUtils; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.Properties; + +@Getter +public class DumpInfo { + + private final DumpInfo.VersionInfo versionInfo; + private Properties gitInfo; + private final GeyserConfiguration config; + private final BootstrapDumpInfo bootstrapInfo; + + public DumpInfo() { + try { + this.gitInfo = new Properties(); + this.gitInfo.load(FileUtils.getResource("git.properties")); + } catch (IOException ignored) { } + + this.config = GeyserConnector.getInstance().getConfig(); + + this.versionInfo = new DumpInfo.VersionInfo(); + this.bootstrapInfo = GeyserConnector.getInstance().getBootstrap().getDumpInfo(); + } + + @Getter + public class VersionInfo { + + private final String name; + private final String version; + private final String javaVersion; + private final String architecture; + private final String operatingSystem; + + private final NetworkInfo network; + private final MCInfo mcInfo; + + VersionInfo() { + this.name = GeyserConnector.NAME; + this.version = GeyserConnector.VERSION; + this.javaVersion = System.getProperty("java.version"); + this.architecture = System.getProperty("os.arch"); // Usually gives Java architecture but still may be helpful. + this.operatingSystem = System.getProperty("os.name"); + + this.network = new NetworkInfo(); + this.mcInfo = new MCInfo(); + } + } + + @Getter + public static class NetworkInfo { + + private String internalIP; + private final boolean dockerCheck; + + NetworkInfo() { + try { + // This is the most reliable for getting the main local IP + Socket socket = new Socket(); + socket.connect(new InetSocketAddress("geysermc.org", 80)); + this.internalIP = socket.getLocalAddress().getHostAddress(); + } catch (IOException e1) { + try { + // Fallback to the normal way of getting the local IP + this.internalIP = InetAddress.getLocalHost().getHostAddress(); + } catch (UnknownHostException ignored) { } + } + + this.dockerCheck = DockerCheck.checkBasic(); + } + } + + @Getter + public static class MCInfo { + + private final String bedrockVersion; + private final int bedrockProtocol; + private final String javaVersion; + private final int javaProtocol; + + MCInfo() { + this.bedrockVersion = GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion(); + this.bedrockProtocol = GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion(); + this.javaVersion = MinecraftConstants.GAME_VERSION; + this.javaProtocol = MinecraftConstants.PROTOCOL_VERSION; + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java b/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java index fa089707..f174747b 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/AbstractArrowEntity.java @@ -27,7 +27,7 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java b/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java index 79e67f34..21861589 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/AreaEffectCloudEntity.java @@ -28,7 +28,7 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.world.particle.Particle; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +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.effect.EffectRegistry; @@ -42,19 +42,19 @@ public class AreaEffectCloudEntity extends Entity { metadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, 600); // This disabled client side shrink of the cloud - metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS_PER_TICK, 0.0f); + metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, 0.0f); } @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 7) { - metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, (float) entityMetadata.getValue()); + metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, entityMetadata.getValue()); metadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * (float) entityMetadata.getValue()); } else if (entityMetadata.getId() == 10) { Particle particle = (Particle) entityMetadata.getValue(); metadata.put(EntityData.AREA_EFFECT_CLOUD_PARTICLE_ID, EffectRegistry.getParticleString(particle.getType())); } else if (entityMetadata.getId() == 8) { - metadata.put(EntityData.POTION_COLOR, entityMetadata.getValue()); + metadata.put(EntityData.POTION_AUX_VALUE, entityMetadata.getValue()); } super.updateBedrockMetadata(entityMetadata, session); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java b/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java index a59cd08f..c067416d 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java @@ -27,7 +27,7 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -92,7 +92,7 @@ public class BoatEntity extends Entity { } else if (entityMetadata.getId() == 11) { isPaddlingLeft = (boolean) entityMetadata.getValue(); if (!isPaddlingLeft) { - metadata.put(EntityData.PADDLE_TIME_LEFT, 0f); + metadata.put(EntityData.ROW_TIME_LEFT, 0f); } else { // Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing @@ -106,7 +106,7 @@ public class BoatEntity extends Entity { else if (entityMetadata.getId() == 12) { isPaddlingRight = (boolean) entityMetadata.getValue(); if (!isPaddlingRight) { - metadata.put(EntityData.PADDLE_TIME_RIGHT, 0f); + metadata.put(EntityData.ROW_TIME_RIGHT, 0f); } else { paddleTimeRight = 0f; session.getConnector().getGeneralThreadPool().execute(() -> @@ -124,7 +124,7 @@ public class BoatEntity extends Entity { public void updateLeftPaddle(GeyserSession session, EntityMetadata entityMetadata) { if (isPaddlingLeft) { paddleTimeLeft += ROWING_SPEED; - metadata.put(EntityData.PADDLE_TIME_LEFT, paddleTimeLeft); + metadata.put(EntityData.ROW_TIME_LEFT, paddleTimeLeft); super.updateBedrockMetadata(entityMetadata, session); session.getConnector().getGeneralThreadPool().schedule(() -> updateLeftPaddle(session, entityMetadata), @@ -136,7 +136,7 @@ public class BoatEntity extends Entity { public void updateRightPaddle(GeyserSession session, EntityMetadata entityMetadata) { if (isPaddlingRight) { paddleTimeRight += ROWING_SPEED; - metadata.put(EntityData.PADDLE_TIME_RIGHT, paddleTimeRight); + metadata.put(EntityData.ROW_TIME_RIGHT, paddleTimeRight); super.updateBedrockMetadata(entityMetadata, session); session.getConnector().getGeneralThreadPool().schedule(() -> updateRightPaddle(session, entityMetadata), diff --git a/connector/src/main/java/org/geysermc/connector/entity/DefaultBlockMinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/DefaultBlockMinecartEntity.java index b774af98..dda4577d 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/DefaultBlockMinecartEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/DefaultBlockMinecartEntity.java @@ -27,7 +27,7 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +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; @@ -45,7 +45,7 @@ public class DefaultBlockMinecartEntity extends MinecartEntity { super(entityId, geyserId, entityType, position, motion, rotation); updateDefaultBlockMetadata(); - metadata.put(EntityData.HAS_DISPLAY, (byte) 1); + metadata.put(EntityData.CUSTOM_DISPLAY, (byte) 1); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java b/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java index 727df90c..4b665683 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/EnderCrystalEntity.java @@ -29,8 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat 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.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; 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 d5ae391c..ffe13a50 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -32,17 +32,17 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.player.Hand; import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.mc.protocol.data.message.TextMessage; import com.github.steveice10.mc.protocol.data.message.TranslationMessage; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityDataMap; -import com.nukkitx.protocol.bedrock.data.EntityFlag; -import com.nukkitx.protocol.bedrock.data.EntityFlags; +import com.nukkitx.protocol.bedrock.data.AttributeData; +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.entity.EntityFlags; import com.nukkitx.protocol.bedrock.packet.*; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import lombok.Getter; @@ -68,7 +68,7 @@ public class Entity { protected long entityId; protected long geyserId; - protected int dimension; + protected String dimension; protected Vector3f position; protected Vector3f motion; @@ -101,15 +101,15 @@ public class Entity { this.rotation = rotation; this.valid = false; - this.dimension = 0; + this.dimension = "minecraft:overworld"; setPosition(position); metadata.put(EntityData.SCALE, 1f); metadata.put(EntityData.COLOR, 0); - metadata.put(EntityData.MAX_AIR, (short) 300); - metadata.put(EntityData.AIR, (short) 0); - metadata.put(EntityData.LEAD_HOLDER_EID, -1L); + metadata.put(EntityData.MAX_AIR_SUPPLY, (short) 300); + metadata.put(EntityData.AIR_SUPPLY, (short) 0); + metadata.put(EntityData.LEASH_HOLDER_EID, -1L); metadata.put(EntityData.BOUNDING_BOX_HEIGHT, entityType.getHeight()); metadata.put(EntityData.BOUNDING_BOX_WIDTH, entityType.getWidth()); EntityFlags flags = new EntityFlags(); @@ -146,6 +146,13 @@ public class Entity { public boolean despawnEntity(GeyserSession session) { if (!valid) return true; + for (long passenger : passengers) { // Make sure all passengers on the despawned entity are updated + Entity entity = session.getEntityCache().getEntityByJavaId(passenger); + if (entity == null) continue; + entity.getMetadata().getOrCreateFlags().setFlag(EntityFlag.RIDING, false); + entity.updateBedrockMetadata(session); + } + RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket(); removeEntityPacket.setUniqueEntityId(geyserId); session.sendUpstreamPacket(removeEntityPacket); @@ -241,7 +248,7 @@ public class Entity { public void updateBedrockAttributes(GeyserSession session) { if (!valid) return; - List attributes = new ArrayList<>(); + List attributes = new ArrayList<>(); for (Map.Entry entry : this.attributes.entrySet()) { if (!entry.getValue().getType().isBedrockAttribute()) continue; @@ -260,7 +267,7 @@ public class Entity { case 0: if (entityMetadata.getType() == MetadataType.BYTE) { byte xd = (byte) entityMetadata.getValue(); - metadata.getFlags().setFlag(EntityFlag.ON_FIRE, (xd & 0x01) == 0x01); + metadata.getFlags().setFlag(EntityFlag.ON_FIRE, ((xd & 0x01) == 0x01) && !metadata.getFlags().getFlag(EntityFlag.FIRE_IMMUNE)); // Otherwise immune entities sometimes flicker onfire metadata.getFlags().setFlag(EntityFlag.SNEAKING, (xd & 0x02) == 0x02); metadata.getFlags().setFlag(EntityFlag.SPRINTING, (xd & 0x08) == 0x08); metadata.getFlags().setFlag(EntityFlag.SWIMMING, ((xd & 0x10) == 0x10) && metadata.getFlags().getFlag(EntityFlag.SPRINTING)); // Otherwise swimming is enabled on older servers @@ -292,7 +299,7 @@ public class Entity { } } else if (session.getPlayerEntity().getEntityId() == entityId && !metadata.getFlags().getFlag(EntityFlag.SNEAKING) && metadata.getFlags().getFlag(EntityFlag.BLOCKING)) { metadata.getFlags().setFlag(EntityFlag.BLOCKING, false); - metadata.getFlags().setFlag(EntityFlag.DISABLE_BLOCKING, true); + metadata.getFlags().setFlag(EntityFlag.IS_AVOIDING_BLOCK, true); //TODO: CHECK ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, new Position(0, 0, 0), BlockFace.DOWN); session.sendDownstreamPacket(releaseItemPacket); } @@ -300,9 +307,9 @@ public class Entity { break; case 1: // Air/bubbles if ((int) entityMetadata.getValue() == 300) { - metadata.put(EntityData.AIR, (short) 0); // Otherwise the bubble counter remains in the UI + metadata.put(EntityData.AIR_SUPPLY, (short) 0); // Otherwise the bubble counter remains in the UI } else { - metadata.put(EntityData.AIR, (short) (int) entityMetadata.getValue()); + metadata.put(EntityData.AIR_SUPPLY, (short) (int) entityMetadata.getValue()); } break; case 2: // custom name @@ -318,7 +325,7 @@ public class Entity { break; case 3: // is custom name visible if (!this.is(PlayerEntity.class)) - metadata.put(EntityData.ALWAYS_SHOW_NAMETAG, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); + metadata.put(EntityData.NAMETAG_ALWAYS_SHOW, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); break; case 4: // silent metadata.getFlags().setFlag(EntityFlag.SILENT, (boolean) entityMetadata.getValue()); @@ -330,18 +337,18 @@ public class Entity { if (entityMetadata.getValue().equals(Pose.SLEEPING)) { metadata.getFlags().setFlag(EntityFlag.SLEEPING, true); // Has to be a byte or it does not work - metadata.put(EntityData.CAN_START_SLEEP, (byte) 2); + metadata.put(EntityData.PLAYER_FLAGS, (byte) 2); //TODO: CHECK if (entityId == session.getPlayerEntity().getEntityId()) { Vector3i lastInteractionPos = session.getLastInteractionPosition(); - metadata.put(EntityData.BED_RESPAWN_POS, lastInteractionPos); + metadata.put(EntityData.BED_POSITION, lastInteractionPos); if (session.getConnector().getConfig().isCacheChunks()) { - BlockState bed = session.getConnector().getWorldManager().getBlockAt(session, lastInteractionPos.getX(), + 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_RESPAWN_POS, Vector3i.from(position.getFloorX(), position.getFloorY() - 2, position.getFloorZ())); + 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); @@ -349,7 +356,7 @@ public class Entity { metadata.getFlags().setFlag(EntityFlag.SLEEPING, false); metadata.put(EntityData.BOUNDING_BOX_WIDTH, getEntityType().getWidth()); metadata.put(EntityData.BOUNDING_BOX_HEIGHT, getEntityType().getHeight()); - metadata.put(EntityData.CAN_START_SLEEP, (byte) 0); + metadata.put(EntityData.PLAYER_FLAGS, (byte) 0); } break; case 7: // blocking diff --git a/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java b/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java index bfd3e1ca..c830d259 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ExpOrbEntity.java @@ -26,7 +26,7 @@ package org.geysermc.connector.entity; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/FallingBlockEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FallingBlockEntity.java index 59e1d408..54757b71 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FallingBlockEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FallingBlockEntity.java @@ -26,7 +26,7 @@ package org.geysermc.connector.entity; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.translators.world.block.BlockTranslator; diff --git a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java index 1db4f757..cf49dc5f 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FireworkEntity.java @@ -31,8 +31,10 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; +import com.nukkitx.nbt.NbtType; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -49,7 +51,6 @@ public class FireworkEntity extends Entity { super(entityId, geyserId, entityType, position, motion, rotation); } - @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 7) { @@ -62,19 +63,19 @@ public class FireworkEntity extends Entity { CompoundTag fireworks = tag.get("Fireworks"); - CompoundTagBuilder fireworksBuilder = CompoundTagBuilder.builder(); + NbtMapBuilder fireworksBuilder = NbtMap.builder(); if (fireworks.get("Flight") != null) { - fireworksBuilder.byteTag("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue())); + fireworksBuilder.putByte("Flight", MathUtils.convertByte(fireworks.get("Flight").getValue())); } - List explosions = new ArrayList<>(); + List explosions = new ArrayList<>(); if (fireworks.get("Explosions") != null) { for (Tag effect : ((ListTag) fireworks.get("Explosions")).getValue()) { CompoundTag effectData = (CompoundTag) effect; - CompoundTagBuilder effectBuilder = CompoundTagBuilder.builder(); + NbtMapBuilder effectBuilder = NbtMap.builder(); if (effectData.get("Type") != null) { - effectBuilder.byteTag("FireworkType", MathUtils.convertByte(effectData.get("Type").getValue())); + effectBuilder.putByte("FireworkType", MathUtils.convertByte(effectData.get("Type").getValue())); } if (effectData.get("Colors") != null) { @@ -86,7 +87,7 @@ public class FireworkEntity extends Entity { colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); } - effectBuilder.byteArrayTag("FireworkColor", colors); + effectBuilder.putByteArray("FireworkColor", colors); } if (effectData.get("FadeColors") != null) { @@ -98,24 +99,24 @@ public class FireworkEntity extends Entity { colors[i++] = FireworkColor.fromJavaID(color).getBedrockID(); } - effectBuilder.byteArrayTag("FireworkFade", colors); + effectBuilder.putByteArray("FireworkFade", colors); } if (effectData.get("Trail") != null) { - effectBuilder.byteTag("FireworkTrail", MathUtils.convertByte(effectData.get("Trail").getValue())); + effectBuilder.putByte("FireworkTrail", MathUtils.convertByte(effectData.get("Trail").getValue())); } if (effectData.get("Flicker") != null) { - effectBuilder.byteTag("FireworkFlicker", MathUtils.convertByte(effectData.get("Flicker").getValue())); + effectBuilder.putByte("FireworkFlicker", MathUtils.convertByte(effectData.get("Flicker").getValue())); } - explosions.add(effectBuilder.buildRootTag()); + explosions.add(effectBuilder.build()); } } - fireworksBuilder.tag(new com.nukkitx.nbt.tag.ListTag<>("Explosions", com.nukkitx.nbt.tag.CompoundTag.class, explosions)); + fireworksBuilder.putList("Explosions", NbtType.COMPOUND, explosions); - metadata.put(EntityData.DISPLAY_ITEM, CompoundTagBuilder.builder().tag(fireworksBuilder.build("Fireworks")).buildRootTag()); + metadata.put(EntityData.DISPLAY_ITEM, NbtMap.builder().put("Fireworks", fireworksBuilder.build())); } else if (entityMetadata.getId() == 8 && !entityMetadata.getValue().equals(OptionalInt.empty()) && ((OptionalInt) entityMetadata.getValue()).getAsInt() == session.getPlayerEntity().getEntityId()) { //Checks if the firework has an entity ID (used when a player is gliding) and checks to make sure the player that is gliding is the one getting sent the packet or else every player near the gliding player will boost too. PlayerEntity entity = session.getPlayerEntity(); diff --git a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java index 1b648f7c..4d0eb202 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FishingHookEntity.java @@ -28,7 +28,7 @@ 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.object.ProjectileData; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -37,7 +37,7 @@ public class FishingHookEntity extends Entity { public FishingHookEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, ProjectileData data) { super(entityId, geyserId, entityType, position, motion, rotation); - for (GeyserSession session : GeyserConnector.getInstance().getPlayers().values()) { + for (GeyserSession session : GeyserConnector.getInstance().getPlayers()) { Entity entity = session.getEntityCache().getEntityByJavaId(data.getOwnerId()); if (entity == null && session.getPlayerEntity().getEntityId() == data.getOwnerId()) { entity = session.getPlayerEntity(); @@ -63,6 +63,8 @@ public class FishingHookEntity extends Entity { } } + //TODO Is ID 8 needed? + super.updateBedrockMetadata(entityMetadata, session); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java index 29ade193..8f0d97b0 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/FurnaceMinecartEntity.java @@ -27,7 +27,7 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +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; 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 3680945c..392cec24 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/ItemFrameEntity.java @@ -30,9 +30,9 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.object.HangingDirection; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.StartGamePacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; @@ -66,21 +66,21 @@ public class ItemFrameEntity extends Entity { /** * Cached item frame's Bedrock compound tag. */ - private CompoundTag cachedTag; + private NbtMap cachedTag; public ItemFrameEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation, HangingDirection direction) { super(entityId, geyserId, entityType, position, motion, rotation); - CompoundTagBuilder builder = CompoundTag.builder(); - builder.tag(CompoundTag.builder() - .stringTag("name", "minecraft:frame") - .intTag("version", BlockTranslator.getBlockStateVersion()) - .tag(CompoundTag.builder() - .intTag("facing_direction", direction.ordinal()) - .byteTag("item_frame_map_bit", (byte) 0) - .build("states")) - .build("block")); - builder.shortTag("id", (short) 199); - bedrockRuntimeId = BlockTranslator.getItemFrame(builder.buildRootTag()); + NbtMapBuilder builder = NbtMap.builder(); + NbtMapBuilder blockBuilder = NbtMap.builder() + .putString("name", "minecraft:frame") + .putInt("version", BlockTranslator.getBlockStateVersion()); + blockBuilder.put("states", NbtMap.builder() + .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()); bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ()); } @@ -100,7 +100,7 @@ public class ItemFrameEntity extends Entity { if (entityMetadata.getId() == 7 && entityMetadata.getValue() != null) { ItemData itemData = ItemTranslator.translateToBedrock(session, (ItemStack) entityMetadata.getValue()); ItemEntry itemEntry = ItemRegistry.getItem((ItemStack) entityMetadata.getValue()); - CompoundTagBuilder builder = CompoundTag.builder(); + NbtMapBuilder builder = NbtMap.builder(); String blockName = ""; for (StartGamePacket.ItemEntry startGamePacketItemEntry : ItemRegistry.ITEMS) { @@ -110,17 +110,17 @@ public class ItemFrameEntity extends Entity { } } - builder.byteTag("Count", (byte) itemData.getCount()); + builder.putByte("Count", (byte) itemData.getCount()); if (itemData.getTag() != null) { - builder.tag(itemData.getTag().toBuilder().build("tag")); + builder.put("tag", itemData.getTag().toBuilder().build()); } - builder.shortTag("Damage", itemData.getDamage()); - builder.stringTag("Name", blockName); - CompoundTagBuilder tag = getDefaultTag().toBuilder(); - tag.tag(builder.build("Item")); - tag.floatTag("ItemDropChance", 1.0f); - tag.floatTag("ItemRotation", rotation); - cachedTag = tag.buildRootTag(); + builder.putShort("Damage", itemData.getDamage()); + builder.putString("Name", blockName); + NbtMapBuilder tag = getDefaultTag().toBuilder(); + tag.put("Item", builder.build()); + tag.putFloat("ItemDropChance", 1.0f); + tag.putFloat("ItemRotation", rotation); + cachedTag = tag.build(); updateBlock(session); } else if (entityMetadata.getId() == 7 && entityMetadata.getValue() == null && cachedTag != null) { @@ -133,9 +133,9 @@ public class ItemFrameEntity extends Entity { updateBlock(session); return; } - CompoundTagBuilder builder = cachedTag.toBuilder(); - builder.floatTag("ItemRotation", rotation); - cachedTag = builder.buildRootTag(); + NbtMapBuilder builder = cachedTag.toBuilder(); + builder.putFloat("ItemRotation", rotation); + cachedTag = builder.build(); updateBlock(session); } else { @@ -150,7 +150,7 @@ public class ItemFrameEntity extends Entity { updateBlockPacket.setBlockPosition(bedrockPosition); updateBlockPacket.setRuntimeId(0); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); session.sendUpstreamPacket(updateBlockPacket); session.getItemFrameCache().remove(position, entityId); @@ -158,14 +158,14 @@ public class ItemFrameEntity extends Entity { return true; } - private CompoundTag getDefaultTag() { - CompoundTagBuilder builder = CompoundTag.builder(); - builder.intTag("x", bedrockPosition.getX()); - builder.intTag("y", bedrockPosition.getY()); - builder.intTag("z", bedrockPosition.getZ()); - builder.byteTag("isMovable", (byte) 1); - builder.stringTag("id", "ItemFrame"); - return builder.buildRootTag(); + private NbtMap getDefaultTag() { + NbtMapBuilder builder = NbtMap.builder(); + builder.putInt("x", bedrockPosition.getX()); + builder.putInt("y", bedrockPosition.getY()); + builder.putInt("z", bedrockPosition.getZ()); + builder.putByte("isMovable", (byte) 1); + builder.putString("id", "ItemFrame"); + return builder.build(); } /** @@ -178,7 +178,7 @@ public class ItemFrameEntity extends Entity { updateBlockPacket.setBlockPosition(bedrockPosition); updateBlockPacket.setRuntimeId(bedrockRuntimeId); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); session.sendUpstreamPacket(updateBlockPacket); 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 f5aa4a54..07a09fa1 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/LivingEntity.java @@ -27,17 +27,23 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.data.AttributeData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.MobArmorEquipmentPacket; import com.nukkitx.protocol.bedrock.packet.MobEquipmentPacket; - +import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket; import lombok.Getter; import lombok.Setter; - +import org.geysermc.connector.entity.attribute.AttributeType; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.AttributeUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; @Getter @Setter @@ -58,13 +64,13 @@ public class LivingEntity extends Entity { public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { switch (entityMetadata.getId()) { case 8: - metadata.put(EntityData.HEALTH, (float) entityMetadata.getValue()); + metadata.put(EntityData.HEALTH, entityMetadata.getValue()); break; case 9: - metadata.put(EntityData.POTION_COLOR, (int) entityMetadata.getValue()); + metadata.put(EntityData.POTION_AUX_VALUE, entityMetadata.getValue()); //TODO: CHECK THIS AND THE BOTTOM ONE break; case 10: - metadata.put(EntityData.POTION_AMBIENT, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); + metadata.put(EntityData.EFFECT_AMBIENT, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); break; } @@ -100,4 +106,38 @@ public class LivingEntity extends Entity { session.sendUpstreamPacket(handPacket); session.sendUpstreamPacket(offHandPacket); } + + @Override + public void updateBedrockAttributes(GeyserSession session) { + if (!valid) return; + + float maxHealth = this.attributes.containsKey(AttributeType.MAX_HEALTH) ? this.attributes.get(AttributeType.MAX_HEALTH).getValue() : getDefaultMaxHealth(); + + List attributes = new ArrayList<>(); + for (Map.Entry entry : this.attributes.entrySet()) { + if (!entry.getValue().getType().isBedrockAttribute()) + continue; + if (entry.getValue().getType() == AttributeType.HEALTH) { + // Add health attribute to properly show hearts when mounting + // TODO: Not a perfect system, since it led to respawn bugs + attributes.add(new AttributeData("minecraft:health", 0.0f, maxHealth, metadata.getFloat(EntityData.HEALTH, 20f), maxHealth)); + continue; + } + + attributes.add(AttributeUtils.getBedrockAttribute(entry.getValue())); + } + + UpdateAttributesPacket updateAttributesPacket = new UpdateAttributesPacket(); + updateAttributesPacket.setRuntimeEntityId(geyserId); + updateAttributesPacket.setAttributes(attributes); + session.sendUpstreamPacket(updateAttributesPacket); + } + + /** + * Used for the health visual when mounting an entity. + * @return the default maximum health for the entity. + */ + protected float getDefaultMaxHealth() { + return 20f; + } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java index a67c0be5..72b5ee82 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/MinecartEntity.java @@ -27,7 +27,7 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +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; @@ -69,7 +69,7 @@ public class MinecartEntity extends Entity { // If the custom block should be enabled if (entityMetadata.getId() == 12) { // Needs a byte based off of Java's boolean - metadata.put(EntityData.HAS_DISPLAY, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); + metadata.put(EntityData.CUSTOM_DISPLAY, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0)); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java index 00cfc8b5..d509b41f 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java @@ -52,7 +52,7 @@ public class PaintingEntity extends Entity { AddPaintingPacket addPaintingPacket = new AddPaintingPacket(); addPaintingPacket.setUniqueEntityId(geyserId); addPaintingPacket.setRuntimeEntityId(geyserId); - addPaintingPacket.setName(paintingName.getBedrockName()); + addPaintingPacket.setMotive(paintingName.getBedrockName()); //TODO: This is what it's called now? addPaintingPacket.setPosition(fixOffset(true)); addPaintingPacket.setDirection(direction); session.sendUpstreamPacket(addPaintingPacket); 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 594f139a..fe4dc905 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -26,27 +26,32 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.auth.data.GameProfile; -import com.github.steveice10.mc.protocol.data.game.entity.Effect; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; 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.protocol.bedrock.data.*; +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.EntityLinkData; import com.nukkitx.protocol.bedrock.packet.*; - import lombok.Getter; import lombok.Setter; - import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.entity.attribute.Attribute; +import org.geysermc.connector.entity.attribute.AttributeType; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; -import org.geysermc.connector.scoreboard.Team; -import org.geysermc.connector.utils.MessageUtils; 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.utils.SkinUtils; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -99,7 +104,7 @@ public class PlayerEntity extends LivingEntity { long linkedEntityId = session.getEntityCache().getCachedPlayerEntityLink(entityId); if (linkedEntityId != -1) { - addPlayerPacket.getEntityLinks().add(new EntityLink(session.getEntityCache().getEntityByJavaId(linkedEntityId).getGeyserId(), geyserId, EntityLink.Type.RIDER, false)); + addPlayerPacket.getEntityLinks().add(new EntityLinkData(session.getEntityCache().getEntityByJavaId(linkedEntityId).getGeyserId(), geyserId, EntityLinkData.Type.RIDER, false)); } valid = true; @@ -194,7 +199,7 @@ public class PlayerEntity extends LivingEntity { movePlayerPacket.setRuntimeEntityId(geyserId); movePlayerPacket.setPosition(position); movePlayerPacket.setRotation(getBedrockRotation()); - movePlayerPacket.setMode(MovePlayerPacket.Mode.ROTATION); + movePlayerPacket.setMode(MovePlayerPacket.Mode.HEAD_ROTATION); session.sendUpstreamPacket(movePlayerPacket); } @@ -212,7 +217,7 @@ public class PlayerEntity extends LivingEntity { movePlayerPacket.setPosition(position); movePlayerPacket.setRotation(getBedrockRotation()); movePlayerPacket.setOnGround(isOnGround); - movePlayerPacket.setMode(MovePlayerPacket.Mode.ROTATION); + movePlayerPacket.setMode(MovePlayerPacket.Mode.HEAD_ROTATION); session.sendUpstreamPacket(movePlayerPacket); } @@ -247,9 +252,9 @@ public class PlayerEntity extends LivingEntity { if (entityMetadata.getId() == 14) { UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); attributesPacket.setRuntimeEntityId(geyserId); - List attributes = new ArrayList<>(); + List attributes = new ArrayList<>(); // Setting to a higher maximum since plugins/datapacks can probably extend the Bedrock soft limit - attributes.add(new Attribute("minecraft:absorption", 0.0f, 1024f, (float) entityMetadata.getValue(), 0.0f)); + attributes.add(new AttributeData("minecraft:absorption", 0.0f, 1024f, (float) entityMetadata.getValue(), 0.0f)); attributesPacket.setAttributes(attributes); session.sendUpstreamPacket(attributesPacket); } @@ -269,8 +274,8 @@ public class PlayerEntity extends LivingEntity { parrot.getMetadata().put(EntityData.RIDER_ROTATION_LOCKED, 1); parrot.updateBedrockMetadata(session); SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); - EntityLink.Type type = (entityMetadata.getId() == 18) ? EntityLink.Type.RIDER : EntityLink.Type.PASSENGER; - linkPacket.setEntityLink(new EntityLink(geyserId, parrot.getGeyserId(), type, false)); + EntityLinkData.Type type = (entityMetadata.getId() == 18) ? EntityLinkData.Type.RIDER : EntityLinkData.Type.PASSENGER; + linkPacket.setEntityLink(new EntityLinkData(geyserId, parrot.getGeyserId(), type, false)); // Delay, or else spawned-in players won't get the link // TODO: Find a better solution. This problem also exists with item frames session.getConnector().getGeneralThreadPool().schedule(() -> session.sendUpstreamPacket(linkPacket), 500, TimeUnit.MILLISECONDS); @@ -292,4 +297,22 @@ public class PlayerEntity extends LivingEntity { } } } + + @Override + public void updateBedrockAttributes(GeyserSession session) { // TODO: Don't use duplicated code + if (!valid) return; + + List attributes = new ArrayList<>(); + for (Map.Entry entry : this.attributes.entrySet()) { + if (!entry.getValue().getType().isBedrockAttribute()) + continue; + + attributes.add(AttributeUtils.getBedrockAttribute(entry.getValue())); + } + + UpdateAttributesPacket updateAttributesPacket = new UpdateAttributesPacket(); + updateAttributesPacket.setRuntimeEntityId(geyserId); + updateAttributesPacket.setAttributes(attributes); + session.sendUpstreamPacket(updateAttributesPacket); + } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/SpawnerMinecartEntity.java b/connector/src/main/java/org/geysermc/connector/entity/SpawnerMinecartEntity.java index 6be138c0..56341b3b 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/SpawnerMinecartEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/SpawnerMinecartEntity.java @@ -26,7 +26,7 @@ package org.geysermc.connector.entity; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.translators.world.block.BlockTranslator; diff --git a/connector/src/main/java/org/geysermc/connector/entity/TNTEntity.java b/connector/src/main/java/org/geysermc/connector/entity/TNTEntity.java index 629c9e51..d2addbfb 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/TNTEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/TNTEntity.java @@ -28,8 +28,8 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; diff --git a/connector/src/main/java/org/geysermc/connector/entity/TridentEntity.java b/connector/src/main/java/org/geysermc/connector/entity/TridentEntity.java index 7c2442b0..4a9007ab 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/TridentEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/TridentEntity.java @@ -27,7 +27,7 @@ package org.geysermc.connector.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -39,7 +39,7 @@ public class TridentEntity extends AbstractArrowEntity { @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { - if (entityMetadata.getId() == 11) { + if (entityMetadata.getId() == 10) { metadata.getFlags().setFlag(EntityFlag.ENCHANTED, (boolean) entityMetadata.getValue()); } diff --git a/connector/src/main/java/org/geysermc/connector/entity/attribute/AttributeType.java b/connector/src/main/java/org/geysermc/connector/entity/attribute/AttributeType.java index 2061b895..1d692e2a 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/attribute/AttributeType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/attribute/AttributeType.java @@ -33,20 +33,20 @@ import lombok.Getter; public enum AttributeType { // Universal Attributes - FOLLOW_RANGE("generic.followRange", "minecraft:follow_range", 0f, 2048f, 32f), - KNOCKBACK_RESISTANCE("generic.knockbackResistance", "minecraft:knockback_resistance", 0f, 1f, 0f), - MOVEMENT_SPEED("generic.movementSpeed", "minecraft:movement", 0f, 1024f, 0.1f), - FLYING_SPEED("generic.flyingSpeed", "minecraft:movement", 0.0f, 1024.0f, 0.4000000059604645f), - ATTACK_DAMAGE("generic.attackDamage", "minecraft:attack_damage", 0f, 2048f, 1f), - HORSE_JUMP_STRENGTH("horse.jumpStrength", "minecraft:horse.jump_strength", 0.0f, 2.0f, 0.7f), + FOLLOW_RANGE("minecraft:generic.follow_range", "minecraft:follow_range", 0f, 2048f, 32f), + KNOCKBACK_RESISTANCE("minecraft:generic.knockback_resistance", "minecraft:knockback_resistance", 0f, 1f, 0f), + MOVEMENT_SPEED("minecraft:generic.movement_speed", "minecraft:movement", 0f, 1024f, 0.1f), + FLYING_SPEED("minecraft:generic.flying_speed", "minecraft:movement", 0.0f, 1024.0f, 0.4000000059604645f), + ATTACK_DAMAGE("minecraft:generic.attack_damage", "minecraft:attack_damage", 0f, 2048f, 1f), + HORSE_JUMP_STRENGTH("minecraft:horse.jump_strength", "minecraft:horse.jump_strength", 0.0f, 2.0f, 0.7f), // Java Attributes - ARMOR("generic.armor", null, 0f, 30f, 0f), - ARMOR_TOUGHNESS("generic.armorToughness", null, 0F, 20f, 0f), - ATTACK_KNOCKBACK("generic.attackKnockback", null, 1.5f, Float.MAX_VALUE, 0f), - ATTACK_SPEED("generic.attackSpeed", null, 0f, 1024f, 4f), - LUCK("generic.luck", null, -1024f, 1024f, 0f), - MAX_HEALTH("generic.maxHealth", null, 0f, 1024f, 20f), + ARMOR("minecraft:generic.armor", null, 0f, 30f, 0f), + ARMOR_TOUGHNESS("minecraft:generic.armor_toughness", null, 0F, 20f, 0f), + ATTACK_KNOCKBACK("minecraft:generic.attack_knockback", null, 1.5f, Float.MAX_VALUE, 0f), + ATTACK_SPEED("minecraft:generic.attack_speed", null, 0f, 1024f, 4f), + LUCK("minecraft:generic.luck", null, -1024f, 1024f, 0f), + MAX_HEALTH("minecraft:generic.max_health", null, 0f, 1024f, 20f), // Bedrock Attributes ABSORPTION(null, "minecraft:absorption", 0f, Float.MAX_VALUE, 0f), diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java index de5fa1b5..9c3e2084 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/AbstractFishEntity.java @@ -26,7 +26,7 @@ package org.geysermc.connector.entity.living; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; public class AbstractFishEntity extends WaterEntity { diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java index b90983f7..2175efcd 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java @@ -27,8 +27,8 @@ 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.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; 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 47faad36..07496093 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 @@ -28,7 +28,7 @@ package org.geysermc.connector.entity.living; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.LivingEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/InsentientEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/InsentientEntity.java index 2467dfe0..808eb3cb 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/InsentientEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/InsentientEntity.java @@ -28,7 +28,7 @@ package org.geysermc.connector.entity.living; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.LivingEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/SlimeEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/SlimeEntity.java index 26106f0a..2ee22de7 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/SlimeEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/SlimeEntity.java @@ -28,7 +28,7 @@ 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.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/WaterEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/WaterEntity.java index 69afd975..b0692eab 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/WaterEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/WaterEntity.java @@ -26,7 +26,7 @@ package org.geysermc.connector.entity.living; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.type.EntityType; public class WaterEntity extends CreatureEntity { @@ -34,6 +34,6 @@ public class WaterEntity extends CreatureEntity { public WaterEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); - metadata.put(EntityData.AIR, (short) 400); + metadata.put(EntityData.AIR_SUPPLY, (short) 400); } } 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 537a1251..c46f00fe 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,7 @@ 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.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; 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 a277f8ee..88c30cbf 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 @@ -27,8 +27,8 @@ 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.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java index 1c5dc975..36a67dbb 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/OcelotEntity.java @@ -27,7 +27,7 @@ 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.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; 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 f22815c6..7e555122 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,7 +27,7 @@ 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.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java index fd9fd999..9b9701f8 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java @@ -27,33 +27,18 @@ 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.Attribute; -import com.nukkitx.protocol.bedrock.data.EntityFlag; -import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket; -import org.geysermc.connector.entity.attribute.AttributeType; +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.AttributeUtils; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; public class PigEntity extends AnimalEntity { - // For updating the pig heart visual easier - private float health = 20f; - public PigEntity(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() == 8) { - health = (float) entityMetadata.getValue(); - updateBedrockAttributes(session); - } if (entityMetadata.getId() == 16) { metadata.getFlags().setFlag(EntityFlag.SADDLED, (boolean) entityMetadata.getValue()); @@ -62,23 +47,7 @@ public class PigEntity extends AnimalEntity { } @Override - public void updateBedrockAttributes(GeyserSession session) { - if (!valid) return; - - float maxHealth = attributes.containsKey(AttributeType.MAX_HEALTH) ? attributes.get(AttributeType.MAX_HEALTH).getValue() : 20f; - - List attributesLocal = new ArrayList<>(); - for (Map.Entry entry : this.attributes.entrySet()) { - if (!entry.getValue().getType().isBedrockAttribute()) - continue; - - attributesLocal.add(AttributeUtils.getBedrockAttribute(entry.getValue())); - } - attributesLocal.add(new Attribute("minecraft:health", 0.0f, maxHealth, health, maxHealth)); - - UpdateAttributesPacket updateAttributesPacket = new UpdateAttributesPacket(); - updateAttributesPacket.setRuntimeEntityId(geyserId); - updateAttributesPacket.setAttributes(attributesLocal); - session.sendUpstreamPacket(updateAttributesPacket); + protected float getDefaultMaxHealth() { + return 10f; } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java index 6011d513..2b09ca91 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PolarBearEntity.java @@ -27,7 +27,7 @@ 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.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PufferFishEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PufferFishEntity.java index d5503dc0..407708a5 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PufferFishEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PufferFishEntity.java @@ -27,7 +27,7 @@ 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.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.living.AbstractFishEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; 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 6bc64bfd..0b61713a 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 @@ -27,8 +27,8 @@ 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.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/SheepEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/SheepEntity.java index e2b1b979..464377ef 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/SheepEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/SheepEntity.java @@ -27,8 +27,8 @@ 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.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java new file mode 100644 index 00000000..ee6815d1 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/StriderEntity.java @@ -0,0 +1,86 @@ +/* + * 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.Entity; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +public class StriderEntity extends AnimalEntity { + + private boolean shaking = false; + + public StriderEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + + metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true); + metadata.getFlags().setFlag(EntityFlag.BREATHING, true); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 17) { + shaking = (boolean) entityMetadata.getValue(); + } + if (entityMetadata.getId() == 18) { + metadata.getFlags().setFlag(EntityFlag.SADDLED, (boolean) entityMetadata.getValue()); + } + + super.updateBedrockMetadata(entityMetadata, session); + } + + @Override + public void updateBedrockMetadata(GeyserSession session) { + // Make sure they are not shaking when riding another entity + // Needs to copy the parent state + if (metadata.getFlags().getFlag(EntityFlag.RIDING)) { + boolean parentShaking = false; + for (Entity ent : session.getEntityCache().getEntities().values()) { + if (ent.getPassengers().contains(entityId) && ent instanceof StriderEntity) { + parentShaking = ent.getMetadata().getFlags().getFlag(EntityFlag.SHAKING); + break; + } + } + + metadata.getFlags().setFlag(EntityFlag.BREATHING, !parentShaking); + metadata.getFlags().setFlag(EntityFlag.SHAKING, parentShaking); + } else { + metadata.getFlags().setFlag(EntityFlag.BREATHING, !shaking); + metadata.getFlags().setFlag(EntityFlag.SHAKING, shaking); + } + + // Update the passengers if we have any + for (long passenger : passengers) { + session.getEntityCache().getEntityByJavaId(passenger).updateBedrockMetadata(session); + } + + super.updateBedrockMetadata(session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java index a8866d7e..eadc3db0 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/TropicalFishEntity.java @@ -27,7 +27,7 @@ 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.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import lombok.AllArgsConstructor; import lombok.Getter; import org.geysermc.connector.entity.living.AbstractFishEntity; 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 3773011a..e08f9adf 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,24 +27,13 @@ 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.Attribute; -import com.nukkitx.protocol.bedrock.data.EntityFlag; -import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket; -import org.geysermc.connector.entity.attribute.AttributeType; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; 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.utils.AttributeUtils; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; public class AbstractHorseEntity extends AnimalEntity { - // For updating the horse visual easier - private float health = 20f; - public AbstractHorseEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); } @@ -52,11 +41,6 @@ public class AbstractHorseEntity extends AnimalEntity { @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { - if (entityMetadata.getId() == 8) { - health = (float) entityMetadata.getValue(); - updateBedrockAttributes(session); - } - if (entityMetadata.getId() == 16) { byte xd = (byte) entityMetadata.getValue(); metadata.getFlags().setFlag(EntityFlag.TAMED, (xd & 0x02) == 0x02); @@ -71,25 +55,4 @@ public class AbstractHorseEntity extends AnimalEntity { super.updateBedrockMetadata(entityMetadata, session); } - - @Override - public void updateBedrockAttributes(GeyserSession session) { - if (!valid) return; - - float maxHealth = attributes.containsKey(AttributeType.MAX_HEALTH) ? attributes.get(AttributeType.MAX_HEALTH).getValue() : 20f; - - List attributesLocal = new ArrayList<>(); - for (Map.Entry entry : this.attributes.entrySet()) { - if (!entry.getValue().getType().isBedrockAttribute()) - continue; - - attributesLocal.add(AttributeUtils.getBedrockAttribute(entry.getValue())); - } - attributesLocal.add(new Attribute("minecraft:health", 0.0f, maxHealth, health, maxHealth)); - - UpdateAttributesPacket updateAttributesPacket = new UpdateAttributesPacket(); - updateAttributesPacket.setRuntimeEntityId(geyserId); - updateAttributesPacket.setAttributes(attributesLocal); - session.sendUpstreamPacket(updateAttributesPacket); - } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/ChestedHorseEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/ChestedHorseEntity.java index df354357..7343f5e8 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/ChestedHorseEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/ChestedHorseEntity.java @@ -27,7 +27,7 @@ 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.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; 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 27f4b83c..da3ff349 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 @@ -27,8 +27,8 @@ 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.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java index d4d7b726..ddac4a63 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/LlamaEntity.java @@ -27,8 +27,8 @@ 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.EntityData; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.MobArmorEquipmentPacket; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java index b9505509..f0132673 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/horse/TraderLlamaEntity.java @@ -26,7 +26,7 @@ package org.geysermc.connector.entity.living.animal.horse; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; 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 de9bcb4e..067a360c 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 @@ -27,8 +27,8 @@ package org.geysermc.connector.entity.living.animal.tameable; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java index e02b3e7b..a867517a 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/ParrotEntity.java @@ -27,7 +27,7 @@ package org.geysermc.connector.entity.living.animal.tameable; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; 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 2d3e0b1d..2e8ab816 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 @@ -27,8 +27,8 @@ package org.geysermc.connector.entity.living.animal.tameable; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.living.animal.AnimalEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java index 118262dc..aa578acb 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/WolfEntity.java @@ -27,8 +27,8 @@ package org.geysermc.connector.entity.living.animal.tameable; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; @@ -40,11 +40,6 @@ public class WolfEntity extends TameableEntity { @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { - // "Begging" on wiki.vg, "Interested" in Nukkit - the tilt of the head - if (entityMetadata.getId() == 18) { - metadata.getFlags().setFlag(EntityFlag.INTERESTED, (boolean) entityMetadata.getValue()); - } - //Reset wolf color if (entityMetadata.getId() == 16) { byte xd = (byte) entityMetadata.getValue(); @@ -54,11 +49,17 @@ public class WolfEntity extends TameableEntity { } } + // "Begging" on wiki.vg, "Interested" in Nukkit - the tilt of the head + if (entityMetadata.getId() == 18) { + metadata.getFlags().setFlag(EntityFlag.INTERESTED, (boolean) entityMetadata.getValue()); + } + // Wolf collar color // Relies on EntityData.OWNER_EID being set in TameableEntity.java if (entityMetadata.getId() == 19 && !metadata.getFlags().getFlag(EntityFlag.ANGRY)) { metadata.put(EntityData.COLOR, (byte) (int) entityMetadata.getValue()); } + //TODO: Anger time int? 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 895f8cc1..a2fa1c49 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 @@ -28,7 +28,7 @@ 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.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import org.geysermc.connector.entity.type.EntityType; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/BlazeEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/BlazeEntity.java index 16836976..75fec18f 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/BlazeEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/BlazeEntity.java @@ -27,7 +27,7 @@ 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.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; 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 9b5c3822..3c3a76bd 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 @@ -27,7 +27,7 @@ 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.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ElderGuardianEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ElderGuardianEntity.java index fedd7980..76b1ba2c 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ElderGuardianEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ElderGuardianEntity.java @@ -27,7 +27,7 @@ package org.geysermc.connector.entity.living.monster; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; public class ElderGuardianEntity extends GuardianEntity { diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java index 394be544..aa2b4e02 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/EnderDragonEntity.java @@ -27,9 +27,9 @@ 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.Attribute; -import com.nukkitx.protocol.bedrock.data.EntityEventType; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.data.AttributeData; +import com.nukkitx.protocol.bedrock.data.entity.EntityEventType; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.packet.AddEntityPacket; import com.nukkitx.protocol.bedrock.packet.EntityEventPacket; import org.geysermc.connector.entity.living.InsentientEntity; @@ -76,7 +76,7 @@ public class EnderDragonEntity extends InsentientEntity { addEntityPacket.getMetadata().putAll(metadata); // Otherwise dragon is always 'dying' - addEntityPacket.getAttributes().add(new Attribute("minecraft:health", 0.0f, 200f, 200f, 200f)); + addEntityPacket.getAttributes().add(new AttributeData("minecraft:health", 0.0f, 200f, 200f, 200f)); valid = true; session.sendUpstreamPacket(addEntityPacket); diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/EndermanEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/EndermanEntity.java index 644181ab..914b2085 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/EndermanEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/EndermanEntity.java @@ -26,10 +26,9 @@ 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.world.block.BlockState; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; import org.geysermc.connector.network.translators.world.block.BlockTranslator; @@ -44,7 +43,7 @@ public class EndermanEntity extends MonsterEntity { public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { // Held block if (entityMetadata.getId() == 15) { - metadata.put(EntityData.ENDERMAN_HELD_ITEM_ID, BlockTranslator.getBedrockBlockId((BlockState) entityMetadata.getValue())); + metadata.put(EntityData.DISPLAY_ITEM, BlockTranslator.getBedrockBlockId((int) entityMetadata.getValue())); //TODO: Check } // 'Angry' - mouth open if (entityMetadata.getId() == 16) { diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/GiantEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GiantEntity.java index b9dc9e66..aa22d8d6 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/GiantEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GiantEntity.java @@ -26,7 +26,7 @@ package org.geysermc.connector.entity.living.monster; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.type.EntityType; public class GiantEntity extends MonsterEntity { diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java index 821faa85..aa9ce4ca 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/GuardianEntity.java @@ -27,7 +27,7 @@ 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.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; 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 new file mode 100644 index 00000000..78a420b8 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/PiglinEntity.java @@ -0,0 +1,59 @@ +/* + * 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 com.nukkitx.protocol.bedrock.data.entity.EntityFlag; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +public class PiglinEntity extends MonsterEntity { + + public PiglinEntity(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) { + boolean isBaby = (boolean) entityMetadata.getValue(); + if (isBaby) { + metadata.put(EntityData.SCALE, .55f); + metadata.getFlags().setFlag(EntityFlag.BABY, true); + } + } + if (entityMetadata.getId() == 17) { + metadata.getFlags().setFlag(EntityFlag.CHARGING, (boolean) entityMetadata.getValue()); + } + if (entityMetadata.getId() == 18) { + metadata.getFlags().setFlag(EntityFlag.DANCING, (boolean) entityMetadata.getValue()); + } + + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ShulkerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ShulkerEntity.java index bca9e689..8728547f 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ShulkerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ShulkerEntity.java @@ -30,7 +30,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.living.GolemEntity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/SpiderEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/SpiderEntity.java index 301145e6..f0ad6f05 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/SpiderEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/SpiderEntity.java @@ -27,7 +27,7 @@ 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.EntityFlag; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java index 005d0db3..8b864525 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/WitherEntity.java @@ -27,7 +27,7 @@ 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.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnWeatherEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZoglinEntity.java similarity index 57% rename from connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnWeatherEntityTranslator.java rename to connector/src/main/java/org/geysermc/connector/entity/living/monster/ZoglinEntity.java index c50686a0..4ea84211 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/spawn/JavaSpawnWeatherEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZoglinEntity.java @@ -23,30 +23,30 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.connector.network.translators.java.entity.spawn; +package org.geysermc.connector.entity.living.monster; -import org.geysermc.connector.entity.Entity; +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; -import org.geysermc.connector.network.translators.PacketTranslator; -import org.geysermc.connector.network.translators.Translator; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnWeatherEntityPacket; -import com.nukkitx.math.vector.Vector3f; +public class ZoglinEntity extends MonsterEntity { -@Translator(packet = ServerSpawnWeatherEntityPacket.class) -public class JavaSpawnWeatherEntityTranslator extends PacketTranslator { + public ZoglinEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } @Override - public void translate(ServerSpawnWeatherEntityPacket packet, GeyserSession session) { - Vector3f position = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); - - // Currently WeatherEntityType only has a lightning bolt - Entity entity = new Entity( - packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), - EntityType.LIGHTNING_BOLT, position, Vector3f.ZERO, Vector3f.ZERO - ); - - session.getEntityCache().spawnEntity(entity); + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 15) { + boolean isBaby = (boolean) entityMetadata.getValue(); + if (isBaby) { + metadata.put(EntityData.SCALE, .55f); + metadata.getFlags().setFlag(EntityFlag.BABY, true); + } + } + super.updateBedrockMetadata(entityMetadata, session); } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieEntity.java index 2ca212ff..218a2ca0 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieEntity.java @@ -27,8 +27,8 @@ 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.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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; diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombifiedPiglinEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombifiedPiglinEntity.java new file mode 100644 index 00000000..01693170 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombifiedPiglinEntity.java @@ -0,0 +1,39 @@ +/* + * 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.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; +import org.geysermc.connector.entity.type.EntityType; + +public class ZombifiedPiglinEntity extends ZombieEntity { + + public ZombifiedPiglinEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + + metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true); + } +} 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 3acc17c3..6bc1a1b0 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 @@ -68,7 +68,7 @@ public enum EntityType { CREEPER(CreeperEntity.class, 33, 1.7f, 0.6f, 0.6f, 1.62f), SKELETON(AbstractSkeletonEntity.class, 34, 1.8f, 0.6f, 0.6f, 1.62f), SPIDER(SpiderEntity.class, 35, 0.9f, 1.4f, 1.4f, 1f), - ZOMBIE_PIGMAN(MonsterEntity.class, 36, 1.8f, 0.6f, 0.6f, 1.62f), + ZOMBIFIED_PIGLIN(ZombifiedPiglinEntity.class, 36, 1.95f, 0.6f, 0.6f, 1.62f, "minecraft:zombie_pigman"), SLIME(SlimeEntity.class, 37, 0.51f), ENDERMAN(EndermanEntity.class, 38, 2.9f, 0.6f), SILVERFISH(MonsterEntity.class, 39, 0.3f, 0.4f), @@ -151,6 +151,10 @@ public enum EntityType { PANDA(PandaEntity.class, 113, 1.25f, 1.125f, 1.825f), 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"), //TODO - update entity metadata + HOGLIN(AnimalEntity.class, 124, 1.4f, 1.3965f, 1.3965f, 0f, "minecraft:hoglin"), //TODO + ZOGLIN(ZoglinEntity.class, 126, 1.4f, 1.3965f, 1.3965f, 0f, "minecraft:zoglin"), //TODO + PIGLIN(PiglinEntity.class, 123, 1.95f, 0.6f, 0.6f, 0f, "minecraft:piglin"), //TODO /** * Item frames are handled differently since they are a block in Bedrock. 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 49f81e3f..6ca9063c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/ConnectorServerEventHandler.java @@ -25,16 +25,19 @@ package org.geysermc.connector.network; -import com.github.steveice10.mc.protocol.data.message.Message; -import com.nukkitx.protocol.bedrock.*; +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; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.socket.DatagramPacket; -import org.geysermc.common.ping.GeyserPingInfo; -import org.geysermc.connector.ping.IGeyserPingPassthrough; -import org.geysermc.connector.configuration.GeyserConfiguration; +import org.geysermc.connector.common.ping.GeyserPingInfo; 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.utils.LanguageUtils; import java.net.InetSocketAddress; @@ -48,13 +51,13 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { @Override public boolean onConnectionRequest(InetSocketAddress inetSocketAddress) { - connector.getLogger().info(inetSocketAddress + " tried to connect!"); + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.attempt_connect", inetSocketAddress)); return true; } @Override public BedrockPong onQuery(InetSocketAddress inetSocketAddress) { - connector.getLogger().debug(inetSocketAddress + " has pinged you!"); + connector.getLogger().debug(LanguageUtils.getLocaleStringLog("geyser.network.pinged", inetSocketAddress)); GeyserConfiguration config = connector.getConfig(); @@ -72,8 +75,8 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { pong.setVersion(null); // Server tries to connect either way and it looks better pong.setIpv4Port(config.getBedrock().getPort()); - if (config.isPassthroughMotd() && pingInfo != null && pingInfo.motd != null) { - String[] motd = MessageUtils.getBedrockMessage(Message.fromString(pingInfo.motd)).split("\n"); + if (config.isPassthroughMotd() && pingInfo != null && pingInfo.getDescription() != null) { + String[] motd = MessageUtils.getBedrockMessage(MessageSerializer.fromString(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. @@ -85,8 +88,8 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { } if (config.isPassthroughPlayerCounts() && pingInfo != null) { - pong.setPlayerCount(pingInfo.currentPlayerCount); - pong.setMaximumPlayerCount(pingInfo.maxPlayerCount); + pong.setPlayerCount(pingInfo.getPlayers().getOnline()); + pong.setMaximumPlayerCount(pingInfo.getPlayers().getMax()); } else { pong.setPlayerCount(connector.getPlayers().size()); pong.setMaximumPlayerCount(config.getMaxPlayers()); @@ -105,15 +108,6 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler { public void onSessionCreation(BedrockServerSession bedrockServerSession) { bedrockServerSession.setLogging(true); bedrockServerSession.setPacketHandler(new UpstreamPacketHandler(connector, new GeyserSession(connector, bedrockServerSession))); - bedrockServerSession.addDisconnectHandler(disconnectReason -> { - connector.getLogger().info("Bedrock user with ip: " + bedrockServerSession.getAddress().getAddress() + " has disconnected for reason " + disconnectReason); - - GeyserSession player = connector.getPlayers().get(bedrockServerSession.getAddress()); - if (player != null) { - player.disconnect(disconnectReason.name()); - connector.removePlayer(player); - } - }); bedrockServerSession.setPacketCodec(GeyserConnector.BEDROCK_PACKET_CODEC); } diff --git a/connector/src/main/java/org/geysermc/connector/network/LoggingPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/LoggingPacketHandler.java index 91b3ebd4..c41c64c7 100644 --- a/connector/src/main/java/org/geysermc/connector/network/LoggingPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/LoggingPacketHandler.java @@ -628,12 +628,12 @@ public class LoggingPacketHandler implements BedrockPacketHandler { } @Override - public boolean handle(StructureTemplateDataExportRequestPacket packet) { + public boolean handle(StructureTemplateDataRequestPacket packet) { return defaultHandler(packet); } @Override - public boolean handle(StructureTemplateDataExportResponsePacket packet) { + public boolean handle(StructureTemplateDataResponsePacket packet) { return defaultHandler(packet); } @@ -756,4 +756,74 @@ public class LoggingPacketHandler implements BedrockPacketHandler { public boolean handle(MultiplayerSettingsPacket packet) { return defaultHandler(packet); } + + // 1.16 new packets + + @Override + public boolean handle(DebugInfoPacket packet) { + return defaultHandler(packet); + } + + // I question if God exists because of this packet - God does not exist if I find out there's a built-in dab + // TODO for the future: redirect this as a /me command + // TODO for the far future: should we have a client mod that handles skins, handle these too + @Override + public boolean handle(EmoteListPacket packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(CodeBuilderPacket packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(CreativeContentPacket packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(ItemStackRequestPacket packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(LevelSoundEvent1Packet packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(ItemStackResponsePacket packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(PlayerArmorDamagePacket packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(PlayerEnchantOptionsPacket packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(UpdatePlayerGameTypePacket packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(PacketViolationWarningPacket packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(PositionTrackingDBClientRequestPacket packet) { + return defaultHandler(packet); + } + + @Override + public boolean handle(PositionTrackingDBServerBroadcastPacket packet) { + return defaultHandler(packet); + } } \ No newline at end of file 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 6ad206b3..7b191263 100644 --- a/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/QueryPacketHandler.java @@ -26,10 +26,10 @@ package org.geysermc.connector.network; -import com.github.steveice10.mc.protocol.data.message.Message; +import com.github.steveice10.mc.protocol.data.message.MessageSerializer; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; -import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.common.ping.GeyserPingInfo; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.MessageUtils; @@ -148,7 +148,7 @@ public class QueryPacketHandler { } if (connector.getConfig().isPassthroughMotd() && pingInfo != null) { - String[] javaMotd = MessageUtils.getBedrockMessage(Message.fromString(pingInfo.motd)).split("\n"); + String[] javaMotd = MessageUtils.getBedrockMessage(MessageSerializer.fromString(pingInfo.getDescription())).split("\n"); motd = javaMotd[0].trim(); // First line of the motd. } else { motd = connector.getConfig().getBedrock().getMotd1(); @@ -156,8 +156,8 @@ public class QueryPacketHandler { // If passthrough player counts is enabled lets get players from the server if (connector.getConfig().isPassthroughPlayerCounts() && pingInfo != null) { - currentPlayerCount = String.valueOf(pingInfo.currentPlayerCount); - maxPlayerCount = String.valueOf(pingInfo.maxPlayerCount); + currentPlayerCount = String.valueOf(pingInfo.getPlayers().getOnline()); + maxPlayerCount = String.valueOf(pingInfo.getPlayers().getMax()); } else { currentPlayerCount = String.valueOf(connector.getPlayers().size()); maxPlayerCount = String.valueOf(connector.getConfig().getMaxPlayers()); @@ -220,7 +220,7 @@ public class QueryPacketHandler { // Fill player names if(pingInfo != null) { - for (String username : pingInfo.getPlayers()) { + for (String username : pingInfo.getPlayerList()) { query.write(username.getBytes()); query.write((byte) 0x00); } 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 5a40b246..943b4568 100644 --- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java +++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java @@ -27,12 +27,13 @@ package org.geysermc.connector.network; import com.nukkitx.protocol.bedrock.BedrockPacket; import com.nukkitx.protocol.bedrock.packet.*; -import org.geysermc.common.AuthType; +import org.geysermc.connector.common.AuthType; import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslatorRegistry; import org.geysermc.connector.utils.LoginEncryptionUtils; +import org.geysermc.connector.utils.LanguageUtils; public class UpstreamPacketHandler extends LoggingPacketHandler { @@ -47,10 +48,10 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { @Override public boolean handle(LoginPacket loginPacket) { if (loginPacket.getProtocolVersion() > GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()) { - session.disconnect("Outdated Geyser proxy! I'm still on " + GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion()); + session.disconnect(LanguageUtils.getPlayerLocaleString("geyser.network.outdated.server", session.getClientData().getLanguageCode(), GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion())); return true; } else if (loginPacket.getProtocolVersion() < GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()) { - session.disconnect("Outdated Bedrock client! Please use " + GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion()); + session.disconnect(LanguageUtils.getPlayerLocaleString("geyser.network.outdated.client", session.getClientData().getLanguageCode(), GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion())); return true; } @@ -70,7 +71,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { switch (packet.getStatus()) { case COMPLETED: session.connect(connector.getRemoteServer()); - connector.getLogger().info("Player connected with username " + session.getAuthData().getName()); + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.connect", session.getAuthData().getName())); break; case HAVE_ALL_PACKS: ResourcePackStackPacket stack = new ResourcePackStackPacket(); @@ -97,7 +98,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { GeyserConfiguration.IUserAuthenticationInfo info = connector.getConfig().getUserAuths().get(bedrockUsername); if (info != null) { - connector.getLogger().info("using stored credentials for bedrock user " + session.getAuthData().getName()); + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.auth.stored_credentials", session.getAuthData().getName())); session.authenticate(info.getEmail(), info.getPassword()); // TODO send a message to bedrock user telling them they are connected (if nothing like a motd @@ -111,6 +112,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { @Override public boolean handle(SetLocalPlayerAsInitializedPacket packet) { + LanguageUtils.loadGeyserLocale(session.getClientData().getLanguageCode()); + if (!session.isLoggedIn() && !session.isLoggingIn() && session.getConnector().getAuthType() == AuthType.ONLINE) { // TODO it is safer to key authentication on something that won't change (UUID, not username) if (!couldLoginUserByName(session.getAuthData().getName())) { @@ -124,7 +127,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler { @Override public boolean handle(MovePlayerPacket packet) { if (session.isLoggingIn()) { - session.sendMessage("Please wait until you are logged in..."); + session.sendMessage(LanguageUtils.getPlayerLocaleString("geyser.auth.login.wait", session.getClientData().getLanguageCode())); } return translateAndDefault(packet); 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 d2b87af1..0aa0ceaa 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 @@ -32,7 +32,7 @@ import com.github.steveice10.mc.protocol.MinecraftProtocol; 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.window.VillagerTrade; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; +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; @@ -48,15 +48,16 @@ import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.data.*; import com.nukkitx.protocol.bedrock.packet.*; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongMap; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import lombok.Getter; import lombok.Setter; -import org.geysermc.common.AuthType; import org.geysermc.common.window.FormWindow; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; +import org.geysermc.connector.common.AuthType; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.inventory.PlayerInventory; @@ -69,10 +70,7 @@ import org.geysermc.connector.network.translators.EntityIdentifierRegistry; import org.geysermc.connector.network.translators.PacketTranslatorRegistry; import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.world.block.BlockTranslator; -import org.geysermc.connector.utils.ChunkUtils; -import org.geysermc.connector.utils.LocaleUtils; -import org.geysermc.connector.utils.MathUtils; -import org.geysermc.connector.utils.SkinUtils; +import org.geysermc.connector.utils.*; import org.geysermc.floodgate.util.BedrockData; import org.geysermc.floodgate.util.EncryptionUtil; @@ -110,7 +108,7 @@ public class GeyserSession implements CommandSender { private TeleportCache teleportCache; @Getter - private final Long2ObjectMap storedMaps = new Long2ObjectOpenHashMap<>(); + private final Long2ObjectMap storedMaps = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>()); /** * A map of Vector3i positions to Java entity IDs. @@ -146,7 +144,7 @@ public class GeyserSession implements CommandSender { private boolean jumping; @Setter - private BlockState breakingBlock; + private int breakingBlock; @Setter private Vector3i lastBlockPlacePosition; @@ -212,6 +210,13 @@ public class GeyserSession implements CommandSender { this.loggedIn = false; this.inventoryCache.getInventories().put(0, inventory); + + bedrockServerSession.addDisconnectHandler(disconnectReason -> { + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.disconnect", bedrockServerSession.getAddress().getAddress(), disconnectReason)); + + disconnect(disconnectReason.name()); + connector.removePlayer(this); + }); } public void connect(RemoteServer remoteServer) { @@ -221,16 +226,17 @@ public class GeyserSession implements CommandSender { ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 0, false); BiomeDefinitionListPacket biomeDefinitionListPacket = new BiomeDefinitionListPacket(); - biomeDefinitionListPacket.setTag(BiomeTranslator.BIOMES); + biomeDefinitionListPacket.setDefinitions(BiomeTranslator.BIOMES); upstream.sendPacket(biomeDefinitionListPacket); AvailableEntityIdentifiersPacket entityPacket = new AvailableEntityIdentifiersPacket(); - entityPacket.setTag(EntityIdentifierRegistry.ENTITY_IDENTIFIERS); + entityPacket.setIdentifiers(EntityIdentifierRegistry.ENTITY_IDENTIFIERS); upstream.sendPacket(entityPacket); - InventoryContentPacket creativePacket = new InventoryContentPacket(); - creativePacket.setContainerId(ContainerId.CREATIVE); - creativePacket.setContents(ItemRegistry.CREATIVE_ITEMS); + CreativeContentPacket creativePacket = new CreativeContentPacket(); + for (int i = 0; i < ItemRegistry.CREATIVE_ITEMS.length; i++) { + creativePacket.getEntries().put(i + 1, ItemRegistry.CREATIVE_ITEMS[i]); + } upstream.sendPacket(creativePacket); PlayStatusPacket playStatusPacket = new PlayStatusPacket(); @@ -239,10 +245,10 @@ public class GeyserSession implements CommandSender { UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket(); attributesPacket.setRuntimeEntityId(getPlayerEntity().getGeyserId()); - List attributes = new ArrayList<>(); + List attributes = new ArrayList<>(); // Default move speed // Bedrock clients move very fast by default until they get an attribute packet correcting the speed - attributes.add(new Attribute("minecraft:movement", 0.0f, 1024f, 0.1f, 0.1f)); + attributes.add(new AttributeData("minecraft:movement", 0.0f, 1024f, 0.1f, 0.1f)); attributesPacket.setAttributes(attributes); upstream.sendPacket(attributesPacket); } @@ -260,12 +266,11 @@ public class GeyserSession implements CommandSender { public void login() { if (connector.getAuthType() != AuthType.ONLINE) { - connector.getLogger().info( - "Attempting to login using " + connector.getAuthType().name().toLowerCase() + " mode... " + - (connector.getAuthType() == AuthType.OFFLINE ? - "authentication is disabled." : "authentication will be encrypted" - ) - ); + if (connector.getAuthType() == AuthType.OFFLINE) { + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.auth.login.offline")); + } else { + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.auth.login.floodgate")); + } authenticate(authData.getName()); } } @@ -276,7 +281,7 @@ public class GeyserSession implements CommandSender { public void authenticate(String username, String password) { if (loggedIn) { - connector.getLogger().severe(username + " is already logged in!"); + connector.getLogger().severe(LanguageUtils.getLocaleStringLog("geyser.auth.already_loggedin", username)); return; } @@ -301,13 +306,13 @@ public class GeyserSession implements CommandSender { PublicKey.class ); } catch (IOException | InvalidKeySpecException | NoSuchAlgorithmException e) { - connector.getLogger().error("Error while reading Floodgate key file", e); + connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.auth.floodgate.bad_key"), e); } publicKey = key; } else publicKey = null; if (publicKey != null) { - connector.getLogger().info("Loaded Floodgate key!"); + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.auth.floodgate.loaded_key")); } downstream = new Client(remoteServer.getAddress(), remoteServer.getPort(), protocol, new TcpSessionFactory()); @@ -328,7 +333,7 @@ public class GeyserSession implements CommandSender { upstream.getSession().getAddress().getAddress().getHostAddress() )); } catch (Exception e) { - connector.getLogger().error("Failed to encrypt message", e); + connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.auth.floodgate.encrypt_fail"), e); } HandshakePacket handshakePacket = event.getPacket(); @@ -345,7 +350,7 @@ public class GeyserSession implements CommandSender { public void connected(ConnectedEvent event) { loggingIn = false; loggedIn = true; - connector.getLogger().info(authData.getName() + " (logged in as: " + protocol.getProfile().getName() + ")" + " has connected to remote java server on address " + remoteServer.getAddress()); + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.connect", authData.getName(), protocol.getProfile().getName(), remoteServer.getAddress())); playerEntity.setUuid(protocol.getProfile().getId()); playerEntity.setUsername(protocol.getProfile().getName()); @@ -354,6 +359,7 @@ public class GeyserSession implements CommandSender { // Let the user know there locale may take some time to download // as it has to be extracted from a JAR if (locale.toLowerCase().equals("en_us") && !LocaleUtils.LOCALE_MAPPINGS.containsKey("en_us")) { + // This should probably be left hardcoded as it will only show for en_us clients sendMessage("Downloading your locale (en_us) this may take some time"); } @@ -365,11 +371,12 @@ public class GeyserSession implements CommandSender { public void disconnected(DisconnectedEvent event) { loggingIn = false; loggedIn = false; - connector.getLogger().info(authData.getName() + " has disconnected from remote java server on address " + remoteServer.getAddress() + " because of " + event.getReason()); + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.disconnect", authData.getName(), remoteServer.getAddress(), event.getReason())); if (event.getCause() != null) { event.getCause().printStackTrace(); } - upstream.disconnect(event.getReason()); + + upstream.disconnect(MessageUtils.getBedrockMessage(MessageSerializer.fromString(event.getReason()))); } @Override @@ -403,7 +410,7 @@ public class GeyserSession implements CommandSender { @Override public void packetError(PacketErrorEvent event) { - connector.getLogger().warning("Downstream packet error! " + event.getCause().getMessage()); + connector.getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.network.downstream_error", event.getCause().getMessage())); if (connector.getConfig().isDebugMode()) event.getCause().printStackTrace(); event.setSuppress(true); @@ -413,8 +420,8 @@ public class GeyserSession implements CommandSender { downstream.getSession().connect(); connector.addPlayer(this); } catch (InvalidCredentialsException | IllegalArgumentException e) { - connector.getLogger().info("User '" + username + "' entered invalid login info, kicking."); - disconnect("Invalid/incorrect login info"); + connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.auth.login.invalid", username)); + disconnect(LanguageUtils.getPlayerLocaleString("geyser.auth.login.invalid.kick", getClientData().getLanguageCode())); } catch (RequestException ex) { ex.printStackTrace(); } @@ -428,7 +435,7 @@ public class GeyserSession implements CommandSender { downstream.getSession().disconnect(reason); } if (upstream != null && !upstream.isClosed()) { - connector.getPlayers().remove(this.upstream.getAddress()); + connector.getPlayers().remove(this); upstream.disconnect(reason); } } @@ -443,7 +450,7 @@ public class GeyserSession implements CommandSender { } public void close() { - disconnect("Server closed."); + disconnect(LanguageUtils.getPlayerLocaleString("geyser.network.close", getClientData().getLanguageCode())); } public void setAuthenticationData(AuthData authData) { @@ -499,18 +506,18 @@ public class GeyserSession implements CommandSender { StartGamePacket startGamePacket = new StartGamePacket(); startGamePacket.setUniqueEntityId(playerEntity.getGeyserId()); startGamePacket.setRuntimeEntityId(playerEntity.getGeyserId()); - startGamePacket.setPlayerGamemode(0); + startGamePacket.setPlayerGameType(GameType.SURVIVAL); startGamePacket.setPlayerPosition(Vector3f.from(0, 69, 0)); startGamePacket.setRotation(Vector2f.from(1, 1)); startGamePacket.setSeed(-1); - startGamePacket.setDimensionId(playerEntity.getDimension()); + startGamePacket.setDimensionId(DimensionUtils.javaToBedrock(playerEntity.getDimension())); startGamePacket.setGeneratorId(1); - startGamePacket.setLevelGamemode(0); + startGamePacket.setLevelGameType(GameType.SURVIVAL); startGamePacket.setDifficulty(1); startGamePacket.setDefaultSpawn(Vector3i.ZERO); startGamePacket.setAchievementsDisabled(true); - startGamePacket.setTime(-1); + startGamePacket.setCurrentTick(-1); startGamePacket.setEduEditionOffers(0); startGamePacket.setEduFeaturesEnabled(false); startGamePacket.setRainLevel(0); @@ -535,7 +542,7 @@ public class GeyserSession implements CommandSender { startGamePacket.setWorldTemplateOptionLocked(false); startGamePacket.setLevelId("world"); - startGamePacket.setWorldName("world"); + startGamePacket.setLevelName("world"); startGamePacket.setPremiumWorldTemplateId("00000000-0000-0000-0000-000000000000"); // startGamePacket.setCurrentTick(0); startGamePacket.setEnchantmentSeed(0); 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 267f3cb1..68e8519c 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 @@ -27,7 +27,7 @@ package org.geysermc.connector.network.session.cache; import com.github.steveice10.mc.protocol.data.message.Message; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.packet.AddEntityPacket; import com.nukkitx.protocol.bedrock.packet.BossEventPacket; import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket; @@ -52,10 +52,12 @@ public class BossBar { updateBossBar(); } + //TODO: There is a player unique entity ID - if this didn't exist before, we may be able to get rid of our hack + public void updateBossBar() { BossEventPacket bossEventPacket = new BossEventPacket(); bossEventPacket.setBossUniqueEntityId(entityId); - bossEventPacket.setAction(BossEventPacket.Action.SHOW); + bossEventPacket.setAction(BossEventPacket.Action.CREATE); bossEventPacket.setTitle(MessageUtils.getTranslatedBedrockMessage(title, session.getClientData().getLanguageCode())); bossEventPacket.setHealthPercentage(health); bossEventPacket.setColor(color); //ignored by client @@ -69,7 +71,7 @@ public class BossBar { this.title = title; BossEventPacket bossEventPacket = new BossEventPacket(); bossEventPacket.setBossUniqueEntityId(entityId); - bossEventPacket.setAction(BossEventPacket.Action.TITLE); + bossEventPacket.setAction(BossEventPacket.Action.UPDATE_NAME); bossEventPacket.setTitle(MessageUtils.getTranslatedBedrockMessage(title, session.getClientData().getLanguageCode())); session.sendUpstreamPacket(bossEventPacket); @@ -79,7 +81,7 @@ public class BossBar { this.health = health; BossEventPacket bossEventPacket = new BossEventPacket(); bossEventPacket.setBossUniqueEntityId(entityId); - bossEventPacket.setAction(BossEventPacket.Action.HEALTH_PERCENTAGE); + bossEventPacket.setAction(BossEventPacket.Action.UPDATE_PERCENTAGE); bossEventPacket.setHealthPercentage(health); session.sendUpstreamPacket(bossEventPacket); @@ -88,7 +90,7 @@ public class BossBar { public void removeBossBar() { BossEventPacket bossEventPacket = new BossEventPacket(); bossEventPacket.setBossUniqueEntityId(entityId); - bossEventPacket.setAction(BossEventPacket.Action.HIDE); + bossEventPacket.setAction(BossEventPacket.Action.REMOVE); session.sendUpstreamPacket(bossEventPacket); removeBossEntity(); 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 ac7ab06c..9601a298 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 @@ -28,8 +28,8 @@ package org.geysermc.connector.network.session.cache; 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.entity.metadata.Position; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import lombok.Getter; +import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.network.translators.world.chunk.ChunkPosition; @@ -39,15 +39,17 @@ import java.util.Map; public class ChunkCache { - private boolean cache; - private final GeyserSession session; + private final boolean cache; @Getter private Map chunks = new HashMap<>(); public ChunkCache(GeyserSession session) { - this.session = session; - this.cache = session.getConnector().getConfig().isCacheChunks(); + if (session.getConnector().getWorldManager().getClass() == GeyserBootstrap.DEFAULT_CHUNK_MANAGER.getClass()) { + this.cache = session.getConnector().getConfig().isCacheChunks(); + } else { + this.cache = false; // To prevent Spigot from initializing + } } public void addToCache(Column chunk) { @@ -58,7 +60,7 @@ public class ChunkCache { chunks.put(position, chunk); } - public void updateBlock(Position position, BlockState block) { + public void updateBlock(Position position, int block) { if (!cache) { return; } @@ -74,7 +76,7 @@ public class ChunkCache { } } - public BlockState getBlockAt(Position position) { + public int getBlockAt(Position position) { if (!cache) { return BlockTranslator.AIR; } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java index c12cc513..2daa6b2f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java @@ -26,11 +26,12 @@ package org.geysermc.connector.network.translators; +import com.nukkitx.nbt.NBTInputStream; +import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtUtils; -import com.nukkitx.nbt.stream.NBTInputStream; -import com.nukkitx.nbt.tag.CompoundTag; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.connector.utils.LanguageUtils; import java.io.InputStream; import java.util.Arrays; @@ -40,7 +41,7 @@ import java.util.Arrays; // Array index formula by https://wiki.vg/Chunk_Format public class BiomeTranslator { - public static final CompoundTag BIOMES; + public static final NbtMap BIOMES; private BiomeTranslator() { } @@ -53,13 +54,13 @@ public class BiomeTranslator { /* Load biomes */ InputStream stream = FileUtils.getResource("bedrock/biome_definitions.dat"); - CompoundTag biomesTag; + NbtMap biomesTag; - try (NBTInputStream biomenbtInputStream = NbtUtils.createNetworkReader(stream)){ - biomesTag = (CompoundTag) biomenbtInputStream.readTag(); + try (NBTInputStream biomenbtInputStream = NbtUtils.createNetworkReader(stream)) { + biomesTag = (NbtMap) biomenbtInputStream.readTag(); BIOMES = biomesTag; } catch (Exception ex) { - GeyserConnector.getInstance().getLogger().warning("Failed to get biomes from biome definitions, is there something wrong with the file?"); + GeyserConnector.getInstance().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.biome_read")); throw new AssertionError(ex); } } @@ -70,24 +71,27 @@ public class BiomeTranslator { return bedrockData; } - for (int z = 0; z < 16; z += 4) { - for (int x = 0; x < 16; x += 4) { - byte biomeId = biomeID(biomeData, x, z); - fillArray(z, x, bedrockData, biomeId); - fillArray(z + 1, x, bedrockData, biomeId); - fillArray(z + 2, x, bedrockData, biomeId); - fillArray(z + 3, x, bedrockData, biomeId); + for (int y = 0; y < 16; y += 4) { + for (int z = 0; z < 16; z += 4) { + for (int x = 0; x < 16; x += 4) { + byte biomeId = biomeID(biomeData, x, y, z); + int offset = ((z + (y / 4)) << 4) | x; + Arrays.fill(bedrockData, offset, offset + 4, biomeId); + } } } return bedrockData; } - private static void fillArray(int z, int x, byte[] legacyBiomeData, int biomeId) { - int offset = (z << 4) | x; - Arrays.fill(legacyBiomeData, offset, offset + 4, (byte) biomeId); - } - - private static byte biomeID(int[] biomeData, int x, int z) { - return (byte) biomeData[((z >> 2) & 3) << 2 | ((x >> 2) & 3)]; + private static byte biomeID(int[] biomeData, int x, int y, int z) { + int biomeId = biomeData[((y >> 2) & 63) << 4 | ((z >> 2) & 3) << 2 | ((x >> 2) & 3)]; + if (biomeId == 0) { + biomeId = 42; // Ocean + } else if (biomeId >= 40 && biomeId <= 43) { // Java has multiple End dimensions that Bedrock doesn't recognize + biomeId = 9; + } else if (biomeId >= 170) { // Nether biomes. Dunno why it's like this :microjang: + biomeId += 8; + } + return (byte) biomeId; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java index cc9b2cd8..1f336667 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/EntityIdentifierRegistry.java @@ -26,10 +26,11 @@ package org.geysermc.connector.network.translators; +import com.nukkitx.nbt.NBTInputStream; +import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtUtils; -import com.nukkitx.nbt.stream.NBTInputStream; -import com.nukkitx.nbt.tag.CompoundTag; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.connector.utils.LanguageUtils; import java.io.InputStream; @@ -38,7 +39,7 @@ import java.io.InputStream; */ public class EntityIdentifierRegistry { - public static CompoundTag ENTITY_IDENTIFIERS; + public static NbtMap ENTITY_IDENTIFIERS; private EntityIdentifierRegistry() { } @@ -52,9 +53,9 @@ public class EntityIdentifierRegistry { InputStream stream = FileUtils.getResource("bedrock/entity_identifiers.dat"); try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) { - ENTITY_IDENTIFIERS = (CompoundTag) nbtInputStream.readTag(); + ENTITY_IDENTIFIERS = (NbtMap) nbtInputStream.readTag(); } catch (Exception e) { - throw new AssertionError("Unable to get entities from entity identifiers", e); + throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.entity"), e); } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java index a11dd40a..92d2e910 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/PacketTranslatorRegistry.java @@ -33,6 +33,7 @@ import com.nukkitx.protocol.bedrock.BedrockPacket; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.LanguageUtils; import org.reflections.Reflections; import java.util.HashMap; @@ -66,10 +67,10 @@ public class PacketTranslatorRegistry { BEDROCK_TRANSLATOR.translators.put(targetPacket, translator); } else { - GeyserConnector.getInstance().getLogger().error("Class " + clazz.getCanonicalName() + " is annotated as a translator but has an invalid target packet."); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.invalid_target", clazz.getCanonicalName())); } } catch (InstantiationException | IllegalAccessException e) { - GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated translator " + clazz.getCanonicalName() + "."); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.failed", clazz.getCanonicalName())); } } @@ -97,7 +98,7 @@ public class PacketTranslatorRegistry { GeyserConnector.getInstance().getLogger().debug("Could not find packet for " + (packet.toString().length() > 25 ? packet.getClass().getSimpleName() : packet)); } } catch (Throwable ex) { - GeyserConnector.getInstance().getLogger().error("Could not translate packet " + packet.getClass().getSimpleName(), ex); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.packet.failed", packet.getClass().getSimpleName()), ex); ex.printStackTrace(); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index 2c44e4fd..dfd49f2e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -25,15 +25,6 @@ package org.geysermc.connector.network.translators.bedrock; -import java.util.concurrent.TimeUnit; - -import com.nukkitx.protocol.bedrock.data.LevelEventType; -import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; -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.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState; @@ -41,10 +32,18 @@ import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.protocol.bedrock.data.LevelEventType; +import com.nukkitx.protocol.bedrock.packet.LevelEventPacket; import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket; import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket; +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 org.geysermc.connector.network.translators.world.block.BlockTranslator; +import java.util.concurrent.TimeUnit; + @Translator(packet = PlayerActionPacket.class) public class BedrockActionTranslator extends PacketTranslator { @@ -113,8 +112,8 @@ public class BedrockActionTranslator extends PacketTranslator lines.length - 1) { - break; - } - newMessage = new StringBuilder(); - } else newMessage.append(character); - } - // Put the final line on since it isn't done in the for loop - if (iterator < lines.length) lines[iterator] = newMessage.toString(); - ClientUpdateSignPacket clientUpdateSignPacket = new ClientUpdateSignPacket(pos, lines); - session.sendDownstreamPacket(clientUpdateSignPacket); - //TODO (potentially): originally I was going to update the sign blocks so Bedrock and Java users would match visually - // However Java can still store a lot per-line and visuals are still messed up so that doesn't work - - // We remove the sign position from map to indicate there is no work-in-progress sign - lastMessages.remove(pos); + NbtMap tag = packet.getData(); + if (tag.getString("id").equals("Sign")) { + // This is the reason why this all works - Bedrock sends packets every time you update the sign, Java only wants the final packet + // But Bedrock sends one final packet when you're done editing the sign, which should be equal to the last message since there's no edits + // So if the latest update does not match the last cached update then it's still being edited + Position pos = new Position(tag.getInt("x"), tag.getInt("y"), tag.getInt("z")); + if (!tag.getString("Text").equals(lastMessages.get(pos))) { + lastMessages.put(pos, tag.getString("Text")); + return; } + // Otherwise the two messages are identical and we can get to work deconstructing + StringBuilder newMessage = new StringBuilder(); + // While Bedrock's sign lines are one string, Java's is an array of each line + // (Initialized all with empty strings because it complains about null) + String[] lines = new String[] {"", "", "", ""}; + int iterator = 0; + // This converts the message into the array'd message Java wants + for (char character : tag.getString("Text").toCharArray()) { + // If we get a return in Bedrock, that signals to use the next line. + if (character == '\n') { + lines[iterator] = newMessage.toString(); + iterator++; + // Bedrock, for whatever reason, can hold a message out of bounds + // We don't care about that so we discard that + if (iterator > lines.length - 1) { + break; + } + newMessage = new StringBuilder(); + } else newMessage.append(character); + } + // Put the final line on since it isn't done in the for loop + if (iterator < lines.length) lines[iterator] = newMessage.toString(); + ClientUpdateSignPacket clientUpdateSignPacket = new ClientUpdateSignPacket(pos, lines); + session.sendDownstreamPacket(clientUpdateSignPacket); + //TODO (potentially): originally I was going to update the sign blocks so Bedrock and Java users would match visually + // However Java can still store a lot per-line and visuals are still messed up so that doesn't work + + // We remove the sign position from map to indicate there is no work-in-progress sign + lastMessages.remove(pos); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java index 04fe8dbf..297db702 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockBlockPickRequestPacketTranslator.java @@ -26,7 +26,6 @@ package org.geysermc.connector.network.translators.bedrock; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientMoveItemToHotbarPacket; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.BlockPickRequestPacket; @@ -45,10 +44,10 @@ public class BedrockBlockPickRequestPacketTranslator extends PacketTranslator @Override public void translate(InteractPacket packet, GeyserSession session) { - Entity entity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId()); + Entity entity; + if (packet.getRuntimeEntityId() == session.getPlayerEntity().getGeyserId()) { + //Player is not in entity cache + entity = session.getPlayerEntity(); + } else { + entity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId()); + } if (entity == null) return; @@ -56,12 +64,12 @@ public class BedrockInteractTranslator extends PacketTranslator break; } ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(), - InteractAction.INTERACT, Hand.MAIN_HAND); + InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking()); session.sendDownstreamPacket(interactPacket); break; case DAMAGE: ClientPlayerInteractEntityPacket attackPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(), - InteractAction.ATTACK, Hand.MAIN_HAND); + InteractAction.ATTACK, Hand.MAIN_HAND, session.isSneaking()); session.sendDownstreamPacket(attackPacket); break; case LEAVE_VEHICLE: @@ -126,6 +134,14 @@ public class BedrockInteractTranslator extends PacketTranslator } } break; + case OPEN_INVENTORY: + ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); + containerOpenPacket.setId((byte) 0); + containerOpenPacket.setType(ContainerType.INVENTORY); + containerOpenPacket.setUniqueEntityId(-1); + containerOpenPacket.setBlockPosition(entity.getPosition().toInt()); + session.sendUpstreamPacket(containerOpenPacket); + break; } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java index 777d4d9e..25e1c54e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java @@ -36,7 +36,6 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.data.LevelEventType; @@ -83,9 +82,9 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator { - session.sendUpstreamPacket(session.getStoredMaps().get(mapID)); - session.getStoredMaps().remove(mapID); + ClientboundMapItemDataPacket mapPacket = session.getStoredMaps().remove(mapID); + if (mapPacket != null) { + session.sendUpstreamPacket(mapPacket); + } }, 100, TimeUnit.MILLISECONDS); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMobEquipmentTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMobEquipmentTranslator.java index 1dfa2774..02835151 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMobEquipmentTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMobEquipmentTranslator.java @@ -30,7 +30,7 @@ import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerChangeHeldItemPacket; -import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; import com.nukkitx.protocol.bedrock.packet.MobEquipmentPacket; import org.geysermc.connector.utils.CooldownUtils; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java index 14d597fd..0abf8150 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMovePlayerTranslator.java @@ -26,7 +26,7 @@ package org.geysermc.connector.network.translators.bedrock; import com.nukkitx.math.vector.Vector3d; -import org.geysermc.common.ChatColor; +import org.geysermc.connector.common.ChatColor; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.entity.type.EntityType; @@ -137,7 +137,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator { + + @Override + public void translate(PacketViolationWarningPacket packet, GeyserSession session) { + // Not translated since this is something that the developers need to know + session.getConnector().getLogger().error("Packet violation warning sent from client! " + packet.toString()); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPositionTrackingDBClientRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPositionTrackingDBClientRequestTranslator.java new file mode 100644 index 00000000..41b6246c --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockPositionTrackingDBClientRequestTranslator.java @@ -0,0 +1,80 @@ +/* + * 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.bedrock; + +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; +import com.nukkitx.nbt.NbtType; +import com.nukkitx.protocol.bedrock.packet.PositionTrackingDBClientRequestPacket; +import com.nukkitx.protocol.bedrock.packet.PositionTrackingDBServerBroadcastPacket; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; +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.DimensionUtils; +import org.geysermc.connector.utils.LoadstoneTracker; + +@Translator(packet = PositionTrackingDBClientRequestPacket.class) +public class BedrockPositionTrackingDBClientRequestTranslator extends PacketTranslator { + + @Override + public void translate(PositionTrackingDBClientRequestPacket packet, GeyserSession session) { + PositionTrackingDBServerBroadcastPacket broadcastPacket = new PositionTrackingDBServerBroadcastPacket(); + broadcastPacket.setTrackingId(packet.getTrackingId()); + + // Fetch the stored Loadstone + LoadstoneTracker.LoadstonePos pos = LoadstoneTracker.getPos(packet.getTrackingId()); + + // If we don't have data for that ID tell the client its not found + if (pos == null) { + broadcastPacket.setAction(PositionTrackingDBServerBroadcastPacket.Action.NOT_FOUND); + session.sendUpstreamPacket(broadcastPacket); + return; + } + + broadcastPacket.setAction(PositionTrackingDBServerBroadcastPacket.Action.UPDATE); + + // Build the nbt data for the update + NbtMapBuilder builder = NbtMap.builder(); + builder.putInt("dim", DimensionUtils.javaToBedrock(pos.getDimension())); + builder.putString("id", String.format("%08X", packet.getTrackingId())); + + builder.putByte("version", (byte) 1); // Not sure what this is for + builder.putByte("status", (byte) 0); // Not sure what this is for + + // Build the position for the update + IntList posList = new IntArrayList(); + posList.add(pos.getX()); + posList.add(pos.getY()); + posList.add(pos.getZ()); + builder.putList("pos", NbtType.INT, posList); + broadcastPacket.setTag(builder.build()); + + session.sendUpstreamPacket(broadcastPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java index 8fc377ab..14bc1507 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockRespawnTranslator.java @@ -25,14 +25,13 @@ package org.geysermc.connector.network.translators.bedrock; -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.ClientRequest; import com.github.steveice10.mc.protocol.packet.ingame.client.ClientRequestPacket; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.protocol.bedrock.packet.RespawnPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; @Translator(packet = RespawnPacket.class) public class BedrockRespawnTranslator extends PacketTranslator { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/effect/EffectRegistry.java b/connector/src/main/java/org/geysermc/connector/network/translators/effect/EffectRegistry.java index 50888090..0a3b01ef 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/effect/EffectRegistry.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/effect/EffectRegistry.java @@ -35,6 +35,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import lombok.NonNull; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.connector.utils.LanguageUtils; import java.io.InputStream; import java.util.HashMap; @@ -80,7 +81,7 @@ public class EffectRegistry { + entry.getValue().asText() + ", it will take effect."); } catch (IllegalArgumentException e2){ - GeyserConnector.getInstance().getLogger().warning("Fail to map particle " + entry.getKey() + "=>" + entry.getValue().asText()); + GeyserConnector.getInstance().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.particle.failed_map", entry.getKey(), entry.getValue().asText())); } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java index f301d2b5..c780038a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/AnvilInventoryTranslator.java @@ -26,18 +26,18 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; -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.packet.ingame.client.window.ClientRenameItemPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryActionData; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.protocol.bedrock.data.inventory.*; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater; import java.util.List; +import java.util.stream.Collectors; public class AnvilInventoryTranslator extends BlockInventoryTranslator { public AnvilInventoryTranslator() { @@ -46,7 +46,7 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { @Override public int bedrockSlotToJava(InventoryActionData action) { - if (action.getSource().getContainerId() == ContainerId.CURSOR) { + if (action.getSource().getContainerId() == ContainerId.UI) { switch (action.getSlot()) { case 1: return 0; @@ -56,6 +56,9 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { return 2; } } + if (action.getSource().getContainerId() == ContainerId.ANVIL_RESULT) { + return 2; + } return super.bedrockSlotToJava(action); } @@ -101,7 +104,7 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { } if (itemName != null) { String rename; - com.nukkitx.nbt.tag.CompoundTag tag = itemName.getTag(); + NbtMap tag = itemName.getTag(); if (tag != null) { rename = tag.getCompound("display").getString("Name"); } else { @@ -111,7 +114,13 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { session.sendDownstreamPacket(renameItemPacket); } if (anvilResult != null) { - //client will send another packet to grab anvil output + //Strip unnecessary actions + List strippedActions = actions.stream() + .filter(action -> action.getSource().getContainerId() == ContainerId.ANVIL_RESULT + || (action.getSource().getType() == InventorySource.Type.CONTAINER + && !(action.getSource().getContainerId() == ContainerId.UI && action.getSlot() != 0))) + .collect(Collectors.toList()); + super.translateActions(session, inventory, strippedActions); return; } @@ -120,7 +129,7 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { @Override public void updateSlot(GeyserSession session, Inventory inventory, int slot) { - if (slot >= 0 && slot <= 2) { + if (slot == 0) { ItemStack item = inventory.getItem(slot); if (item != null) { String rename; @@ -129,7 +138,7 @@ public class AnvilInventoryTranslator extends BlockInventoryTranslator { CompoundTag displayTag = tag.get("display"); if (displayTag != null) { String itemName = displayTag.get("Name").getValue().toString(); - Message message = Message.fromString(itemName); + TextMessage message = (TextMessage) MessageSerializer.fromString(itemName); rename = message.getText(); } else { rename = ""; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java index 5deb0370..6f00fc4d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BaseInventoryTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.connector.network.translators.inventory; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.InventoryActionData; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.inventory.action.InventoryActionDataTranslator; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java index ab410ea8..4b8b57e8 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BlockInventoryTranslator.java @@ -25,8 +25,7 @@ package org.geysermc.connector.network.translators.inventory; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.block.BlockTranslator; @@ -40,7 +39,7 @@ public class BlockInventoryTranslator extends BaseInventoryTranslator { public BlockInventoryTranslator(int size, String javaBlockIdentifier, ContainerType containerType, InventoryUpdater updater) { super(size); - BlockState javaBlockState = BlockTranslator.getJavaBlockState(javaBlockIdentifier); + int javaBlockState = BlockTranslator.getJavaBlockState(javaBlockIdentifier); int blockId = BlockTranslator.getBedrockBlockId(javaBlockState); this.holder = new BlockInventoryHolder(blockId, containerType); this.updater = updater; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java index acda7c91..89cdbe8d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/BrewingInventoryTranslator.java @@ -25,8 +25,8 @@ package org.geysermc.connector.network.translators.inventory; -import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryActionData; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; +import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java index 13684a60..152f4a85 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/ChestInventoryTranslator.java @@ -25,7 +25,7 @@ package org.geysermc.connector.network.translators.inventory; -import com.nukkitx.protocol.bedrock.data.InventoryActionData; +import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java index e31eb1e3..afcb321a 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/CraftingInventoryTranslator.java @@ -26,10 +26,10 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryActionData; -import com.nukkitx.protocol.bedrock.data.InventorySource; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; +import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; +import com.nukkitx.protocol.bedrock.data.inventory.InventorySource; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -39,52 +39,17 @@ import org.geysermc.connector.utils.InventoryUtils; import java.util.List; -public class CraftingInventoryTranslator extends BaseInventoryTranslator { - private final InventoryUpdater updater; - +public class CraftingInventoryTranslator extends BlockInventoryTranslator { public CraftingInventoryTranslator() { - super(10); - this.updater = new CursorInventoryUpdater(); - } - - @Override - public void prepareInventory(GeyserSession session, Inventory inventory) { - // - } - - @Override - public void openInventory(GeyserSession session, Inventory inventory) { - ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); - containerOpenPacket.setWindowId((byte) inventory.getId()); - containerOpenPacket.setType((byte) ContainerType.WORKBENCH.id()); - containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); - containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); - session.sendUpstreamPacket(containerOpenPacket); - } - - @Override - public void closeInventory(GeyserSession session, Inventory inventory) { - // - } - - @Override - public void updateInventory(GeyserSession session, Inventory inventory) { - updater.updateInventory(this, session, inventory); - } - - @Override - public void updateSlot(GeyserSession session, Inventory inventory, int slot) { - updater.updateSlot(this, session, inventory, slot); + super(10, "minecraft:crafting_table", ContainerType.WORKBENCH, new CursorInventoryUpdater()); } @Override public int bedrockSlotToJava(InventoryActionData action) { - if (action.getSource().getContainerId() == ContainerId.CURSOR) { + if (action.getSource().getContainerId() == ContainerId.UI) { int slotnum = action.getSlot(); if (slotnum >= 32 && 42 >= slotnum) { return slotnum - 31; - } else if (slotnum == 50) { - return 0; } } return super.bedrockSlotToJava(action); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java index 6d6cadd7..1183b21d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/DoubleChestInventoryTranslator.java @@ -26,25 +26,22 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.block.BlockTranslator; -import org.geysermc.connector.network.translators.inventory.updater.ChestInventoryUpdater; -import org.geysermc.connector.network.translators.inventory.updater.InventoryUpdater; public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { private final int blockId; public DoubleChestInventoryTranslator(int size) { super(size, 54); - BlockState javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]"); + int javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]"); this.blockId = BlockTranslator.getBedrockBlockId(javaBlockState); } @@ -60,14 +57,14 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); session.sendUpstreamPacket(blockPacket); - CompoundTag tag = CompoundTag.builder() - .stringTag("id", "Chest") - .intTag("x", position.getX()) - .intTag("y", position.getY()) - .intTag("z", position.getZ()) - .intTag("pairx", pairPosition.getX()) - .intTag("pairz", pairPosition.getZ()) - .stringTag("CustomName", inventory.getTitle()).buildRootTag(); + NbtMap tag = NbtMap.builder() + .putString("id", "Chest") + .putInt("x", position.getX()) + .putInt("y", position.getY()) + .putInt("z", position.getZ()) + .putInt("pairx", pairPosition.getX()) + .putInt("pairz", pairPosition.getZ()) + .putString("CustomName", inventory.getTitle()).build(); BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); dataPacket.setData(tag); dataPacket.setBlockPosition(position); @@ -80,14 +77,14 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY); session.sendUpstreamPacket(blockPacket); - tag = CompoundTag.builder() - .stringTag("id", "Chest") - .intTag("x", pairPosition.getX()) - .intTag("y", pairPosition.getY()) - .intTag("z", pairPosition.getZ()) - .intTag("pairx", position.getX()) - .intTag("pairz", position.getZ()) - .stringTag("CustomName", inventory.getTitle()).buildRootTag(); + tag = NbtMap.builder() + .putString("id", "Chest") + .putInt("x", pairPosition.getX()) + .putInt("y", pairPosition.getY()) + .putInt("z", pairPosition.getZ()) + .putInt("pairx", position.getX()) + .putInt("pairz", position.getZ()) + .putString("CustomName", inventory.getTitle()).build(); dataPacket = new BlockEntityDataPacket(); dataPacket.setData(tag); dataPacket.setBlockPosition(pairPosition); @@ -99,8 +96,8 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { @Override public void openInventory(GeyserSession session, Inventory inventory) { ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); - containerOpenPacket.setWindowId((byte) inventory.getId()); - containerOpenPacket.setType((byte) ContainerType.CONTAINER.id()); + containerOpenPacket.setId((byte) inventory.getId()); + containerOpenPacket.setType(ContainerType.CONTAINER); containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); session.sendUpstreamPacket(containerOpenPacket); @@ -110,7 +107,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { public void closeInventory(GeyserSession session, Inventory inventory) { Vector3i holderPos = inventory.getHolderPosition(); Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); - BlockState realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ()); + int realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ()); UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); 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 ba7f8cc7..c8e9ed18 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 @@ -25,7 +25,7 @@ package org.geysermc.connector.network.translators.inventory; -import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.inventory.updater.ContainerInventoryUpdater; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java index 5c6de0e8..1f148e02 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/FurnaceInventoryTranslator.java @@ -26,7 +26,7 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.data.game.window.WindowType; -import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; import com.nukkitx.protocol.bedrock.packet.ContainerSetDataPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java index 174cfbc1..4b4a1246 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/GrindstoneInventoryTranslator.java @@ -25,8 +25,9 @@ package org.geysermc.connector.network.translators.inventory; -import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryActionData; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; +import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater; public class GrindstoneInventoryTranslator extends BlockInventoryTranslator { @@ -38,7 +39,7 @@ public class GrindstoneInventoryTranslator extends BlockInventoryTranslator { @Override public int bedrockSlotToJava(InventoryActionData action) { final int slot = super.bedrockSlotToJava(action); - if (action.getSource().getContainerId() == 124) { + if (action.getSource().getContainerId() == ContainerId.UI) { switch (slot) { case 16: return 0; 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 97594907..7d06aed1 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 @@ -26,8 +26,8 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.data.game.window.WindowType; -import com.nukkitx.protocol.bedrock.data.ContainerType; -import com.nukkitx.protocol.bedrock.data.InventoryActionData; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; +import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; import lombok.AllArgsConstructor; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -55,6 +55,7 @@ public abstract class InventoryTranslator { put(WindowType.CRAFTING, new CraftingInventoryTranslator()); put(WindowType.GRINDSTONE, new GrindstoneInventoryTranslator()); put(WindowType.MERCHANT, new MerchantInventoryTranslator()); + put(WindowType.SMITHING, new SmithingInventoryTranslator()); //put(WindowType.ENCHANTMENT, new EnchantmentInventoryTranslator()); //TODO InventoryTranslator furnace = new FurnaceInventoryTranslator(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/MerchantInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/MerchantInventoryTranslator.java index 3f7636b9..37c84e28 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/MerchantInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/MerchantInventoryTranslator.java @@ -26,9 +26,9 @@ package org.geysermc.connector.network.translators.inventory; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.InventoryActionData; -import com.nukkitx.protocol.bedrock.data.InventorySource; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; +import com.nukkitx.protocol.bedrock.data.inventory.InventorySource; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater; @@ -60,7 +60,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator { @Override public int bedrockSlotToJava(InventoryActionData action) { - if (action.getSource().getContainerId() == ContainerId.CURSOR) { + if (action.getSource().getContainerId() == ContainerId.UI) { switch (action.getSlot()) { case 4: return 0; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java index 28986e58..7d7673c4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/PlayerInventoryTranslator.java @@ -28,10 +28,10 @@ package org.geysermc.connector.network.translators.inventory; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCreativeInventoryActionPacket; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.InventoryActionData; -import com.nukkitx.protocol.bedrock.data.InventorySource; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; +import com.nukkitx.protocol.bedrock.data.inventory.InventorySource; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; @@ -39,12 +39,12 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.inventory.action.InventoryActionDataTranslator; import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.utils.InventoryUtils; +import org.geysermc.connector.utils.LanguageUtils; import java.util.List; public class PlayerInventoryTranslator extends InventoryTranslator { - private static final ItemData UNUSUABLE_CRAFTING_SPACE_BLOCK = InventoryUtils.createUnusableSpaceBlock( - "The creative crafting grid is\nunavailable in Java Edition"); + private static final ItemData UNUSUABLE_CRAFTING_SPACE_BLOCK = InventoryUtils.createUnusableSpaceBlock(LanguageUtils.getLocaleStringLog("geyser.inventory.unusable_item.creative")); public PlayerInventoryTranslator() { super(46); @@ -94,7 +94,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { // Crafting grid for (int i = 1; i < 5; i++) { InventorySlotPacket slotPacket = new InventorySlotPacket(); - slotPacket.setContainerId(ContainerId.CURSOR); + slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(i + 27); if (session.getGameMode() == GameMode.CREATIVE) { @@ -122,7 +122,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { slotPacket.setContainerId(ContainerId.ARMOR); slotPacket.setSlot(slot - 5); } else { - slotPacket.setContainerId(ContainerId.CURSOR); + slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(slot + 27); } slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(slot))); @@ -156,13 +156,13 @@ public class PlayerInventoryTranslator extends InventoryTranslator { break; case ContainerId.OFFHAND: return 45; - case ContainerId.CURSOR: + case ContainerId.UI: if (slotnum >= 28 && 31 >= slotnum) { return slotnum - 27; - } else if (slotnum == 50) { - return 0; } break; + case ContainerId.CRAFTING_RESULT: + return 0; } return slotnum; } @@ -184,7 +184,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { if (session.getGameMode() == GameMode.CREATIVE) { //crafting grid is not visible in creative mode in java edition for (InventoryActionData action : actions) { - if (action.getSource().getContainerId() == ContainerId.CURSOR && (action.getSlot() >= 28 && 31 >= action.getSlot())) { + if (action.getSource().getContainerId() == ContainerId.UI && (action.getSlot() >= 28 && 31 >= action.getSlot())) { updateInventory(session, inventory); InventoryUtils.updateCursor(session); return; @@ -207,7 +207,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator { session.sendDownstreamPacket(creativePacket); inventory.setItem(javaSlot, javaItem); break; - case ContainerId.CURSOR: + case ContainerId.UI: if (action.getSlot() == 0) { session.getInventory().setCursor(ItemTranslator.translateToJava(action.getToItem())); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java index 3f1a58f4..45860dcd 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SingleChestInventoryTranslator.java @@ -25,8 +25,7 @@ package org.geysermc.connector.network.translators.inventory; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.inventory.holder.BlockInventoryHolder; @@ -38,7 +37,7 @@ public class SingleChestInventoryTranslator extends ChestInventoryTranslator { public SingleChestInventoryTranslator(int size) { super(size, 27); - BlockState javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]"); + int javaBlockState = BlockTranslator.getJavaBlockState("minecraft:chest[facing=north,type=single,waterlogged=false]"); this.holder = new BlockInventoryHolder(BlockTranslator.getBedrockBlockId(javaBlockState), ContainerType.CONTAINER); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SmithingInventoryTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SmithingInventoryTranslator.java new file mode 100644 index 00000000..f347ccae --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/SmithingInventoryTranslator.java @@ -0,0 +1,70 @@ +/* + * 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.inventory; + +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; +import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; +import org.geysermc.connector.network.translators.inventory.updater.CursorInventoryUpdater; + +public class SmithingInventoryTranslator extends BlockInventoryTranslator { + + public SmithingInventoryTranslator() { + super(3, "minecraft:smithing_table", ContainerType.SMITHING_TABLE, new CursorInventoryUpdater()); + } + + @Override + public int bedrockSlotToJava(InventoryActionData action) { + final int slot = super.bedrockSlotToJava(action); + if (action.getSource().getContainerId() == ContainerId.UI) { + switch (slot) { + case 51: + return 0; + case 52: + return 1; + case 50: + return 2; + default: + return slot; + } + } return slot; + } + + @Override + public int javaSlotToBedrock(int slot) { + switch (slot) { + case 0: + return 51; + case 1: + return 52; + case 2: + return 50; + } + return super.javaSlotToBedrock(slot); + } + +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java index 209df074..96cbd61f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/action/InventoryActionDataTranslator.java @@ -32,10 +32,10 @@ import com.github.steveice10.mc.protocol.data.game.window.*; import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientWindowActionPacket; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.InventoryActionData; -import com.nukkitx.protocol.bedrock.data.InventorySource; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData; +import com.nukkitx.protocol.bedrock.data.inventory.InventorySource; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; @@ -55,11 +55,11 @@ public class InventoryActionDataTranslator { InventoryActionData containerAction = null; boolean refresh = false; for (InventoryActionData action : actions) { - if (action.getSource().getContainerId() == ContainerId.CRAFTING_USE_INGREDIENT || action.getSource().getContainerId() == ContainerId.CRAFTING_RESULT) { + if (action.getSource().getContainerId() == ContainerId.CRAFTING_USE_INGREDIENT) { return; } else if (action.getSource().getType() == InventorySource.Type.WORLD_INTERACTION) { worldAction = action; - } else if (action.getSource().getContainerId() == ContainerId.CURSOR && action.getSlot() == 0) { + } else if (action.getSource().getContainerId() == ContainerId.UI && action.getSlot() == 0) { cursorAction = action; ItemData translatedCursor = ItemTranslator.translateToBedrock(session, session.getInventory().getCursor()); if (!translatedCursor.equals(action.getFromItem())) { @@ -120,9 +120,9 @@ public class InventoryActionDataTranslator { session.sendDownstreamPacket(dropPacket); } } - ItemStack item = session.getInventory().getItem(javaSlot); + ItemStack item = inventory.getItem(javaSlot); if (item != null) { - session.getInventory().setItem(javaSlot, new ItemStack(item.getId(), item.getAmount() - dropAmount, item.getNbt())); + inventory.setItem(javaSlot, new ItemStack(item.getId(), item.getAmount() - dropAmount, item.getNbt())); } return; } else { //clicking outside of inventory diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java index 67ce2ce1..6dfde5d1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/holder/BlockInventoryHolder.java @@ -26,10 +26,9 @@ package org.geysermc.connector.network.translators.inventory.holder; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.protocol.bedrock.data.ContainerType; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerType; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; @@ -57,11 +56,11 @@ public class BlockInventoryHolder extends InventoryHolder { session.sendUpstreamPacket(blockPacket); inventory.setHolderPosition(position); - CompoundTag tag = CompoundTag.builder() - .intTag("x", position.getX()) - .intTag("y", position.getY()) - .intTag("z", position.getZ()) - .stringTag("CustomName", LocaleUtils.getLocaleString(inventory.getTitle(), session.getClientData().getLanguageCode())).buildRootTag(); + NbtMap tag = NbtMap.builder() + .putInt("x", position.getX()) + .putInt("y", position.getY()) + .putInt("z", position.getZ()) + .putString("CustomName", LocaleUtils.getLocaleString(inventory.getTitle(), session.getClientData().getLanguageCode())).build(); BlockEntityDataPacket dataPacket = new BlockEntityDataPacket(); dataPacket.setData(tag); dataPacket.setBlockPosition(position); @@ -71,8 +70,8 @@ public class BlockInventoryHolder extends InventoryHolder { @Override public void openInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { ContainerOpenPacket containerOpenPacket = new ContainerOpenPacket(); - containerOpenPacket.setWindowId((byte) inventory.getId()); - containerOpenPacket.setType((byte) containerType.id()); + containerOpenPacket.setId((byte) inventory.getId()); + containerOpenPacket.setType(containerType); containerOpenPacket.setBlockPosition(inventory.getHolderPosition()); containerOpenPacket.setUniqueEntityId(inventory.getHolderId()); session.sendUpstreamPacket(containerOpenPacket); @@ -82,7 +81,7 @@ public class BlockInventoryHolder extends InventoryHolder { public void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { Vector3i holderPos = inventory.getHolderPosition(); Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ()); - BlockState realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ()); + int realBlock = session.getConnector().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ()); UpdateBlockPacket blockPacket = new UpdateBlockPacket(); blockPacket.setDataLayer(0); blockPacket.setBlockPosition(holderPos); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java index 6ec8d481..e45945bc 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ChestInventoryUpdater.java @@ -25,7 +25,7 @@ package org.geysermc.connector.network.translators.inventory.updater; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import lombok.AllArgsConstructor; @@ -34,11 +34,11 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.item.ItemTranslator; import org.geysermc.connector.utils.InventoryUtils; +import org.geysermc.connector.utils.LanguageUtils; @AllArgsConstructor public class ChestInventoryUpdater extends InventoryUpdater { - private static final ItemData UNUSUABLE_SPACE_BLOCK = InventoryUtils.createUnusableSpaceBlock( - "This slot does not exist in the inventory\non Java Edition, as there is less\nrows than possible in Bedrock"); + private static final ItemData UNUSUABLE_SPACE_BLOCK = InventoryUtils.createUnusableSpaceBlock(LanguageUtils.getLocaleStringLog("geyser.inventory.unusable_item.slot")); private final int paddedSize; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java index ec6175c3..51f33ac4 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/ContainerInventoryUpdater.java @@ -25,7 +25,7 @@ package org.geysermc.connector.network.translators.inventory.updater; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java index adbbdbac..26d88990 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/CursorInventoryUpdater.java @@ -25,7 +25,7 @@ package org.geysermc.connector.network.translators.inventory.updater; -import com.nukkitx.protocol.bedrock.data.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -33,6 +33,8 @@ import org.geysermc.connector.network.translators.inventory.InventoryTranslator; import org.geysermc.connector.network.translators.item.ItemTranslator; public class CursorInventoryUpdater extends InventoryUpdater { + + //TODO: Consider renaming this? Since the Protocol enum updated @Override public void updateInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { super.updateInventory(translator, session, inventory); @@ -42,7 +44,7 @@ public class CursorInventoryUpdater extends InventoryUpdater { if (bedrockSlot == 50) continue; InventorySlotPacket slotPacket = new InventorySlotPacket(); - slotPacket.setContainerId(ContainerId.CURSOR); + slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(bedrockSlot); slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(i))); session.sendUpstreamPacket(slotPacket); @@ -55,7 +57,7 @@ public class CursorInventoryUpdater extends InventoryUpdater { return true; InventorySlotPacket slotPacket = new InventorySlotPacket(); - slotPacket.setContainerId(ContainerId.CURSOR); + slotPacket.setContainerId(ContainerId.UI); slotPacket.setSlot(translator.javaSlotToBedrock(javaSlot)); slotPacket.setItem(ItemTranslator.translateToBedrock(session, inventory.getItem(javaSlot))); session.sendUpstreamPacket(slotPacket); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java index 88157df0..57601a9e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/inventory/updater/InventoryUpdater.java @@ -25,8 +25,8 @@ package org.geysermc.connector.network.translators.inventory.updater; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; import org.geysermc.connector.inventory.Inventory; 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 ed99ece3..23c566d7 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 @@ -29,23 +29,20 @@ package org.geysermc.connector.network.translators.item; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtUtils; -import com.nukkitx.protocol.bedrock.data.ItemData; +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 org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.FileUtils; +import org.geysermc.connector.utils.LanguageUtils; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; -import java.util.Base64; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Registry for anything item related. @@ -81,7 +78,7 @@ public class ItemRegistry { try { itemEntries = GeyserConnector.JSON_MAPPER.readValue(stream, itemEntriesType); } catch (Exception e) { - throw new AssertionError("Unable to load Bedrock runtime item IDs", e); + throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_bedrock"), e); } for (JsonNode entry : itemEntries) { @@ -94,7 +91,7 @@ public class ItemRegistry { try { items = GeyserConnector.JSON_MAPPER.readTree(stream); } catch (Exception e) { - throw new AssertionError("Unable to load Java runtime item IDs", e); + throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e); } int itemIndex = 0; @@ -109,7 +106,7 @@ public class ItemRegistry { entry.getValue().get("bedrock_data").intValue(), entry.getValue().get("tool_type").textValue(), entry.getValue().get("tool_tier").textValue(), - entry.getValue().get("is_block").booleanValue())); + entry.getValue().get("is_block") != null && entry.getValue().get("is_block").booleanValue())); } else { ITEM_ENTRIES.put(itemIndex, new ToolItemEntry( entry.getKey(), itemIndex, @@ -124,7 +121,7 @@ public class ItemRegistry { entry.getKey(), itemIndex, entry.getValue().get("bedrock_id").intValue(), entry.getValue().get("bedrock_data").intValue(), - entry.getValue().get("is_block").booleanValue())); + entry.getValue().get("is_block") != null && entry.getValue().get("is_block").booleanValue())); } if (entry.getKey().equals("minecraft:barrier")) { BARRIER_INDEX = itemIndex; @@ -133,6 +130,9 @@ public class ItemRegistry { 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)); + /* Load creative items */ stream = FileUtils.getResource("bedrock/creative_items.json"); @@ -140,7 +140,7 @@ public class ItemRegistry { try { creativeItemEntries = GeyserConnector.JSON_MAPPER.readTree(stream).get("items"); } catch (Exception e) { - throw new AssertionError("Unable to load creative items", e); + throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.creative"), e); } List creativeItems = new ArrayList<>(); @@ -153,7 +153,7 @@ public class ItemRegistry { byte[] bytes = Base64.getDecoder().decode(itemNode.get("nbt_b64").asText()); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); try { - com.nukkitx.nbt.tag.CompoundTag tag = (com.nukkitx.nbt.tag.CompoundTag) NbtUtils.createReaderLE(bais).readTag(); + NbtMap tag = (NbtMap) NbtUtils.createReaderLE(bais).readTag(); creativeItems.add(ItemData.of(itemNode.get("id").asInt(), damage, 1, tag)); } catch (IOException e) { e.printStackTrace(); @@ -195,7 +195,10 @@ public class ItemRegistry { } } - GeyserConnector.getInstance().getLogger().debug("Missing mapping for bedrock item " + data.getId() + ":" + data.getDamage()); + // This will hide the message when the player clicks with an empty hand + if (data.getId() != 0 && data.getDamage() != 0) { + GeyserConnector.getInstance().getLogger().debug("Missing mapping for bedrock item " + data.getId() + ":" + data.getDamage()); + } return ItemEntry.AIR; } 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 1962f62e..fde799fe 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 @@ -27,17 +27,22 @@ 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.Message; +import com.github.steveice10.mc.protocol.data.message.MessageSerializer; import com.github.steveice10.opennbt.tag.builtin.*; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.nbt.tag.Tag; -import com.nukkitx.protocol.bedrock.data.ItemData; +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 it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.kyori.adventure.text.TextComponent; +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.utils.LanguageUtils; import org.geysermc.connector.utils.MessageUtils; import org.reflections.Reflections; @@ -77,14 +82,13 @@ public abstract class ItemTranslator { for (ItemEntry item : appliedItems) { ItemTranslator registered = ITEM_STACK_TRANSLATORS.get(item.getJavaId()); if (registered != null) { - GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated item translator " + clazz.getCanonicalName() + "." + - " Item translator " + registered.getClass().getCanonicalName() + " is already registered for the item " + item.getJavaIdentifier()); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.item.already_registered", clazz.getCanonicalName(), registered.getClass().getCanonicalName(), item.getJavaIdentifier())); continue; } ITEM_STACK_TRANSLATORS.put(item.getJavaId(), itemStackTranslator); } } catch (InstantiationException | IllegalAccessException e) { - GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated item translator " + clazz.getCanonicalName() + "."); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.item.failed", clazz.getCanonicalName())); } } @@ -150,27 +154,33 @@ public abstract class ItemTranslator { // Get the display name of the item - CompoundTag tag = itemData.getTag(); + NbtMap tag = itemData.getTag(); if (tag != null) { - CompoundTag display = tag.getCompound("display"); + NbtMap display = tag.getCompound("display"); if (display != null) { String name = display.getString("Name"); + // If its not a message convert it + if (!MessageUtils.isMessage(name)) { + TextComponent component = LegacyComponentSerializer.legacy().deserialize(name); + name = GsonComponentSerializer.gson().serialize(component); + } + // Check if its a message to translate if (MessageUtils.isMessage(name)) { // Get the translated name - name = MessageUtils.getTranslatedBedrockMessage(Message.fromString(name), session.getClientData().getLanguageCode()); + name = MessageUtils.getTranslatedBedrockMessage(MessageSerializer.fromString(name), session.getClientData().getLanguageCode()); // Build the new display tag - CompoundTagBuilder displayBuilder = display.toBuilder(); - displayBuilder.stringTag("Name", name); + NbtMapBuilder displayBuilder = display.toBuilder(); + displayBuilder.putString("Name", name); // Build the new root tag - CompoundTagBuilder builder = tag.toBuilder(); - builder.tag(displayBuilder.build("display")); + NbtMapBuilder builder = tag.toBuilder(); + builder.put("display", displayBuilder.build()); // Create a new item with the original data + updated name - itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.buildRootTag()); + itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.build()); } } } @@ -200,108 +210,101 @@ public abstract class ItemTranslator { if (itemData.getTag() == null) { return new ItemStack(itemEntry.getJavaId(), itemData.getCount(), new com.github.steveice10.opennbt.tag.builtin.CompoundTag("")); } - return new ItemStack(itemEntry.getJavaId(), itemData.getCount(), this.translateToJavaNBT(itemData.getTag())); + return new ItemStack(itemEntry.getJavaId(), itemData.getCount(), this.translateToJavaNBT("", itemData.getTag())); } public abstract List getAppliedItems(); - public CompoundTag translateNbtToBedrock(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag) { - Map> javaValue = new HashMap<>(); + public NbtMap translateNbtToBedrock(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag) { + Map javaValue = new HashMap<>(); if (tag.getValue() != null && !tag.getValue().isEmpty()) { for (String str : tag.getValue().keySet()) { com.github.steveice10.opennbt.tag.builtin.Tag javaTag = tag.get(str); - com.nukkitx.nbt.tag.Tag translatedTag = translateToBedrockNBT(javaTag); + Object translatedTag = translateToBedrockNBT(javaTag); if (translatedTag == null) continue; - javaValue.put(translatedTag.getName(), translatedTag); + javaValue.put(javaTag.getName(), translatedTag); } } - - return new CompoundTag(tag.getName(), javaValue); + NbtMapBuilder builder = NbtMap.builder(); + javaValue.forEach(builder::put); + return builder.build(); } - private Tag translateToBedrockNBT(com.github.steveice10.opennbt.tag.builtin.Tag tag) { + private Object translateToBedrockNBT(com.github.steveice10.opennbt.tag.builtin.Tag tag) { if (tag instanceof ByteArrayTag) { - ByteArrayTag byteArrayTag = (ByteArrayTag) tag; - return new com.nukkitx.nbt.tag.ByteArrayTag(byteArrayTag.getName(), byteArrayTag.getValue()); + return ((ByteArrayTag) tag).getValue(); } if (tag instanceof ByteTag) { - ByteTag byteTag = (ByteTag) tag; - return new com.nukkitx.nbt.tag.ByteTag(byteTag.getName(), byteTag.getValue()); + return ((ByteTag) tag).getValue(); } if (tag instanceof DoubleTag) { - DoubleTag doubleTag = (DoubleTag) tag; - return new com.nukkitx.nbt.tag.DoubleTag(doubleTag.getName(), doubleTag.getValue()); + return ((DoubleTag) tag).getValue(); } if (tag instanceof FloatTag) { - FloatTag floatTag = (FloatTag) tag; - return new com.nukkitx.nbt.tag.FloatTag(floatTag.getName(), floatTag.getValue()); + return ((FloatTag) tag).getValue(); } if (tag instanceof IntArrayTag) { - IntArrayTag intArrayTag = (IntArrayTag) tag; - return new com.nukkitx.nbt.tag.IntArrayTag(intArrayTag.getName(), intArrayTag.getValue()); + return ((IntArrayTag) tag).getValue(); } if (tag instanceof IntTag) { - IntTag intTag = (IntTag) tag; - return new com.nukkitx.nbt.tag.IntTag(intTag.getName(), intTag.getValue()); + return ((IntTag) tag).getValue(); } if (tag instanceof LongArrayTag) { - LongArrayTag longArrayTag = (LongArrayTag) tag; - return new com.nukkitx.nbt.tag.LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); + //Long array tag does not exist in BE + //LongArrayTag longArrayTag = (LongArrayTag) tag; + //return new com.nukkitx.nbt.tag.LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); + return null; } if (tag instanceof LongTag) { - LongTag longTag = (LongTag) tag; - return new com.nukkitx.nbt.tag.LongTag(longTag.getName(), longTag.getValue()); + return ((LongTag) tag).getValue(); } if (tag instanceof ShortTag) { - ShortTag shortTag = (ShortTag) tag; - return new com.nukkitx.nbt.tag.ShortTag(shortTag.getName(), shortTag.getValue()); + return ((ShortTag) tag).getValue(); } if (tag instanceof StringTag) { - StringTag stringTag = (StringTag) tag; - return new com.nukkitx.nbt.tag.StringTag(stringTag.getName(), stringTag.getValue()); + return ((StringTag) tag).getValue(); } if (tag instanceof ListTag) { ListTag listTag = (ListTag) tag; - List> tagList = new ArrayList<>(); + List tagList = new ArrayList<>(); for (com.github.steveice10.opennbt.tag.builtin.Tag value : listTag) { tagList.add(translateToBedrockNBT(value)); } - Class clazz = CompoundTag.class; + NbtType type = NbtType.COMPOUND; if (!tagList.isEmpty()) { - clazz = tagList.get(0).getClass(); + type = NbtType.byClass(tagList.get(0).getClass()); } - return new com.nukkitx.nbt.tag.ListTag(listTag.getName(), clazz, tagList); + return new NbtList(type, tagList); } if (tag instanceof com.github.steveice10.opennbt.tag.builtin.CompoundTag) { com.github.steveice10.opennbt.tag.builtin.CompoundTag compoundTag = (com.github.steveice10.opennbt.tag.builtin.CompoundTag) tag; - return translateNbtToBedrock(compoundTag); } return null; } - public com.github.steveice10.opennbt.tag.builtin.CompoundTag translateToJavaNBT(com.nukkitx.nbt.tag.CompoundTag tag) { - com.github.steveice10.opennbt.tag.builtin.CompoundTag javaTag = new com.github.steveice10.opennbt.tag.builtin.CompoundTag(tag.getName()); + public com.github.steveice10.opennbt.tag.builtin.CompoundTag translateToJavaNBT(String name, NbtMap tag) { + com.github.steveice10.opennbt.tag.builtin.CompoundTag javaTag = new com.github.steveice10.opennbt.tag.builtin.CompoundTag(name); Map javaValue = javaTag.getValue(); - if (tag.getValue() != null && !tag.getValue().isEmpty()) { - for (String str : tag.getValue().keySet()) { - Tag bedrockTag = tag.get(str); - com.github.steveice10.opennbt.tag.builtin.Tag translatedTag = translateToJavaNBT(bedrockTag); + if (tag != null && !tag.isEmpty()) { + for (String str : tag.keySet()) { + Object bedrockTag = tag.get(str); + com.github.steveice10.opennbt.tag.builtin.Tag translatedTag = translateToJavaNBT(name, bedrockTag); if (translatedTag == null) continue; @@ -313,77 +316,65 @@ public abstract class ItemTranslator { return javaTag; } - private com.github.steveice10.opennbt.tag.builtin.Tag translateToJavaNBT(com.nukkitx.nbt.tag.Tag tag) { - if (tag instanceof com.nukkitx.nbt.tag.ByteArrayTag) { - com.nukkitx.nbt.tag.ByteArrayTag byteArrayTag = (com.nukkitx.nbt.tag.ByteArrayTag) tag; - return new ByteArrayTag(byteArrayTag.getName(), byteArrayTag.getValue()); + private com.github.steveice10.opennbt.tag.builtin.Tag translateToJavaNBT(String name, Object object) { + if (object instanceof int[]) { + return new IntArrayTag(name, (int[]) object); } - if (tag instanceof com.nukkitx.nbt.tag.ByteTag) { - com.nukkitx.nbt.tag.ByteTag byteTag = (com.nukkitx.nbt.tag.ByteTag) tag; - return new ByteTag(byteTag.getName(), byteTag.getValue()); + if (object instanceof byte[]) { + return new ByteArrayTag(name, (byte[]) object); + } + + if (object instanceof Byte) { + return new ByteTag(name, (byte) object); } - if (tag instanceof com.nukkitx.nbt.tag.DoubleTag) { - com.nukkitx.nbt.tag.DoubleTag doubleTag = (com.nukkitx.nbt.tag.DoubleTag) tag; - return new DoubleTag(doubleTag.getName(), doubleTag.getValue()); + if (object instanceof Float) { + return new FloatTag(name, (float) object); } - if (tag instanceof com.nukkitx.nbt.tag.FloatTag) { - com.nukkitx.nbt.tag.FloatTag floatTag = (com.nukkitx.nbt.tag.FloatTag) tag; - return new FloatTag(floatTag.getName(), floatTag.getValue()); + if (object instanceof Double) { + return new DoubleTag(name, (double) object); } - if (tag instanceof com.nukkitx.nbt.tag.IntArrayTag) { - com.nukkitx.nbt.tag.IntArrayTag intArrayTag = (com.nukkitx.nbt.tag.IntArrayTag) tag; - return new IntArrayTag(intArrayTag.getName(), intArrayTag.getValue()); + if (object instanceof Integer) { + return new IntTag(name, (int) object); } - if (tag instanceof com.nukkitx.nbt.tag.IntTag) { - com.nukkitx.nbt.tag.IntTag intTag = (com.nukkitx.nbt.tag.IntTag) tag; - return new IntTag(intTag.getName(), intTag.getValue()); + if (object instanceof long[]) { + return new LongArrayTag(name, (long[]) object); } - if (tag instanceof com.nukkitx.nbt.tag.LongArrayTag) { - com.nukkitx.nbt.tag.LongArrayTag longArrayTag = (com.nukkitx.nbt.tag.LongArrayTag) tag; - return new LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); + if (object instanceof Long) { + return new LongTag(name, (long) object); } - if (tag instanceof com.nukkitx.nbt.tag.LongTag) { - com.nukkitx.nbt.tag.LongTag longTag = (com.nukkitx.nbt.tag.LongTag) tag; - return new LongTag(longTag.getName(), longTag.getValue()); + if (object instanceof Short) { + return new ShortTag(name, (short) object); } - if (tag instanceof com.nukkitx.nbt.tag.ShortTag) { - com.nukkitx.nbt.tag.ShortTag shortTag = (com.nukkitx.nbt.tag.ShortTag) tag; - return new ShortTag(shortTag.getName(), shortTag.getValue()); + if (object instanceof String) { + return new StringTag(name, (String) object); } - if (tag instanceof com.nukkitx.nbt.tag.StringTag) { - com.nukkitx.nbt.tag.StringTag stringTag = (com.nukkitx.nbt.tag.StringTag) tag; - return new StringTag(stringTag.getName(), stringTag.getValue()); - } - - if (tag instanceof com.nukkitx.nbt.tag.ListTag) { - com.nukkitx.nbt.tag.ListTag listTag = (com.nukkitx.nbt.tag.ListTag) tag; - + if (object instanceof List) { List tags = new ArrayList<>(); - for (Object value : listTag.getValue()) { - if (!(value instanceof com.nukkitx.nbt.tag.Tag)) - continue; - - com.nukkitx.nbt.tag.Tag tagValue = (com.nukkitx.nbt.tag.Tag) value; - com.github.steveice10.opennbt.tag.builtin.Tag javaTag = translateToJavaNBT(tagValue); + for (Object value : (List) object) { + com.github.steveice10.opennbt.tag.builtin.Tag javaTag = translateToJavaNBT("", value); if (javaTag != null) tags.add(javaTag); } - return new ListTag(listTag.getName(), tags); + return new ListTag(name, tags); } - if (tag instanceof com.nukkitx.nbt.tag.CompoundTag) { - com.nukkitx.nbt.tag.CompoundTag compoundTag = (com.nukkitx.nbt.tag.CompoundTag) tag; - return translateToJavaNBT(compoundTag); + if (object instanceof NbtMap) { + NbtMap map = (NbtMap) object; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue().equals(map.get(name))) { + return translateToJavaNBT(entry.getKey(), map.getCompound(name)); + } + } } return null; 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 f4f545ff..304ea3fb 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 @@ -31,8 +31,11 @@ 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.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.protocol.bedrock.data.ItemData; +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.ItemRegistry; import org.geysermc.connector.network.translators.item.ItemTranslator; @@ -63,10 +66,10 @@ public class BannerTranslator extends ItemTranslator { if (blockEntityTag.contains("Patterns")) { ListTag patterns = blockEntityTag.get("Patterns"); - CompoundTagBuilder builder = itemData.getTag().toBuilder(); - builder.tag(convertBannerPattern(patterns)); + NbtMapBuilder builder = itemData.getTag().toBuilder(); + builder.put("Patterns", convertBannerPattern(patterns)); - itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.buildRootTag()); + itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.build()); } return itemData; @@ -78,9 +81,9 @@ public class BannerTranslator extends ItemTranslator { ItemStack itemStack = super.translateToJava(itemData, itemEntry); - com.nukkitx.nbt.tag.CompoundTag nbtTag = itemData.getTag(); - if (nbtTag.contains("Patterns")) { - com.nukkitx.nbt.tag.ListTag patterns = nbtTag.get("Patterns"); + 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)); @@ -102,16 +105,16 @@ public class BannerTranslator extends ItemTranslator { * @param patterns The patterns to convert * @return The new converted patterns */ - public static com.nukkitx.nbt.tag.ListTag convertBannerPattern(ListTag patterns) { - List tagsList = new ArrayList<>(); + public static NbtList convertBannerPattern(ListTag patterns) { + List tagsList = new ArrayList<>(); for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) { - com.nukkitx.nbt.tag.CompoundTag newPatternTag = getBedrockBannerPattern((CompoundTag) patternTag); + NbtMap newPatternTag = getBedrockBannerPattern((CompoundTag) patternTag); if (newPatternTag != null) { tagsList.add(newPatternTag); } } - return new com.nukkitx.nbt.tag.ListTag<>("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, tagsList); + return new NbtList<>(NbtType.COMPOUND, tagsList); } /** @@ -120,7 +123,7 @@ public class BannerTranslator extends ItemTranslator { * @param pattern Java edition pattern nbt * @return The Bedrock edition format pattern nbt */ - public static com.nukkitx.nbt.tag.CompoundTag getBedrockBannerPattern(CompoundTag pattern) { + public static NbtMap getBedrockBannerPattern(CompoundTag pattern) { String patternName = (String) pattern.get("Pattern").getValue(); // Return null if its the globe pattern as it doesn't exist on bedrock @@ -128,11 +131,11 @@ public class BannerTranslator extends ItemTranslator { return null; } - return CompoundTagBuilder.builder() - .intTag("Color", 15 - (int) pattern.get("Color").getValue()) - .stringTag("Pattern", (String) pattern.get("Pattern").getValue()) - .stringTag("Pattern", patternName) - .buildRootTag(); + return NbtMap.builder() + .putInt("Color", 15 - (int) pattern.get("Color").getValue()) + .putString("Pattern", (String) pattern.get("Pattern").getValue()) + .putString("Pattern", patternName) + .build(); } /** @@ -141,10 +144,10 @@ public class BannerTranslator extends ItemTranslator { * @param patterns The patterns to convert * @return The new converted patterns */ - public static ListTag convertBannerPattern(com.nukkitx.nbt.tag.ListTag patterns) { + public static ListTag convertBannerPattern(List patterns) { List tagsList = new ArrayList<>(); - for (Object patternTag : patterns.getValue()) { - CompoundTag newPatternTag = getJavaBannerPattern((com.nukkitx.nbt.tag.CompoundTag) patternTag); + for (Object patternTag : patterns) { + CompoundTag newPatternTag = getJavaBannerPattern((NbtMap) patternTag); tagsList.add(newPatternTag); } @@ -157,7 +160,7 @@ public class BannerTranslator extends ItemTranslator { * @param pattern Bedorck edition pattern nbt * @return The Java edition format pattern nbt */ - public static CompoundTag getJavaBannerPattern(com.nukkitx.nbt.tag.CompoundTag pattern) { + public static CompoundTag getJavaBannerPattern(NbtMap pattern) { Map tags = new HashMap<>(); tags.put("Color", new IntTag("Color", 15 - pattern.getInt("Color"))); tags.put("Pattern", new StringTag("Pattern", pattern.getString("Pattern"))); 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 new file mode 100644 index 00000000..675d4255 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/CompassTranslator.java @@ -0,0 +1,121 @@ +/* + * 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.item.translators; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; +import com.github.steveice10.opennbt.tag.builtin.*; +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.utils.LoadstoneTracker; + +import java.util.List; +import java.util.stream.Collectors; + +@ItemRemapper +public class CompassTranslator extends ItemTranslator { + + private List appliedItems; + + public CompassTranslator() { + appliedItems = ItemRegistry.ITEM_ENTRIES.values().stream().filter(entry -> entry.getJavaIdentifier().endsWith("compass")).collect(Collectors.toList()); + } + + @Override + public ItemData translateToBedrock(ItemStack itemStack, ItemEntry itemEntry) { + if (itemStack.getNbt() == null) return super.translateToBedrock(itemStack, itemEntry); + + Tag lodestoneTag = itemStack.getNbt().get("LodestoneTracked"); + if (lodestoneTag instanceof ByteTag) { + // Get the fake lodestonecompass entry + itemEntry = ItemRegistry.getItemEntry("minecraft:lodestonecompass"); + + // Get the loadstone pos + CompoundTag loadstonePos = itemStack.getNbt().get("LodestonePos"); + if (loadstonePos != null) { + // Get all info needed for tracking + int x = ((IntTag) loadstonePos.get("X")).getValue(); + int y = ((IntTag) loadstonePos.get("Y")).getValue(); + int z = ((IntTag) loadstonePos.get("Z")).getValue(); + String dim = ((StringTag) itemStack.getNbt().get("LodestoneDimension")).getValue(); + + // Store the info + int trackID = LoadstoneTracker.store(x, y, z, dim); + + // Set the bedrock tracking id + itemStack.getNbt().put(new IntTag("trackingHandle", trackID)); + } else { + // The loadstone was removed just set the tracking id to 0 + itemStack.getNbt().put(new IntTag("trackingHandle", 0)); + } + } + + ItemData itemData = super.translateToBedrock(itemStack, itemEntry); + + return itemData; + } + + @Override + public ItemStack translateToJava(ItemData itemData, ItemEntry itemEntry) { + boolean isLoadstone = false; + if (itemEntry.getJavaIdentifier().equals("minecraft:lodestonecompass")) { + // Revert the entry back to the compass + itemEntry = ItemRegistry.getItemEntry("minecraft:compass"); + + isLoadstone = true; + } + + ItemStack itemStack = super.translateToJava(itemData, itemEntry); + + if (isLoadstone) { + // Get the tracking id + int trackingID = ((IntTag) itemStack.getNbt().get("trackingHandle")).getValue(); + + // Fetch the tracking info from the id + LoadstoneTracker.LoadstonePos pos = LoadstoneTracker.getPos(trackingID); + if (pos != null) { + // Build the new NBT data for the fetched tracking info + itemStack.getNbt().put(new StringTag("LodestoneDimension", pos.getDimension())); + + CompoundTag posTag = new CompoundTag("LodestonePos"); + posTag.put(new IntTag("X", pos.getX())); + posTag.put(new IntTag("Y", pos.getY())); + posTag.put(new IntTag("Z", pos.getZ())); + + itemStack.getNbt().put(posTag); + } + } + + return itemStack; + } + + @Override + public List getAppliedItems() { + return appliedItems; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java index 2fdde31d..7cb88d70 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/PotionTranslator.java @@ -28,7 +28,7 @@ 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.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; -import com.nukkitx.protocol.bedrock.data.ItemData; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.network.translators.item.ItemRegistry; import org.geysermc.connector.network.translators.item.ItemTranslator; 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 776cec72..34c7f43d 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 @@ -29,13 +29,13 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; 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 net.kyori.text.Component; -import net.kyori.text.TextComponent; -import net.kyori.text.serializer.gson.GsonComponentSerializer; -import net.kyori.text.serializer.legacy.LegacyComponentSerializer; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 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.network.translators.item.NbtItemStackTranslator; import org.geysermc.connector.utils.MessageUtils; import java.util.ArrayList; @@ -101,7 +101,7 @@ public class BasicItemTranslator extends NbtItemStackTranslator { message = message.replaceFirst("§r", ""); } Component component = TextComponent.of(message); - return GsonComponentSerializer.INSTANCE.serialize(component); + return GsonComponentSerializer.gson().serialize(component); } private String toBedrockMessage(StringTag tag) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java index 404d7824..6bd9cc77 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/EnchantmentTranslator.java @@ -114,7 +114,7 @@ public class EnchantmentTranslator extends NbtItemStackTranslator { itemTag.put(new ListTag("Enchantments", enchantments)); } if (!storedEnchantments.isEmpty()) { - itemTag.put(new ListTag("StoredEnchantments", enchantments)); + itemTag.put(new ListTag("StoredEnchantments", storedEnchantments)); } itemTag.remove("ench"); } @@ -122,7 +122,7 @@ public class EnchantmentTranslator extends NbtItemStackTranslator { private CompoundTag remapEnchantment(CompoundTag tag) { Tag javaEnchLvl = tag.get("lvl"); - if (!(javaEnchLvl instanceof ShortTag)) + if (!(javaEnchLvl instanceof ShortTag || javaEnchLvl instanceof IntTag)) return null; Tag javaEnchId = tag.get("id"); @@ -137,7 +137,7 @@ public class EnchantmentTranslator extends NbtItemStackTranslator { CompoundTag bedrockTag = new CompoundTag(""); bedrockTag.put(new ShortTag("id", (short) enchantment.ordinal())); - bedrockTag.put(new ShortTag("lvl", ((ShortTag) javaEnchLvl).getValue())); + bedrockTag.put(new ShortTag("lvl", ((Number) javaEnchLvl.getValue()).shortValue())); return bedrockTag; } 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 53ce6811..d222d729 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,14 @@ 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 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 java.util.List; @Translator(packet = ServerChatPacket.class) @@ -66,14 +65,14 @@ public class JavaChatTranslator extends PacketTranslator { textPacket.setType(TextPacket.Type.TRANSLATION); textPacket.setNeedsTranslation(true); - List paramsTranslated = MessageUtils.getTranslationParams(((TranslationMessage) packet.getMessage()).getTranslationParams(), locale); + List paramsTranslated = MessageUtils.getTranslationParams(((TranslationMessage) packet.getMessage()).getWith(), locale, packet.getMessage()); textPacket.setParameters(paramsTranslated); - textPacket.setMessage(MessageUtils.insertParams(MessageUtils.getTranslatedBedrockMessage(packet.getMessage(), locale, true), 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)); + textPacket.setMessage(MessageUtils.getTranslatedBedrockMessage(packet.getMessage(), locale, false, packet.getMessage())); } session.sendUpstreamPacket(textPacket); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java index 053630d5..8f524336 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaDeclareCommandsTranslator.java @@ -28,9 +28,10 @@ package org.geysermc.connector.network.translators.java; import com.github.steveice10.mc.protocol.data.game.command.CommandNode; import com.github.steveice10.mc.protocol.data.game.command.CommandParser; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerDeclareCommandsPacket; -import com.nukkitx.protocol.bedrock.data.CommandData; -import com.nukkitx.protocol.bedrock.data.CommandEnumData; -import com.nukkitx.protocol.bedrock.data.CommandParamData; +import com.nukkitx.protocol.bedrock.data.command.CommandData; +import com.nukkitx.protocol.bedrock.data.command.CommandEnumData; +import com.nukkitx.protocol.bedrock.data.command.CommandParamData; +import com.nukkitx.protocol.bedrock.data.command.CommandParamType; import com.nukkitx.protocol.bedrock.packet.AvailableCommandsPacket; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; @@ -40,7 +41,10 @@ import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; @Translator(packet = ServerDeclareCommandsPacket.class) public class JavaDeclareCommandsTranslator extends PacketTranslator { @@ -151,41 +155,41 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator { private static final Collection POTION_MIXES = Arrays.stream(new int[]{372, 331, 348, 376, 289, 437, 353, 414, 382, 375, 462, 378, 396, 377, 370, 469, 470}) - .mapToObj(ingredient -> new PotionMixData(0, ingredient, 0)) + .mapToObj(ingredient -> new PotionMixData(0, ingredient, 0, 0, 0, 0)) //TODO: Confirm this is correct behavior. .collect(Collectors.toList()); @Override @@ -119,7 +119,7 @@ public class JavaDeclareRecipesTranslator extends PacketTranslator session.setGameMode(packet.getGamemode()); LevelEventPacket stopRainPacket = new LevelEventPacket(); - stopRainPacket.setType(LevelEventType.STOP_RAIN); + stopRainPacket.setType(LevelEventType.STOP_RAINING); stopRainPacket.setData(ThreadLocalRandom.current().nextInt(50000) + 10000); stopRainPacket.setPosition(Vector3f.ZERO); session.sendUpstreamPacket(stopRainPacket); - if (entity.getDimension() != DimensionUtils.javaToBedrock(packet.getDimension())) { + if (!entity.getDimension().equals(packet.getDimension())) { DimensionUtils.switchDimension(session, packet.getDimension()); } else { if (session.isManyDimPackets()) { //reloading world - int fakeDim = entity.getDimension() == 0 ? -1 : 0; + String fakeDim = entity.getDimension().equals(DimensionUtils.OVERWORLD) ? DimensionUtils.NETHER : DimensionUtils.OVERWORLD; DimensionUtils.switchDimension(session, fakeDim); DimensionUtils.switchDimension(session, packet.getDimension()); } 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 8ecf4e30..214413ab 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 @@ -42,20 +42,20 @@ public class JavaTitleTranslator extends PacketTranslator { switch (packet.getAction()) { case TITLE: - titlePacket.setType(SetTitlePacket.Type.SET_TITLE); + titlePacket.setType(SetTitlePacket.Type.TITLE); titlePacket.setText(MessageUtils.getBedrockMessage(packet.getTitle())); break; case SUBTITLE: - titlePacket.setType(SetTitlePacket.Type.SET_SUBTITLE); + titlePacket.setType(SetTitlePacket.Type.SUBTITLE); titlePacket.setText(MessageUtils.getBedrockMessage(packet.getTitle())); break; case CLEAR: case RESET: - titlePacket.setType(SetTitlePacket.Type.RESET_TITLE); + titlePacket.setType(SetTitlePacket.Type.CLEAR); titlePacket.setText(""); break; case ACTION_BAR: - titlePacket.setType(SetTitlePacket.Type.SET_ACTIONBAR_MESSAGE); + titlePacket.setType(SetTitlePacket.Type.ACTIONBAR); titlePacket.setText(MessageUtils.getBedrockMessage(packet.getTitle())); break; case TIMES: 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 6e53df27..2ab499b0 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 @@ -27,9 +27,9 @@ package org.geysermc.connector.network.translators.java.entity; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityAttachPacket; -import com.nukkitx.protocol.bedrock.data.EntityData; -import com.nukkitx.protocol.bedrock.data.EntityEventType; -import com.nukkitx.protocol.bedrock.data.EntityFlag; +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.Entity; import org.geysermc.connector.network.session.GeyserSession; @@ -63,7 +63,7 @@ public class JavaEntityAttachTranslator extends PacketTranslator id == passengerId)) { SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); - linkPacket.setEntityLink(new EntityLink(entity.getGeyserId(), passenger.getGeyserId(), EntityLink.Type.REMOVE, false)); + linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), EntityLinkData.Type.REMOVE, false)); session.sendUpstreamPacket(linkPacket); passengers.remove(passenger.getEntityId()); this.updateOffset(passenger, entity.getEntityType(), session, false, false, (passengers.size() > 1)); } + + // Force an update to the passenger metadata + passenger.updateBedrockMetadata(session); } if (entity.getEntityType() == EntityType.HORSE) { @@ -140,8 +143,14 @@ public class JavaEntitySetPassengersTranslator extends PacketTranslator { @@ -53,25 +52,25 @@ public class JavaEntityStatusTranslator extends PacketTranslator { @@ -59,20 +58,20 @@ public class JavaPlayerAbilitiesTranslator extends PacketTranslator playerFlags = new ObjectOpenHashSet<>(); - playerFlags.add(AdventureSettingsPacket.Flag.AUTO_JUMP); + Set playerFlags = new ObjectOpenHashSet<>(); + playerFlags.add(AdventureSetting.AUTO_JUMP); if (packet.isCanFly()) - playerFlags.add(AdventureSettingsPacket.Flag.MAY_FLY); + playerFlags.add(AdventureSetting.MAY_FLY); if (packet.isFlying()) - playerFlags.add(AdventureSettingsPacket.Flag.FLYING); + playerFlags.add(AdventureSetting.FLYING); AdventureSettingsPacket adventureSettingsPacket = new AdventureSettingsPacket(); adventureSettingsPacket.setPlayerPermission(PlayerPermission.MEMBER); // Required or the packet simply is not sent adventureSettingsPacket.setCommandPermission(CommandPermission.NORMAL); adventureSettingsPacket.setUniqueEntityId(entity.getGeyserId()); - adventureSettingsPacket.getFlags().addAll(playerFlags); + adventureSettingsPacket.getSettings().addAll(playerFlags); session.sendUpstreamPacket(adventureSettingsPacket); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java index b049d0be..9ed11a23 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerActionAckTranslator.java @@ -50,13 +50,13 @@ public class JavaPlayerActionAckTranslator extends PacketTranslator { @@ -80,7 +81,7 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator { @@ -66,21 +65,21 @@ public class JavaTeamTranslator extends PacketTranslator { .setSuffix(MessageUtils.getBedrockMessage(packet.getSuffix())) .setUpdateType(UpdateType.UPDATE); } else { - GeyserConnector.getInstance().getLogger().error("Error while translating Team Packet " + packet.getAction() + "! Scoreboard Team " + packet.getTeamName() + " is not registered."); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.team.failed_not_registered", packet.getAction(), packet.getTeamName())); } break; case ADD_PLAYER: if(team != null){ team.addEntities(packet.getPlayers()); } else { - GeyserConnector.getInstance().getLogger().error("Error while translating Team Packet " + packet.getAction() + "! Scoreboard Team " + packet.getTeamName() + " is not registered."); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.team.failed_not_registered", packet.getAction(), packet.getTeamName())); } break; case REMOVE_PLAYER: if(team != null){ team.removeEntities(packet.getPlayers()); } else { - GeyserConnector.getInstance().getLogger().error("Error while translating Team Packet " + packet.getAction() + "! Scoreboard Team " + packet.getTeamName() + " is not registered."); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.team.failed_not_registered", packet.getAction(), packet.getTeamName())); } break; case REMOVE: diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/scoreboard/JavaUpdateScoreTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/scoreboard/JavaUpdateScoreTranslator.java index eac2ed04..827e4c7f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/scoreboard/JavaUpdateScoreTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/scoreboard/JavaUpdateScoreTranslator.java @@ -34,6 +34,7 @@ import org.geysermc.connector.scoreboard.Scoreboard; import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardAction; import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerUpdateScorePacket; +import org.geysermc.connector.utils.LanguageUtils; @Translator(packet = ServerUpdateScorePacket.class) public class JavaUpdateScoreTranslator extends PacketTranslator { @@ -45,7 +46,7 @@ public class JavaUpdateScoreTranslator extends PacketTranslator blockEntityEntry : chunkData.getLoadBlockEntitiesLater().object2IntEntrySet()) { + for (Object2IntMap.Entry blockEntityEntry : chunkData.getLoadBlockEntitiesLater().object2IntEntrySet()) { int x = blockEntityEntry.getKey().getInt("x"); int y = blockEntityEntry.getKey().getInt("y"); int z = blockEntityEntry.getKey().getInt("z"); - ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntValue()), new Position(x, y, z)); + ChunkUtils.updateBlock(session, blockEntityEntry.getIntValue(), new Position(x, y, z)); } chunkData.getLoadBlockEntitiesLater().clear(); session.getChunkCache().addToCache(packet.getColumn()); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java index 79b27f6a..23e831c0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaExplosionTranslator.java @@ -52,7 +52,7 @@ public class JavaExplosionTranslator extends PacketTranslator= 2.0f ? LevelEventType.PARTICLE_HUGE_EXPLODE : LevelEventType.PARTICLE_LARGE_EXPLOSION); + levelEventPacket.setType(packet.getRadius() >= 2.0f ? LevelEventType.PARTICLE_HUGE_EXPLODE : LevelEventType.PARTICLE_EXPLOSION); levelEventPacket.setData(0); levelEventPacket.setPosition(pos.toFloat()); session.sendUpstreamPacket(levelEventPacket); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java index 5a3ebaba..2aee7bc0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java @@ -35,6 +35,7 @@ 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.BedrockMapIcon; +import org.geysermc.connector.utils.DimensionUtils; import org.geysermc.connector.utils.MapColor; @Translator(packet = ServerMapDataPacket.class) @@ -45,7 +46,7 @@ public class JavaMapDataTranslator extends PacketTranslator boolean shouldStore = false; mapItemDataPacket.setUniqueMapId(packet.getMapId()); - mapItemDataPacket.setDimensionId(session.getPlayerEntity().getDimension()); + mapItemDataPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getPlayerEntity().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 781018b2..f4d1c75d 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 @@ -31,7 +31,13 @@ import com.github.steveice10.mc.protocol.data.game.world.notify.EnterCreditsValu import com.github.steveice10.mc.protocol.packet.ingame.client.ClientRequestPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerNotifyClientPacket; import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.data.*; +import com.nukkitx.protocol.bedrock.data.AdventureSetting; +import com.nukkitx.protocol.bedrock.data.LevelEventType; +import com.nukkitx.protocol.bedrock.data.PlayerPermission; +import com.nukkitx.protocol.bedrock.data.command.CommandPermission; +import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap; +import com.nukkitx.protocol.bedrock.data.entity.EntityEventType; +import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.packet.*; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.geysermc.connector.entity.Entity; @@ -56,35 +62,35 @@ public class JavaNotifyClientTranslator extends PacketTranslator playerFlags = new ObjectOpenHashSet<>(); + Set playerFlags = new ObjectOpenHashSet<>(); GameMode gameMode = (GameMode) packet.getValue(); if (gameMode == GameMode.ADVENTURE) - playerFlags.add(AdventureSettingsPacket.Flag.IMMUTABLE_WORLD); + playerFlags.add(AdventureSetting.WORLD_IMMUTABLE); if (gameMode == GameMode.CREATIVE) - playerFlags.add(AdventureSettingsPacket.Flag.MAY_FLY); + playerFlags.add(AdventureSetting.MAY_FLY); if (gameMode == GameMode.SPECTATOR) { - playerFlags.add(AdventureSettingsPacket.Flag.MAY_FLY); - playerFlags.add(AdventureSettingsPacket.Flag.NO_CLIP); - playerFlags.add(AdventureSettingsPacket.Flag.FLYING); + playerFlags.add(AdventureSetting.MAY_FLY); + playerFlags.add(AdventureSetting.NO_CLIP); + playerFlags.add(AdventureSetting.FLYING); gameMode = GameMode.CREATIVE; // spectator doesnt exist on bedrock } - playerFlags.add(AdventureSettingsPacket.Flag.AUTO_JUMP); + playerFlags.add(AdventureSetting.AUTO_JUMP); SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); playerGameTypePacket.setGamemode(gameMode.ordinal()); @@ -97,7 +103,7 @@ public class JavaNotifyClientTranslator extends PacketTranslator { + // TODO: Update mappings since they're definitely all going to be wrong now @Override public void translate(ServerPlayEffectPacket packet, GeyserSession session) { LevelEventPacket effect = new LevelEventPacket(); @@ -63,21 +64,21 @@ public class JavaPlayEffectTranslator extends PacketTranslator { @@ -49,7 +50,7 @@ public class JavaSpawnParticleTranslator extends PacketTranslator tags = new ArrayList<>(); + NbtMapBuilder builder = NbtMap.builder(); + List tags = new ArrayList<>(); for (VillagerTrade trade : packet.getTrades()) { - CompoundTagBuilder recipe = CompoundTagBuilder.builder(); - recipe.intTag("maxUses", trade.getMaxUses()); - recipe.intTag("traderExp", trade.getXp()); - recipe.floatTag("priceMultiplierA", trade.getPriceMultiplier()); - recipe.tag(getItemTag(session, trade.getOutput(), "sell", 0)); - recipe.floatTag("priceMultiplierB", 0.0f); - recipe.intTag("buyCountB", trade.getSecondInput() != null ? trade.getSecondInput().getAmount() : 0); - recipe.intTag("buyCountA", trade.getFirstInput().getAmount()); - recipe.intTag("demand", trade.getDemand()); - recipe.intTag("tier", packet.getVillagerLevel() - 1); - recipe.tag(getItemTag(session, trade.getFirstInput(), "buyA", trade.getSpecialPrice())); + NbtMapBuilder recipe = NbtMap.builder(); + recipe.putInt("maxUses", trade.getMaxUses()); + recipe.putInt("traderExp", trade.getXp()); + recipe.putFloat("priceMultiplierA", trade.getPriceMultiplier()); + recipe.put("sell", getItemTag(session, trade.getOutput(), 0)); + recipe.putFloat("priceMultiplierB", 0.0f); + recipe.putInt("buyCountB", trade.getSecondInput() != null ? trade.getSecondInput().getAmount() : 0); + recipe.putInt("buyCountA", trade.getFirstInput().getAmount()); + recipe.putInt("demand", trade.getDemand()); + recipe.putInt("tier", packet.getVillagerLevel() - 1); + recipe.put("buyA", getItemTag(session, trade.getFirstInput(), trade.getSpecialPrice())); if (trade.getSecondInput() != null) { - recipe.tag(getItemTag(session, trade.getSecondInput(), "buyB", 0)); + recipe.put("buyB", getItemTag(session, trade.getSecondInput(), 0)); } - recipe.intTag("uses", trade.getNumUses()); - recipe.byteTag("rewardExp", (byte) 1); - tags.add(recipe.buildRootTag()); + recipe.putInt("uses", trade.getNumUses()); + recipe.putByte("rewardExp", (byte) 1); + tags.add(recipe.build()); } //Hidden trade to fix visual experience bug if (packet.isRegularVillager() && packet.getVillagerLevel() < 5) { - tags.add(CompoundTagBuilder.builder() - .intTag("maxUses", 0) - .intTag("traderExp", 0) - .floatTag("priceMultiplierA", 0.0f) - .floatTag("priceMultiplierB", 0.0f) - .intTag("buyCountB", 0) - .intTag("buyCountA", 0) - .intTag("demand", 0) - .intTag("tier", 5) - .intTag("uses", 0) - .byteTag("rewardExp", (byte) 0) - .buildRootTag()); + tags.add(NbtMap.builder() + .putInt("maxUses", 0) + .putInt("traderExp", 0) + .putFloat("priceMultiplierA", 0.0f) + .putFloat("priceMultiplierB", 0.0f) + .putInt("buyCountB", 0) + .putInt("buyCountA", 0) + .putInt("demand", 0) + .putInt("tier", 5) + .putInt("uses", 0) + .putByte("rewardExp", (byte) 0) + .build()); } - builder.listTag("Recipes", CompoundTag.class, tags); - List expTags = new ArrayList<>(); - expTags.add(CompoundTagBuilder.builder().intTag("0", 0).buildRootTag()); - expTags.add(CompoundTagBuilder.builder().intTag("1", 10).buildRootTag()); - expTags.add(CompoundTagBuilder.builder().intTag("2", 70).buildRootTag()); - expTags.add(CompoundTagBuilder.builder().intTag("3", 150).buildRootTag()); - expTags.add(CompoundTagBuilder.builder().intTag("4", 250).buildRootTag()); - builder.listTag("TierExpRequirements", CompoundTag.class, expTags); - updateTradePacket.setOffers(builder.buildRootTag()); + builder.putList("Recipes", NbtType.COMPOUND, tags); + List expTags = new ArrayList<>(); + expTags.add(NbtMap.builder().putInt("0", 0).build()); + expTags.add(NbtMap.builder().putInt("1", 10).build()); + expTags.add(NbtMap.builder().putInt("2", 70).build()); + expTags.add(NbtMap.builder().putInt("3", 150).build()); + expTags.add(NbtMap.builder().putInt("4", 250).build()); + builder.putList("TierExpRequirements", NbtType.COMPOUND, expTags); + updateTradePacket.setOffers(builder.build()); session.sendUpstreamPacket(updateTradePacket); } - private CompoundTag getItemTag(GeyserSession session, ItemStack stack, String name, int specialPrice) { + private NbtMap getItemTag(GeyserSession session, ItemStack stack, int specialPrice) { ItemData itemData = ItemTranslator.translateToBedrock(session, stack); ItemEntry itemEntry = ItemRegistry.getItem(stack); - CompoundTagBuilder builder = CompoundTagBuilder.builder(); - builder.byteTag("Count", (byte) (Math.max(itemData.getCount() + specialPrice, 1))); - builder.shortTag("Damage", itemData.getDamage()); - builder.shortTag("id", (short) itemEntry.getBedrockId()); + NbtMapBuilder builder = NbtMap.builder(); + builder.putByte("Count", (byte) (Math.max(itemData.getCount() + specialPrice, 1))); + builder.putShort("Damage", itemData.getDamage()); + builder.putShort("id", (short) itemEntry.getBedrockId()); if (itemData.getTag() != null) { - CompoundTag tag = itemData.getTag().toBuilder().build("tag"); - builder.tag(tag); + NbtMap tag = itemData.getTag().toBuilder().build(); + builder.put("tag", tag); } - return builder.build(name); + return builder.build(); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java index 362d67d0..ae4ed779 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaUpdateTileEntityTranslator.java @@ -40,14 +40,19 @@ public class JavaUpdateTileEntityTranslator extends PacketTranslator BANNER_COLORS = new Object2IntOpenHashMap<>(); - private static final Object2ByteMap BED_COLORS = new Object2ByteOpenHashMap<>(); + private static final Int2IntMap BANNER_COLORS = new Int2IntOpenHashMap(); + private static final Int2ByteMap BED_COLORS = new Int2ByteOpenHashMap(); private static final Int2ObjectMap DOUBLE_CHEST_VALUES = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>(); - private static final Map FLOWER_POT_BLOCKS = new HashMap<>(); - private static final Object2IntMap NOTEBLOCK_PITCHES = new Object2IntOpenHashMap<>(); + private static final Map FLOWER_POT_BLOCKS = new HashMap<>(); + private static final Int2IntMap NOTEBLOCK_PITCHES = new Int2IntOpenHashMap(); private static final Int2BooleanMap IS_STICKY_PISTON = new Int2BooleanOpenHashMap(); private static final Int2BooleanMap PISTON_VALUES = new Int2BooleanOpenHashMap(); - private static final Object2ByteMap SKULL_VARIANTS = new Object2ByteOpenHashMap<>(); - private static final Object2ByteMap SKULL_ROTATIONS = new Object2ByteOpenHashMap<>(); - private static final Object2ByteMap SHULKERBOX_DIRECTIONS = new Object2ByteOpenHashMap<>(); + private static final Int2ByteMap SKULL_VARIANTS = new Int2ByteOpenHashMap(); + private static final Int2ByteMap SKULL_ROTATIONS = new Int2ByteOpenHashMap(); + private static final Int2ByteMap SHULKERBOX_DIRECTIONS = new Int2ByteOpenHashMap(); /** * Determines if the block state contains Bedrock block information * @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, BlockState javaBlockState) { + public static void storeBlockStateValues(Map.Entry entry, int javaBlockState) { JsonNode bannerColor = entry.getValue().get("banner_color"); if (bannerColor != null) { BANNER_COLORS.put(javaBlockState, (byte) bannerColor.intValue()); @@ -80,12 +72,12 @@ public class BlockStateValues { boolean isDirectionPositive = ((entry.getValue().get("x") != null && entry.getValue().get("x").asBoolean()) || (entry.getValue().get("z") != null && entry.getValue().get("z").asBoolean())); boolean isLeft = (entry.getValue().get("double_chest_position").asText().contains("left")); - DOUBLE_CHEST_VALUES.put(javaBlockState.getId(), new DoubleChestValue(isX, isDirectionPositive, isLeft)); + DOUBLE_CHEST_VALUES.put(javaBlockState, new DoubleChestValue(isX, isDirectionPositive, isLeft)); return; } - if (entry.getKey().contains("potted_")) { - FLOWER_POT_VALUES.put(javaBlockState.getId(), entry.getKey().replace("potted_", "")); + if (entry.getKey().contains("potted_") || entry.getKey().contains("flower_pot")) { + FLOWER_POT_VALUES.put(javaBlockState, entry.getKey().replace("potted_", "")); return; } @@ -97,8 +89,8 @@ public class BlockStateValues { if (entry.getKey().contains("piston")) { // True if extended, false if not - PISTON_VALUES.put(javaBlockState.getId(), entry.getKey().contains("extended=true")); - IS_STICKY_PISTON.put(javaBlockState.getId(), entry.getKey().contains("sticky")); + PISTON_VALUES.put(javaBlockState, entry.getKey().contains("extended=true")); + IS_STICKY_PISTON.put(javaBlockState, entry.getKey().contains("sticky")); return; } @@ -125,9 +117,9 @@ public class BlockStateValues { * @param state BlockState of the block * @return Banner color integer or -1 if no color */ - public static int getBannerColor(BlockState state) { + public static int getBannerColor(int state) { if (BANNER_COLORS.containsKey(state)) { - return BANNER_COLORS.getInt(state); + return BANNER_COLORS.get(state); } return -1; } @@ -139,9 +131,9 @@ public class BlockStateValues { * @param state BlockState of the block * @return Bed color byte or -1 if no color */ - public static byte getBedColor(BlockState state) { + public static byte getBedColor(int state) { if (BED_COLORS.containsKey(state)) { - return BED_COLORS.getByte(state); + return BED_COLORS.get(state); } return -1; } @@ -167,7 +159,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() { + public static Map getFlowerPotBlocks() { return FLOWER_POT_BLOCKS; } @@ -177,9 +169,9 @@ public class BlockStateValues { * @param state BlockState of the block * @return note block note integer or -1 if not present */ - public static int getNoteblockPitch(BlockState state) { + public static int getNoteblockPitch(int state) { if (NOTEBLOCK_PITCHES.containsKey(state)) { - return NOTEBLOCK_PITCHES.getInt(state); + return NOTEBLOCK_PITCHES.get(state); } return -1; } @@ -192,8 +184,8 @@ public class BlockStateValues { return PISTON_VALUES; } - public static boolean isStickyPiston(BlockState blockState) { - return IS_STICKY_PISTON.get(blockState.getId()); + public static boolean isStickyPiston(int blockState) { + return IS_STICKY_PISTON.get(blockState); } /** @@ -203,9 +195,9 @@ public class BlockStateValues { * @param state BlockState of the block * @return Skull variant byte or -1 if no variant */ - public static byte getSkullVariant(BlockState state) { + public static byte getSkullVariant(int state) { if (SKULL_VARIANTS.containsKey(state)) { - return SKULL_VARIANTS.getByte(state); + return SKULL_VARIANTS.get(state); } return -1; } @@ -217,9 +209,9 @@ public class BlockStateValues { * @param state BlockState of the block * @return Skull rotation value or -1 if no value */ - public static byte getSkullRotation(BlockState state) { + public static byte getSkullRotation(int state) { if (SKULL_ROTATIONS.containsKey(state)) { - return SKULL_ROTATIONS.getByte(state); + return SKULL_ROTATIONS.get(state); } return -1; } @@ -232,9 +224,9 @@ public class BlockStateValues { * @param state BlockState of the block * @return Shulker direction value or -1 if no value */ - public static byte getShulkerBoxDirection(BlockState state) { + public static byte getShulkerBoxDirection(int state) { if (SHULKERBOX_DIRECTIONS.containsKey(state)) { - return SHULKERBOX_DIRECTIONS.getByte(state); + return SHULKERBOX_DIRECTIONS.get(state); } return -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 d6f446f0..e627b845 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 @@ -26,14 +26,14 @@ package org.geysermc.connector.network.translators.world.block; import com.fasterxml.jackson.databind.JsonNode; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; -import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.NBTInputStream; +import com.nukkitx.nbt.NbtList; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; +import com.nukkitx.nbt.NbtType; import com.nukkitx.nbt.NbtUtils; -import com.nukkitx.nbt.stream.NBTInputStream; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.nbt.tag.ListTag; import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -46,20 +46,20 @@ import java.io.InputStream; import java.util.*; public class BlockTranslator { - public static final ListTag BLOCKS; - public static final BlockState AIR = new BlockState(0); + public static final NbtList BLOCKS; + public static final int AIR = 0; public static final int BEDROCK_WATER_ID; private static final Int2IntMap JAVA_TO_BEDROCK_BLOCK_MAP = new Int2IntOpenHashMap(); - private static final Int2ObjectMap BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>(); - private static final BiMap JAVA_ID_BLOCK_MAP = HashBiMap.create(); + private static final Int2IntMap BEDROCK_TO_JAVA_BLOCK_MAP = new Int2IntOpenHashMap(); + private static final BiMap JAVA_ID_BLOCK_MAP = HashBiMap.create(); private static final IntSet WATERLOGGED = new IntOpenHashSet(); - private static final Object2IntMap ITEM_FRAMES = new Object2IntOpenHashMap<>(); + private static final Object2IntMap ITEM_FRAMES = new Object2IntOpenHashMap<>(); // Bedrock carpet ID, used in LlamaEntity.java for decoration public static final int CARPET = 171; - private static final Map JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); + private static final Int2ObjectMap JAVA_ID_TO_BLOCK_ENTITY_MAP = new Int2ObjectOpenHashMap<>(); public static final Int2DoubleMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2DoubleOpenHashMap(); public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND = new Int2BooleanOpenHashMap(); @@ -74,22 +74,22 @@ public class BlockTranslator { public static final int JAVA_RUNTIME_SPAWNER_ID; - private static final int BLOCK_STATE_VERSION = 17760256; + private static final int BLOCK_STATE_VERSION = 17825806; static { /* Load block palette */ InputStream stream = FileUtils.getResource("bedrock/runtime_block_states.dat"); - ListTag blocksTag; + NbtList blocksTag; try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) { - blocksTag = (ListTag) nbtInputStream.readTag(); + blocksTag = (NbtList) nbtInputStream.readTag(); } catch (Exception e) { throw new AssertionError("Unable to get blocks from runtime block states", e); } - Map blockStateMap = new HashMap<>(); + Map blockStateMap = new HashMap<>(); - for (CompoundTag tag : blocksTag.getValue()) { + for (NbtMap tag : blocksTag) { if (blockStateMap.putIfAbsent(tag.getCompound("block"), tag) != null) { throw new AssertionError("Duplicate block states in Bedrock palette"); } @@ -102,9 +102,9 @@ public class BlockTranslator { } catch (Exception e) { throw new AssertionError("Unable to load Java block mappings", e); } - Object2IntMap addedStatesMap = new Object2IntOpenHashMap<>(); + Object2IntMap addedStatesMap = new Object2IntOpenHashMap<>(); addedStatesMap.defaultReturnValue(-1); - List paletteList = new ArrayList<>(); + List paletteList = new ArrayList<>(); Reflections ref = new Reflections("org.geysermc.connector.network.translators.world.block.entity"); ref.getTypesAnnotatedWith(BlockEntity.class); @@ -121,8 +121,7 @@ public class BlockTranslator { javaRuntimeId++; Map.Entry entry = blocksIterator.next(); String javaId = entry.getKey(); - BlockState javaBlockState = new BlockState(javaRuntimeId); - CompoundTag blockTag = buildBedrockState(entry.getValue()); + NbtMap blockTag = buildBedrockState(entry.getValue()); // TODO fix this, (no block should have a null hardness) JsonNode hardnessNode = entry.getValue().get("block_hardness"); @@ -130,7 +129,11 @@ public class BlockTranslator { JAVA_RUNTIME_ID_TO_HARDNESS.put(javaRuntimeId, hardnessNode.doubleValue()); } - JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND.put(javaRuntimeId, entry.getValue().get("can_break_with_hand").booleanValue()); + try { + JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND.put(javaRuntimeId, entry.getValue().get("can_break_with_hand").booleanValue()); + } catch (Exception e) { + JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND.put(javaRuntimeId, false); + } JsonNode toolTypeNode = entry.getValue().get("tool_type"); if (toolTypeNode != null) { @@ -145,7 +148,7 @@ public class BlockTranslator { cobwebRuntimeId = javaRuntimeId; } - JAVA_ID_BLOCK_MAP.put(javaId, javaBlockState); + JAVA_ID_BLOCK_MAP.put(javaId, javaRuntimeId); // Used for adding all "special" Java block states to block state map String identifier; @@ -154,12 +157,12 @@ public class BlockTranslator { identifier = clazz.getAnnotation(BlockEntity.class).regex(); // Endswith, or else the block bedrock gets picked up for bed if (bedrock_identifer.endsWith(identifier) && !identifier.equals("")) { - JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaBlockState, clazz.getAnnotation(BlockEntity.class).name()); + JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaRuntimeId, clazz.getAnnotation(BlockEntity.class).name()); break; } } - BlockStateValues.storeBlockStateValues(entry, javaBlockState); + BlockStateValues.storeBlockStateValues(entry, javaRuntimeId); // Get the tag needed for non-empty flower pots if (entry.getValue().get("pottable") != null) { @@ -173,13 +176,13 @@ public class BlockTranslator { || javaId.contains("minecraft:bubble_column") || javaId.contains("minecraft:kelp") || javaId.contains("seagrass"); if (waterlogged) { - BEDROCK_TO_JAVA_BLOCK_MAP.putIfAbsent(bedrockRuntimeId | 1 << 31, javaBlockState); + BEDROCK_TO_JAVA_BLOCK_MAP.putIfAbsent(bedrockRuntimeId | 1 << 31, javaRuntimeId); WATERLOGGED.add(javaRuntimeId); } else { - BEDROCK_TO_JAVA_BLOCK_MAP.putIfAbsent(bedrockRuntimeId, javaBlockState); + BEDROCK_TO_JAVA_BLOCK_MAP.putIfAbsent(bedrockRuntimeId, javaRuntimeId); } - CompoundTag runtimeTag = blockStateMap.remove(blockTag); + NbtMap runtimeTag = blockStateMap.remove(blockTag); if (runtimeTag != null) { addedStatesMap.put(blockTag, bedrockRuntimeId); paletteList.add(runtimeTag); @@ -238,15 +241,15 @@ public class BlockTranslator { // Loop around again to find all item frame runtime IDs int frameRuntimeId = 0; - for (CompoundTag tag : paletteList) { - CompoundTag blockTag = tag.getCompound("block"); + for (NbtMap tag : paletteList) { + NbtMap blockTag = tag.getCompound("block"); if (blockTag.getString("name").equals("minecraft:frame")) { ITEM_FRAMES.put(tag, frameRuntimeId); } frameRuntimeId++; } - BLOCKS = new ListTag<>("", CompoundTag.class, paletteList); + BLOCKS = new NbtList<>(NbtType.COMPOUND, paletteList); } private BlockTranslator() { @@ -256,12 +259,12 @@ public class BlockTranslator { // no-op } - private static CompoundTag buildBedrockState(JsonNode node) { - CompoundTagBuilder tagBuilder = CompoundTag.builder(); - tagBuilder.stringTag("name", node.get("bedrock_identifier").textValue()) - .intTag("version", BlockTranslator.BLOCK_STATE_VERSION); + private static NbtMap buildBedrockState(JsonNode node) { + NbtMapBuilder tagBuilder = NbtMap.builder(); + tagBuilder.putString("name", node.get("bedrock_identifier").textValue()) + .putInt("version", BlockTranslator.BLOCK_STATE_VERSION); - CompoundTagBuilder statesBuilder = CompoundTag.builder(); + NbtMapBuilder statesBuilder = NbtMap.builder(); // check for states if (node.has("bedrock_states")) { @@ -272,32 +275,29 @@ public class BlockTranslator { JsonNode stateValue = stateEntry.getValue(); switch (stateValue.getNodeType()) { case BOOLEAN: - statesBuilder.booleanTag(stateEntry.getKey(), stateValue.booleanValue()); + statesBuilder.putBoolean(stateEntry.getKey(), stateValue.booleanValue()); continue; case STRING: - statesBuilder.stringTag(stateEntry.getKey(), stateValue.textValue()); + statesBuilder.putString(stateEntry.getKey(), stateValue.textValue()); continue; case NUMBER: - statesBuilder.intTag(stateEntry.getKey(), stateValue.intValue()); + statesBuilder.putInt(stateEntry.getKey(), stateValue.intValue()); } } } - return tagBuilder.tag(statesBuilder.build("states")).build("block"); + tagBuilder.put("states", statesBuilder.build()); + return tagBuilder.build(); } - public static int getBedrockBlockId(BlockState state) { - return JAVA_TO_BEDROCK_BLOCK_MAP.get(state.getId()); + public static int getBedrockBlockId(int state) { + return JAVA_TO_BEDROCK_BLOCK_MAP.get(state); } - public static int getBedrockBlockId(int javaId) { - return JAVA_TO_BEDROCK_BLOCK_MAP.get(javaId); - } - - public static BlockState getJavaBlockState(int bedrockId) { + public static int getJavaBlockState(int bedrockId) { return BEDROCK_TO_JAVA_BLOCK_MAP.get(bedrockId); } - public static int getItemFrame(CompoundTag tag) { + public static int getItemFrame(NbtMap tag) { return ITEM_FRAMES.getOrDefault(tag, -1); } @@ -309,23 +309,23 @@ public class BlockTranslator { return BLOCK_STATE_VERSION; } - public static BlockState getJavaBlockState(String javaId) { + public static int getJavaBlockState(String javaId) { return JAVA_ID_BLOCK_MAP.get(javaId); } - public static String getBlockEntityString(BlockState javaId) { + public static String getBlockEntityString(int javaId) { return JAVA_ID_TO_BLOCK_ENTITY_MAP.get(javaId); } - public static boolean isWaterlogged(BlockState state) { - return WATERLOGGED.contains(state.getId()); + public static boolean isWaterlogged(int state) { + return WATERLOGGED.contains(state); } - public static BiMap getJavaIdBlockMap() { + public static BiMap getJavaIdBlockMap() { return JAVA_ID_BLOCK_MAP; } - public static BlockState getJavaWaterloggedState(int bedrockId) { + public static int getJavaWaterloggedState(int bedrockId) { return BEDROCK_TO_JAVA_BLOCK_MAP.get(1 << 31 | bedrockId); } } 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 3e2c0a95..e2a55509 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 @@ -25,43 +25,41 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.IntTag; -import com.nukkitx.nbt.tag.StringTag; -import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtType; import org.geysermc.connector.network.translators.item.translators.BannerTranslator; import org.geysermc.connector.network.translators.world.block.BlockStateValues; import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; @BlockEntity(name = "Banner", regex = "banner") public class BannerBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public boolean isBlock(BlockState blockState) { + public boolean isBlock(int blockState) { return BlockStateValues.getBannerColor(blockState) != -1; } @Override - public List> translateTag(CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); + public Map translateTag(CompoundTag tag, int blockState) { + Map tags = new HashMap<>(); int bannerColor = BlockStateValues.getBannerColor(blockState); if (bannerColor != -1) { - tags.add(new IntTag("Base", 15 - bannerColor)); + tags.put("Base", 15 - bannerColor); } if (tag.contains("Patterns")) { ListTag patterns = tag.get("Patterns"); - tags.add(BannerTranslator.convertBannerPattern(patterns)); + tags.put("", BannerTranslator.convertBannerPattern(patterns)); } if (tag.contains("CustomName")) { - tags.add(new StringTag("CustomName", (String) tag.get("CustomName").getValue())); + tags.put("CustomName", tag.get("CustomName").getValue()); } return tags; @@ -75,9 +73,9 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator implement } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.listTag("Patterns", com.nukkitx.nbt.tag.CompoundTag.class, new ArrayList<>()); - return tagBuilder.buildRootTag(); + public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return getConstantBedrockTag(bedrockId, x, y, z).toBuilder() + .putList("Patterns", NbtType.COMPOUND, new ArrayList<>()) + .build(); } } 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 5f0b1cc0..b84aad98 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 @@ -25,31 +25,28 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.ByteTag; -import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.nbt.NbtMap; import org.geysermc.connector.network.translators.world.block.BlockStateValues; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; @BlockEntity(name = "Bed", regex = "bed") public class BedBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public boolean isBlock(BlockState blockState) { + public boolean isBlock(int blockState) { return BlockStateValues.getBedColor(blockState) != -1; } @Override - public List> translateTag(CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); + public Map translateTag(CompoundTag tag, int blockState) { + Map tags = new HashMap<>(); byte bedcolor = BlockStateValues.getBedColor(blockState); // Just in case... if (bedcolor == -1) bedcolor = 0; - tags.add(new ByteTag("color", bedcolor)); + tags.put("color", bedcolor); return tags; } @@ -59,9 +56,9 @@ public class BedBlockEntityTranslator extends BlockEntityTranslator implements R } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.byteTag("color", (byte) 0); - return tagBuilder.buildRootTag(); + public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return getConstantBedrockTag(bedrockId, x, y, z).toBuilder() + .putByte("color", (byte) 0) + .build(); } } 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 5b325eba..0a91cb79 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 @@ -26,9 +26,8 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.nbt.NbtMap; import org.geysermc.connector.network.session.GeyserSession; /** @@ -42,7 +41,7 @@ public interface BedrockOnlyBlockEntity { * @param blockState The Java block state. * @param position The Bedrock block position. */ - void updateBlock(GeyserSession session, BlockState blockState, Vector3i position); + void updateBlock(GeyserSession session, int blockState, Vector3i position); /** * Get the tag of the Bedrock-only block entity @@ -50,7 +49,7 @@ public interface BedrockOnlyBlockEntity { * @param blockState Java BlockState of block. * @return Bedrock tag, or null if not a Bedrock-only Block Entity */ - static CompoundTag getTag(Vector3i position, BlockState blockState) { + static NbtMap getTag(Vector3i position, int blockState) { if (new FlowerPotBlockEntityTranslator().isBlock(blockState)) { return FlowerPotBlockEntityTranslator.getTag(blockState, position); } else if (PistonBlockEntityTranslator.isBlock(blockState)) { 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 c87938dd..c4401c4c 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 @@ -25,20 +25,19 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.utils.BlockEntityUtils; +import org.geysermc.connector.utils.LanguageUtils; import org.reflections.Reflections; import java.util.HashMap; -import java.util.List; import java.util.Map; public abstract class BlockEntityTranslator { @@ -74,7 +73,7 @@ public abstract class BlockEntityTranslator { try { BLOCK_ENTITY_TRANSLATORS.put(clazz.getAnnotation(BlockEntity.class).name(), (BlockEntityTranslator) clazz.newInstance()); } catch (InstantiationException | IllegalAccessException e) { - GeyserConnector.getInstance().getLogger().error("Could not instantiate annotated block entity " + clazz.getCanonicalName() + "."); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.block_entity.failed", clazz.getCanonicalName())); } } for (Class clazz : ref.getSubTypesOf(RequiresBlockState.class)) { @@ -83,25 +82,26 @@ public abstract class BlockEntityTranslator { try { REQUIRES_BLOCK_STATE_LIST.add((RequiresBlockState) clazz.newInstance()); } catch (InstantiationException | IllegalAccessException e) { - GeyserConnector.getInstance().getLogger().error("Could not instantiate required block state " + clazz.getCanonicalName() + "."); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.network.translator.block_state.failed", clazz.getCanonicalName())); } } } - public abstract List> translateTag(CompoundTag tag, BlockState blockState); + public abstract Map translateTag(CompoundTag tag, int blockState); public abstract CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z); - public abstract com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z); + public abstract NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z); - public com.nukkitx.nbt.tag.CompoundTag getBlockEntityTag(String id, CompoundTag tag, BlockState 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())); - CompoundTagBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(id), x, y, z).toBuilder(); - translateTag(tag, blockState).forEach(tagBuilder::tag); - return tagBuilder.buildRootTag(); + NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(id), x, y, z).toBuilder(); + Map translatedTags = translateTag(tag, blockState); + translatedTags.forEach(tagBuilder::put); + return tagBuilder.build(); } protected CompoundTag getConstantJavaTag(String javaId, int x, int y, int z) { @@ -113,13 +113,13 @@ public abstract class BlockEntityTranslator { return tag; } - protected com.nukkitx.nbt.tag.CompoundTag getConstantBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() - .intTag("x", x) - .intTag("y", y) - .intTag("z", z) - .stringTag("id", bedrockId); - return tagBuilder.buildRootTag(); + protected NbtMap getConstantBedrockTag(String bedrockId, int x, int y, int z) { + return NbtMap.builder() + .putInt("x", x) + .putInt("y", y) + .putInt("z", z) + .putString("id", bedrockId) + .build(); } @SuppressWarnings("unchecked") 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 cd31636c..e3d2c9f5 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 @@ -25,28 +25,26 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.ListTag; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; import org.geysermc.connector.network.translators.item.ItemEntry; import org.geysermc.connector.network.translators.item.ItemRegistry; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; +import java.util.Map; @BlockEntity(name = "Campfire", regex = "campfire") public class CampfireBlockEntityTranslator extends BlockEntityTranslator { @Override - public List> translateTag(CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); + public Map translateTag(CompoundTag tag, int blockState) { + Map tags = new HashMap<>(); ListTag items = tag.get("Items"); int i = 1; for (com.github.steveice10.opennbt.tag.builtin.Tag itemTag : items.getValue()) { - tags.add(getItem((CompoundTag) itemTag).toBuilder().build("Item" + i)); + tags.put("Item" + i, getItem((CompoundTag) itemTag)); i++; } return tags; @@ -60,22 +58,17 @@ public class CampfireBlockEntityTranslator extends BlockEntityTranslator { } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item1", new HashMap<>())); - tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item2", new HashMap<>())); - tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item3", new HashMap<>())); - tagBuilder.tag(new com.nukkitx.nbt.tag.CompoundTag("Item4", new HashMap<>())); - return tagBuilder.buildRootTag(); + public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return getConstantBedrockTag(bedrockId, x, y, z); } - protected com.nukkitx.nbt.tag.CompoundTag getItem(CompoundTag tag) { + protected NbtMap getItem(CompoundTag tag) { ItemEntry entry = ItemRegistry.getItemEntry((String) tag.get("id").getValue()); - CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() - .shortTag("id", (short) entry.getBedrockId()) - .byteTag("Count", (byte) tag.get("Count").getValue()) - .shortTag("Damage", (short) entry.getBedrockData()) - .tag(CompoundTagBuilder.builder().build("tag")); - return tagBuilder.buildRootTag(); + NbtMapBuilder tagBuilder = NbtMap.builder() + .putShort("id", (short) entry.getBedrockId()) + .putByte("Count", (byte) tag.get("Count").getValue()) + .putShort("Damage", (short) entry.getBedrockData()); + tagBuilder.put("tag", NbtMap.builder().build()); + return tagBuilder.build(); } } 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 f5599832..012d0c59 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 @@ -26,20 +26,17 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.ByteTag; -import com.nukkitx.nbt.tag.IntTag; -import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; import org.geysermc.connector.network.session.GeyserSession; 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.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; /** * Chests have more block entity properties in Bedrock, which is solved by implementing the BedrockOnlyBlockEntity @@ -48,23 +45,23 @@ import java.util.List; public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator implements BedrockOnlyBlockEntity, RequiresBlockState { @Override - public boolean isBlock(BlockState blockState) { - return BlockStateValues.getDoubleChestValues().containsKey(blockState.getId()); + public boolean isBlock(int blockState) { + return BlockStateValues.getDoubleChestValues().containsKey(blockState); } @Override - public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { + public void updateBlock(GeyserSession session, int blockState, Vector3i position) { CompoundTag javaTag = getConstantJavaTag("chest", position.getX(), position.getY(), position.getZ()); - CompoundTagBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId("chest"), position.getX(), position.getY(), position.getZ()).toBuilder(); - translateTag(javaTag, blockState).forEach(tagBuilder::tag); - BlockEntityUtils.updateBlockEntity(session, tagBuilder.buildRootTag(), position); + NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId("chest"), position.getX(), position.getY(), position.getZ()).toBuilder(); + translateTag(javaTag, blockState).forEach(tagBuilder::put); + BlockEntityUtils.updateBlockEntity(session, tagBuilder.build(), position); } @Override - public List> translateTag(CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); - if (blockState != null && BlockStateValues.getDoubleChestValues().containsKey(blockState.getId())) { - DoubleChestValue chestValues = BlockStateValues.getDoubleChestValues().get(blockState.getId()); + 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(); @@ -86,10 +83,10 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl x = x + (chestValues.isLeft ? 1 : -1); } } - tags.add(new IntTag("pairx", x)); - tags.add(new IntTag("pairz", z)); + tags.put("pairx", x); + tags.put("pairz", z); if (!chestValues.isLeft) { - tags.add(new ByteTag("pairlead", (byte) 1)); + tags.put("pairlead", (byte) 1); } } } @@ -102,7 +99,7 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) { return null; } } 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 d1068277..6de13611 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 @@ -25,19 +25,18 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.nbt.NbtMap; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; @BlockEntity(name = "Empty", regex = "") public class EmptyBlockEntityTranslator extends BlockEntityTranslator { @Override - public List> translateTag(CompoundTag tag, BlockState blockState) { - return new ArrayList<>(); + public Map translateTag(CompoundTag tag, int blockState) { + return new HashMap<>(); } @Override @@ -46,7 +45,7 @@ public class EmptyBlockEntityTranslator extends BlockEntityTranslator { } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) { return getConstantBedrockTag(bedrockId, x, y, z); } } 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 4cd2eaa9..784afed5 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 @@ -25,34 +25,34 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.LongTag; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.IntTag; -import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.nbt.NbtList; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtType; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; -import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.LinkedHashMap; -import java.util.List; +import java.util.Map; @BlockEntity(name = "EndGateway", regex = "end_gateway") public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator { @Override - public List> translateTag(CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); - tags.add(new IntTag("Age", (int) (long) tag.get("Age").getValue())); + public Map translateTag(CompoundTag tag, int blockState) { + Map tags = new HashMap<>(); + tags.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 - List tagsList = new ArrayList<>(); + IntList tagsList = new IntArrayList(); // Yes, the axis letters are capitalized - tagsList.add(new IntTag("", getExitPortalCoordinate(tag, "X"))); - tagsList.add(new IntTag("", getExitPortalCoordinate(tag, "Y"))); - tagsList.add(new IntTag("", getExitPortalCoordinate(tag, "Z"))); - com.nukkitx.nbt.tag.ListTag exitPortal = - new com.nukkitx.nbt.tag.ListTag<>("ExitPortal", IntTag.class, tagsList); - tags.add(exitPortal); + 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; } @@ -64,20 +64,16 @@ public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator { } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - List tagsList = new ArrayList<>(); - tagsList.add(new IntTag("", 0)); - tagsList.add(new IntTag("", 0)); - tagsList.add(new IntTag("", 0)); - tagBuilder.listTag("ExitPortal", IntTag.class, tagsList); - return tagBuilder.buildRootTag(); + public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return getConstantBedrockTag(bedrockId, x, y, z).toBuilder() + .putList("ExitPortal", NbtType.INT, Arrays.asList(0, 0, 0)) + .build(); } private int getExitPortalCoordinate(CompoundTag tag, String axis) { // Return 0 if it doesn't exist, otherwise give proper value if (tag.get("ExitPortal") != null) { - LinkedHashMap compoundTag = (LinkedHashMap) tag.get("ExitPortal").getValue(); + LinkedHashMap compoundTag = (LinkedHashMap) tag.get("ExitPortal").getValue(); com.github.steveice10.opennbt.tag.builtin.IntTag intTag = (com.github.steveice10.opennbt.tag.builtin.IntTag) compoundTag.get(axis); return intTag.getValue(); } 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 c4748c82..1e7cda5f 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 @@ -26,10 +26,9 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.block.BlockStateValues; @@ -39,46 +38,47 @@ import org.geysermc.connector.utils.BlockEntityUtils; public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity, RequiresBlockState { @Override - public boolean isBlock(BlockState blockState) { - return (BlockStateValues.getFlowerPotValues().containsKey(blockState.getId())); + public boolean isBlock(int blockState) { + return (BlockStateValues.getFlowerPotValues().containsKey(blockState)); } @Override - public void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { + 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.PRIORITY); - updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NONE); 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); } /** * Get the Nukkit CompoundTag of the flower pot. - * @param blockState Java BlockState of flower pot. + * @param blockState Java block state of flower pot. * @param position Bedrock position of flower pot. * @return Bedrock tag of flower pot. */ - public static CompoundTag getTag(BlockState blockState, Vector3i position) { - CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() - .intTag("x", position.getX()) - .intTag("y", position.getY()) - .intTag("z", position.getZ()) - .byteTag("isMovable", (byte) 1) - .stringTag("id", "FlowerPot"); + public static NbtMap getTag(int blockState, Vector3i position) { + NbtMapBuilder tagBuilder = NbtMap.builder() + .putInt("x", position.getX()) + .putInt("y", position.getY()) + .putInt("z", position.getZ()) + .putByte("isMovable", (byte) 1) + .putString("id", "FlowerPot"); // Get the Java name of the plant inside. e.g. minecraft:oak_sapling - String name = BlockStateValues.getFlowerPotValues().get(blockState.getId()); + String name = BlockStateValues.getFlowerPotValues().get(blockState); if (name != null) { // Get the Bedrock CompoundTag of the block. // This is where we need to store the *Java* name because Bedrock has six minecraft:sapling blocks with different block states. - CompoundTag plant = BlockStateValues.getFlowerPotBlocks().get(name); + NbtMap plant = BlockStateValues.getFlowerPotBlocks().get(name); if (plant != null) { - tagBuilder.tag(plant.toBuilder().build("PlantBlock")); + tagBuilder.put("PlantBlock", plant.toBuilder().build()); } } - return tagBuilder.buildRootTag(); + return tagBuilder.build(); } } 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 168015f6..ca5a4f52 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 @@ -27,7 +27,6 @@ package org.geysermc.connector.network.translators.world.block.entity; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.math.vector.Vector3i; import com.nukkitx.protocol.bedrock.packet.BlockEventPacket; import org.geysermc.connector.network.session.GeyserSession; @@ -40,12 +39,12 @@ import org.geysermc.connector.utils.ChunkUtils; public class NoteblockBlockEntityTranslator implements RequiresBlockState { @Override - public boolean isBlock(BlockState blockState) { + public boolean isBlock(int blockState) { return BlockStateValues.getNoteblockPitch(blockState) != -1; } public static void translate(GeyserSession session, Position position) { - BlockState blockState = ChunkUtils.CACHED_BLOCK_ENTITIES.get(position); + int blockState = ChunkUtils.CACHED_BLOCK_ENTITIES.getOrDefault(position, 0); BlockEventPacket blockEventPacket = new BlockEventPacket(); blockEventPacket.setBlockPosition(Vector3i.from(position.getX(), position.getY(), position.getZ())); blockEventPacket.setEventType(0); 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 2dffce24..a2362e81 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 @@ -26,10 +26,9 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.CompoundTag; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; import org.geysermc.connector.network.translators.world.block.BlockStateValues; /** @@ -42,31 +41,31 @@ public class PistonBlockEntityTranslator { * @param blockState Java BlockState of block. * @return if block is a piston or not. */ - public static boolean isBlock(BlockState blockState) { - return BlockStateValues.getPistonValues().containsKey(blockState.getId()); + public static boolean isBlock(int blockState) { + return BlockStateValues.getPistonValues().containsKey(blockState); } /** * Calculates the Nukkit CompoundTag to send to the client on chunk - * @param blockState Java BlockState of block. + * @param blockState Java block state of block. * @param position Bedrock position of piston. * @return Bedrock tag of piston. */ - public static CompoundTag getTag(BlockState blockState, Vector3i position) { - CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder() - .intTag("x", position.getX()) - .intTag("y", position.getY()) - .intTag("z", position.getZ()) - .byteTag("isMovable", (byte) 1) - .stringTag("id", "PistonArm"); - if (BlockStateValues.getPistonValues().containsKey(blockState.getId())) { - boolean extended = BlockStateValues.getPistonValues().get(blockState.getId()); + public static NbtMap getTag(int blockState, Vector3i position) { + NbtMapBuilder tagBuilder = NbtMap.builder() + .putInt("x", position.getX()) + .putInt("y", position.getY()) + .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.floatTag("Progress", (extended) ? 1.0f : 0.0f); + tagBuilder.putFloat("Progress", (extended) ? 1.0f : 0.0f); // 1 if sticky, 0 if not - tagBuilder.byteTag("Sticky", (byte)((BlockStateValues.isStickyPiston(blockState)) ? 1 : 0)); + tagBuilder.putByte("Sticky", (byte)((BlockStateValues.isStickyPiston(blockState)) ? 1 : 0)); } - return tagBuilder.buildRootTag(); + return tagBuilder.build(); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/RequiresBlockState.java b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/RequiresBlockState.java index 4df7292a..0db306aa 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/RequiresBlockState.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/world/block/entity/RequiresBlockState.java @@ -25,8 +25,6 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; - /** * Implemented in block entities if their Java block state is required for additional values in Bedrock */ @@ -37,6 +35,6 @@ public interface RequiresBlockState { * @param blockState BlockState to be compared * @return true if part of the class */ - boolean isBlock(BlockState blockState); + boolean isBlock(int blockState); } 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 373b963e..329b3a8a 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,28 +26,24 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.ByteTag; -import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.nbt.NbtMap; import org.geysermc.connector.network.translators.world.block.BlockStateValues; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; @BlockEntity(name = "ShulkerBox", regex = "shulker_box") public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator { @Override - public List> translateTag(CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); + public Map translateTag(CompoundTag tag, int blockState) { + Map tags = new HashMap<>(); byte direction = BlockStateValues.getShulkerBoxDirection(blockState); // Just in case... if (direction == -1) direction = 1; - tags.add(new ByteTag("facing", direction)); - + tags.put("facing", direction); return tags; } @@ -57,9 +53,9 @@ public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator { } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.byteTag("facing", (byte)1); - return tagBuilder.buildRootTag(); + public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return getConstantBedrockTag(bedrockId, x, y, z).toBuilder() + .putByte("facing", (byte) 1) + .build(); } } 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 6c170462..a95c853e 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,30 +25,26 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.github.steveice10.mc.protocol.data.message.Message; +import com.github.steveice10.mc.protocol.data.message.MessageSerializer; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.StringTag; -import com.nukkitx.nbt.tag.Tag; -import io.netty.util.internal.StringUtil; +import com.nukkitx.nbt.NbtMap; import org.geysermc.connector.utils.MessageUtils; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; @BlockEntity(name = "Sign", regex = "sign") public class SignBlockEntityTranslator extends BlockEntityTranslator { @Override - public List> translateTag(CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); + 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(Message.fromString(signLine)); + signLine = MessageUtils.getBedrockMessage(MessageSerializer.fromString(signLine)); //Java allows up to 16+ characters on certain symbols. if(signLine.length() >= 15 && (signLine.contains("-") || signLine.contains("="))) { @@ -59,7 +55,7 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { signText.append("\n"); } - tags.add(new StringTag("Text", MessageUtils.getBedrockMessage(Message.fromString(signText.toString())))); + tags.put("Text", MessageUtils.getBedrockMessage(MessageSerializer.fromString(signText.toString()))); return tags; } @@ -74,9 +70,9 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator { } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.stringTag("Text", ""); - return tagBuilder.buildRootTag(); + public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return getConstantBedrockTag(bedrockId, x, y, z).toBuilder() + .putString("Text", "") + .build(); } } 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 9393f7bb..9547ba2f 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,34 +25,29 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.ByteTag; -import com.nukkitx.nbt.tag.CompoundTag; -import com.nukkitx.nbt.tag.FloatTag; -import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.nbt.NbtMap; import org.geysermc.connector.network.translators.world.block.BlockStateValues; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; @BlockEntity(name = "Skull", regex = "skull") public class SkullBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState { @Override - public boolean isBlock(BlockState blockState) { + public boolean isBlock(int blockState) { return BlockStateValues.getSkullVariant(blockState) != -1; } @Override - public List> translateTag(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); + public Map translateTag(com.github.steveice10.opennbt.tag.builtin.CompoundTag tag, int blockState) { + Map tags = new HashMap<>(); byte skullVariant = BlockStateValues.getSkullVariant(blockState); float rotation = BlockStateValues.getSkullRotation(blockState) * 22.5f; // Just in case... if (skullVariant == -1) skullVariant = 0; - tags.add(new FloatTag("Rotation", rotation)); - tags.add(new ByteTag("SkullType", skullVariant)); + tags.put("Rotation", rotation); + tags.put("SkullType", skullVariant); return tags; } @@ -62,10 +57,10 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements } @Override - public CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.floatTag("Rotation", 0); - tagBuilder.byteTag("SkullType", (byte) 0); - return tagBuilder.buildRootTag(); + public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return getConstantBedrockTag(bedrockId, x, y, z).toBuilder() + .putFloat("Rotation", 0f) + .putByte("SkullType", (byte) 0) + .build(); } } 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 100dbddd..e911feaa 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,65 +26,63 @@ package org.geysermc.connector.network.translators.world.block.entity; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.*; +import com.nukkitx.nbt.NbtMap; import org.geysermc.connector.entity.type.EntityType; -import java.util.ArrayList; -import java.util.List; +import java.util.HashMap; +import java.util.Map; @BlockEntity(name = "MobSpawner", regex = "mob_spawner") public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { @Override - public List> translateTag(CompoundTag tag, BlockState blockState) { - List> tags = new ArrayList<>(); + public Map translateTag(CompoundTag tag, int blockState) { + Map tags = new HashMap<>(); if (tag.get("MaxNearbyEntities") != null) { - tags.add(new ShortTag("MaxNearbyEntities", (short) tag.get("MaxNearbyEntities").getValue())); + tags.put("MaxNearbyEntities", (short) tag.get("MaxNearbyEntities").getValue()); } if (tag.get("RequiredPlayerRange") != null) { - tags.add(new ShortTag("RequiredPlayerRange", (short) tag.get("RequiredPlayerRange").getValue())); + tags.put("RequiredPlayerRange", (short) tag.get("RequiredPlayerRange").getValue()); } if (tag.get("SpawnCount") != null) { - tags.add(new ShortTag("SpawnCount", (short) tag.get("SpawnCount").getValue())); + tags.put("SpawnCount", (short) tag.get("SpawnCount").getValue()); } if (tag.get("MaxSpawnDelay") != null) { - tags.add(new ShortTag("MaxSpawnDelay", (short) tag.get("MaxSpawnDelay").getValue())); + tags.put("MaxSpawnDelay", (short) tag.get("MaxSpawnDelay").getValue()); } if (tag.get("Delay") != null) { - tags.add(new ShortTag("Delay", (short) tag.get("Delay").getValue())); + tags.put("Delay", (short) tag.get("Delay").getValue()); } if (tag.get("SpawnRange") != null) { - tags.add(new ShortTag("SpawnRange", (short) tag.get("SpawnRange").getValue())); + tags.put("SpawnRange", (short) tag.get("SpawnRange").getValue()); } if (tag.get("MinSpawnDelay") != null) { - tags.add(new ShortTag("MinSpawnDelay", (short) tag.get("MinSpawnDelay").getValue())); + tags.put("MinSpawnDelay", (short) tag.get("MinSpawnDelay").getValue()); } if (tag.get("SpawnData") != null) { CompoundTag spawnData = tag.get("SpawnData"); String entityID = (String) spawnData.get("id").getValue(); - tags.add(new StringTag("EntityIdentifier", entityID)); + tags.put("EntityIdentifier", entityID); EntityType type = EntityType.getFromIdentifier(entityID); if (type != null) { - tags.add(new FloatTag("DisplayEntityWidth", type.getWidth())); - tags.add(new FloatTag("DisplayEntityHeight", type.getHeight())); - tags.add(new FloatTag("DisplayEntityScale", 1.0f)); + tags.put("DisplayEntityWidth", type.getWidth()); + tags.put("DisplayEntityHeight", type.getHeight()); + tags.put("DisplayEntityScale", 1.0f); } } - tags.add(new StringTag("id", "MobSpawner")); - tags.add(new ByteTag("isMovable", (byte) 1)); + tags.put("id", "MobSpawner"); + tags.put("isMovable", (byte) 1); return tags; } @@ -95,11 +93,10 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator { } @Override - public com.nukkitx.nbt.tag.CompoundTag getDefaultBedrockTag(String bedrockId, int x, int y, int z) { - CompoundTagBuilder tagBuilder = getConstantBedrockTag(bedrockId, x, y, z).toBuilder(); - tagBuilder.byteTag("isMovable", (byte) 1) - .stringTag("id", "MobSpawner"); - - return tagBuilder.buildRootTag(); + public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) { + return getConstantBedrockTag(bedrockId, x, y, z).toBuilder() + .putByte("isMovable", (byte) 1) + .putString("id", "MobSpawner") + .build(); } } diff --git a/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java b/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java index 6a323d54..aa9e0503 100644 --- a/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java +++ b/connector/src/main/java/org/geysermc/connector/ping/GeyserLegacyPingPassthrough.java @@ -26,15 +26,21 @@ package org.geysermc.connector.ping; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; import com.github.steveice10.mc.protocol.MinecraftConstants; -import com.github.steveice10.mc.protocol.MinecraftProtocol; -import com.github.steveice10.mc.protocol.data.SubProtocol; -import com.github.steveice10.mc.protocol.data.status.handler.ServerInfoHandler; -import com.github.steveice10.packetlib.Client; -import com.github.steveice10.packetlib.tcp.TcpSessionFactory; -import org.geysermc.common.ping.GeyserPingInfo; +import com.nukkitx.nbt.util.VarInts; +import org.geysermc.connector.common.ping.GeyserPingInfo; import org.geysermc.connector.GeyserConnector; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.ConnectException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketTimeoutException; import java.util.concurrent.TimeUnit; public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runnable { @@ -43,13 +49,10 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn public GeyserLegacyPingPassthrough(GeyserConnector connector) { this.connector = connector; - this.pingInfo = new GeyserPingInfo(null, 0, 0); } private GeyserPingInfo pingInfo; - private Client client; - /** * Start legacy ping passthrough thread * @param connector GeyserConnector @@ -75,15 +78,51 @@ public class GeyserLegacyPingPassthrough implements IGeyserPingPassthrough, Runn @Override public void run() { try { - this.client = new Client(connector.getConfig().getRemote().getAddress(), connector.getConfig().getRemote().getPort(), new MinecraftProtocol(SubProtocol.STATUS), new TcpSessionFactory()); - this.client.getSession().setFlag(MinecraftConstants.SERVER_INFO_HANDLER_KEY, (ServerInfoHandler) (session, info) -> { - this.pingInfo = new GeyserPingInfo(info.getDescription().getFullText(), info.getPlayerInfo().getOnlinePlayers(), info.getPlayerInfo().getMaxPlayers()); - this.client.getSession().disconnect(null); - }); + Socket socket = new Socket(); + socket.connect(new InetSocketAddress(connector.getConfig().getRemote().getAddress(), connector.getConfig().getRemote().getPort()), 5000); - client.getSession().connect(); - } catch (Exception ex) { - ex.printStackTrace(); + ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream(); + DataOutputStream handshake = new DataOutputStream(byteArrayStream); + handshake.write(0x0); + VarInts.writeUnsignedInt(handshake, MinecraftConstants.PROTOCOL_VERSION); + VarInts.writeUnsignedInt(handshake, socket.getInetAddress().getHostAddress().length()); + handshake.writeBytes(socket.getInetAddress().getHostAddress()); + handshake.writeShort(socket.getPort()); + VarInts.writeUnsignedInt(handshake, 1); + + DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); + VarInts.writeUnsignedInt(dataOutputStream, byteArrayStream.size()); + dataOutputStream.write(byteArrayStream.toByteArray()); + dataOutputStream.writeByte(0x01); + dataOutputStream.writeByte(0x00); + + DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); + VarInts.readUnsignedInt(dataInputStream); + VarInts.readUnsignedInt(dataInputStream); + int length = VarInts.readUnsignedInt(dataInputStream); + byte[] buffer = new byte[length]; + dataInputStream.readFully(buffer); + dataOutputStream.writeByte(0x09); + dataOutputStream.writeByte(0x01); + dataOutputStream.writeLong(System.currentTimeMillis()); + + VarInts.readUnsignedInt(dataInputStream); + String json = new String(buffer); + + this.pingInfo = GeyserConnector.JSON_MAPPER.readValue(json, GeyserPingInfo.class); + + byteArrayStream.close(); + handshake.close(); + dataOutputStream.close(); + dataInputStream.close(); + socket.close(); + } catch (SocketTimeoutException | ConnectException ex) { + this.pingInfo = null; + this.connector.getLogger().debug("Connection timeout for ping passthrough."); + } catch (JsonParseException | JsonMappingException ex) { + this.connector.getLogger().error("Failed to parse json when pinging server!", ex); + } catch (IOException e) { + e.printStackTrace(); } } } diff --git a/connector/src/main/java/org/geysermc/connector/ping/IGeyserPingPassthrough.java b/connector/src/main/java/org/geysermc/connector/ping/IGeyserPingPassthrough.java index 7bc842df..35c8058e 100644 --- a/connector/src/main/java/org/geysermc/connector/ping/IGeyserPingPassthrough.java +++ b/connector/src/main/java/org/geysermc/connector/ping/IGeyserPingPassthrough.java @@ -26,7 +26,7 @@ package org.geysermc.connector.ping; -import org.geysermc.common.ping.GeyserPingInfo; +import org.geysermc.connector.common.ping.GeyserPingInfo; /** * Interface that retrieves ping passthrough information from the Java server 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 59d9b25f..5fdda617 100644 --- a/connector/src/main/java/org/geysermc/connector/scoreboard/Scoreboard.java +++ b/connector/src/main/java/org/geysermc/connector/scoreboard/Scoreboard.java @@ -34,6 +34,7 @@ import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import lombok.Getter; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.LanguageUtils; import java.util.*; import java.util.concurrent.atomic.AtomicLong; @@ -78,7 +79,7 @@ public class Scoreboard { public Team registerNewTeam(String teamName, Set players) { if (teams.containsKey(teamName)) { - session.getConnector().getLogger().info("Ignoring team " + teamName + ". It overrides without removing old team."); + session.getConnector().getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.translator.team.failed_overrides", teamName)); return getTeam(teamName); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/AttributeUtils.java b/connector/src/main/java/org/geysermc/connector/utils/AttributeUtils.java index 943fd239..45cd0f9b 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/AttributeUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/AttributeUtils.java @@ -27,6 +27,7 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeModifier; import com.github.steveice10.mc.protocol.data.game.entity.attribute.ModifierOperation; +import com.nukkitx.protocol.bedrock.data.AttributeData; import org.geysermc.connector.entity.attribute.Attribute; import org.geysermc.connector.entity.attribute.AttributeType; @@ -62,12 +63,12 @@ public class AttributeUtils { return new com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute(type, attribute.getValue()); } - public static com.nukkitx.protocol.bedrock.data.Attribute getBedrockAttribute(Attribute attribute) { + public static AttributeData getBedrockAttribute(Attribute attribute) { AttributeType type = attribute.getType(); if (!type.isBedrockAttribute()) return null; - return new com.nukkitx.protocol.bedrock.data.Attribute(type.getBedrockIdentifier(), attribute.getMinimum(), attribute.getMaximum(), attribute.getValue(), attribute.getDefaultValue()); + return new AttributeData(type.getBedrockIdentifier(), attribute.getMinimum(), attribute.getMaximum(), attribute.getValue(), attribute.getDefaultValue()); } /** 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 3a356e03..69c4a368 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/BlockEntityUtils.java @@ -2,6 +2,7 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.NbtMap; import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator; @@ -41,11 +42,11 @@ public class BlockEntityUtils { return blockEntityTranslator; } - public static void updateBlockEntity(GeyserSession session, com.nukkitx.nbt.tag.CompoundTag blockEntity, Position position) { + public static void updateBlockEntity(GeyserSession session, NbtMap blockEntity, Position position) { updateBlockEntity(session, blockEntity, Vector3i.from(position.getX(), position.getY(), position.getZ())); } - public static void updateBlockEntity(GeyserSession session, com.nukkitx.nbt.tag.CompoundTag blockEntity, Vector3i position) { + public static void updateBlockEntity(GeyserSession session, NbtMap blockEntity, Vector3i position) { BlockEntityDataPacket blockEntityPacket = new BlockEntityDataPacket(); blockEntityPacket.setBlockPosition(position); blockEntityPacket.setData(blockEntity); 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 f86173e2..06b40090 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ChunkUtils.java @@ -28,15 +28,14 @@ package org.geysermc.connector.utils; 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.entity.metadata.Position; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.Tag; import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.nbt.CompoundTagBuilder; +import com.nukkitx.nbt.NBTOutputStream; +import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtUtils; -import com.nukkitx.nbt.stream.NBTOutputStream; import com.nukkitx.protocol.bedrock.packet.*; import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; @@ -54,8 +53,6 @@ import org.geysermc.connector.network.translators.world.chunk.ChunkSection; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; import static org.geysermc.connector.network.translators.world.block.BlockTranslator.AIR; import static org.geysermc.connector.network.translators.world.block.BlockTranslator.BEDROCK_WATER_ID; @@ -65,9 +62,9 @@ public class ChunkUtils { /** * Temporarily stores positions of BlockState values that are needed for certain block entities actively */ - public static final Map CACHED_BLOCK_ENTITIES = new HashMap<>(); + public static final Object2IntMap CACHED_BLOCK_ENTITIES = new Object2IntOpenHashMap<>(); - private static final com.nukkitx.nbt.tag.CompoundTag EMPTY_TAG = CompoundTagBuilder.builder().buildRootTag(); + private static final NbtMap EMPTY_TAG = NbtMap.builder().build(); public static final byte[] EMPTY_LEVEL_CHUNK_DATA; static { @@ -75,7 +72,7 @@ public class ChunkUtils { outputStream.write(new byte[258]); // Biomes + Border Size + Extra Data Size try (NBTOutputStream stream = NbtUtils.createNetworkWriter(outputStream)) { - stream.write(EMPTY_TAG); + stream.writeTag(EMPTY_TAG); } EMPTY_LEVEL_CHUNK_DATA = outputStream.toByteArray(); @@ -91,10 +88,10 @@ public class ChunkUtils { CompoundTag[] blockEntities = column.getTileEntities(); // Temporarily stores positions of BlockState values per chunk load - Map blockEntityPositions = new HashMap<>(); + Object2IntMap blockEntityPositions = new Object2IntOpenHashMap<>(); // Temporarily stores compound tags of Bedrock-only block entities - ObjectArrayList bedrockOnlyBlockEntities = new ObjectArrayList<>(); + ObjectArrayList bedrockOnlyBlockEntities = new ObjectArrayList<>(); for (int chunkY = 0; chunkY < chunks.length; chunkY++) { chunkData.sections[chunkY] = new ChunkSection(); @@ -107,7 +104,7 @@ public class ChunkUtils { for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { - BlockState blockState = chunk.get(x, y, z); + int blockState = chunk.get(x, y, z); int id = BlockTranslator.getBedrockBlockId(blockState); // Check to see if the name is in BlockTranslator.getBlockEntityString, and therefore must be handled differently @@ -119,8 +116,8 @@ public class ChunkUtils { section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); // Check if block is piston or flower - only block entities in Bedrock - if (BlockStateValues.getFlowerPotValues().containsKey(blockState.getId()) || - BlockStateValues.getPistonValues().containsKey(blockState.getId())) { + if (BlockStateValues.getFlowerPotValues().containsKey(blockState) || + BlockStateValues.getPistonValues().containsKey(blockState)) { Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); bedrockOnlyBlockEntities.add(BedrockOnlyBlockEntity.getTag(Vector3i.from(pos.getX(), pos.getY(), pos.getZ()), blockState)); } @@ -134,7 +131,7 @@ public class ChunkUtils { } - com.nukkitx.nbt.tag.CompoundTag[] bedrockBlockEntities = new com.nukkitx.nbt.tag.CompoundTag[blockEntities.length + bedrockOnlyBlockEntities.size()]; + NbtMap[] bedrockBlockEntities = new NbtMap[blockEntities.length + bedrockOnlyBlockEntities.size()]; int i = 0; while (i < blockEntities.length) { CompoundTag tag = blockEntities[i]; @@ -161,11 +158,11 @@ public class ChunkUtils { String id = BlockEntityUtils.getBedrockBlockEntityId(tagName); BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(id); Position pos = new Position((int) tag.get("x").getValue(), (int) tag.get("y").getValue(), (int) tag.get("z").getValue()); - BlockState blockState = blockEntityPositions.get(pos); + int blockState = blockEntityPositions.getOrDefault(pos, 0); bedrockBlockEntities[i] = blockEntityTranslator.getBlockEntityTag(tagName, tag, blockState); i++; } - for (com.nukkitx.nbt.tag.CompoundTag tag : bedrockOnlyBlockEntities) { + for (NbtMap tag : bedrockOnlyBlockEntities) { bedrockBlockEntities[i] = tag; i++; } @@ -188,14 +185,14 @@ public class ChunkUtils { } } - public static void updateBlock(GeyserSession session, BlockState blockState, Position position) { + public static void updateBlock(GeyserSession session, int blockState, Position position) { Vector3i pos = Vector3i.from(position.getX(), position.getY(), position.getZ()); updateBlock(session, blockState, pos); } - public static void updateBlock(GeyserSession session, BlockState blockState, Vector3i position) { + 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.equals(AIR)) { + if (ItemFrameEntity.positionContainsItemFrame(session, position) && blockState == AIR) { ((ItemFrameEntity) session.getEntityCache().getEntityByJavaId(ItemFrameEntity.getItemFrameEntityId(session, position))).updateBlock(session); return; } else if (ItemFrameEntity.positionContainsItemFrame(session, position)) { @@ -214,6 +211,7 @@ public class ChunkUtils { updateBlockPacket.setBlockPosition(position); updateBlockPacket.setRuntimeId(blockId); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS); + updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); session.sendUpstreamPacket(updateBlockPacket); UpdateBlockPacket waterPacket = new UpdateBlockPacket(); @@ -272,8 +270,8 @@ public class ChunkUtils { public ChunkSection[] sections; @Getter - private com.nukkitx.nbt.tag.CompoundTag[] blockEntities = new com.nukkitx.nbt.tag.CompoundTag[0]; + private NbtMap[] blockEntities = new NbtMap[0]; @Getter - private Object2IntMap loadBlockEntitiesLater = new Object2IntOpenHashMap<>(); + private Object2IntMap loadBlockEntitiesLater = new Object2IntOpenHashMap<>(); } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java b/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java index 9444fc2a..446e4773 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java @@ -53,7 +53,7 @@ public class CooldownUtils { if (session.getAttackSpeed() == 0.0 || session.getAttackSpeed() > 20) return; // 0.0 usually happens on login and causes issues with visuals; anything above 20 means a plugin like OldCombatMechanics is being used // Needs to be sent or no subtitle packet is recognized by the client SetTitlePacket titlePacket = new SetTitlePacket(); - titlePacket.setType(SetTitlePacket.Type.SET_TITLE); + titlePacket.setType(SetTitlePacket.Type.TITLE); titlePacket.setText(" "); session.sendUpstreamPacket(titlePacket); session.setLastHitTime(System.currentTimeMillis()); @@ -70,7 +70,7 @@ public class CooldownUtils { if (session.isClosed()) return; // Don't run scheduled tasks if the client left if (lastHitTime != session.getLastHitTime()) return; // Means another cooldown has started so there's no need to continue this one SetTitlePacket titlePacket = new SetTitlePacket(); - titlePacket.setType(SetTitlePacket.Type.SET_SUBTITLE); + titlePacket.setType(SetTitlePacket.Type.SUBTITLE); titlePacket.setText(getTitle(session)); titlePacket.setFadeInTime(0); titlePacket.setFadeOutTime(5); @@ -80,7 +80,7 @@ public class CooldownUtils { session.getConnector().getGeneralThreadPool().schedule(() -> computeCooldown(session, lastHitTime), 50, TimeUnit.MILLISECONDS); // Updated per tick. 1000 divided by 20 ticks equals 50 } else { SetTitlePacket removeTitlePacket = new SetTitlePacket(); - removeTitlePacket.setType(SetTitlePacket.Type.SET_SUBTITLE); + removeTitlePacket.setType(SetTitlePacket.Type.SUBTITLE); removeTitlePacket.setText(" "); session.sendUpstreamPacket(removeTitlePacket); } 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 6c8d9f94..74db16bb 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -36,10 +36,15 @@ public class DimensionUtils { // Changes if the above-bedrock Nether building workaround is applied private static int BEDROCK_NETHER_ID = 1; - public static void switchDimension(GeyserSession session, int javaDimension) { + // Static references to all vanilla dimensions + public static final String OVERWORLD = "minecraft:overworld"; + public static final String NETHER = "minecraft:the_nether"; + 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 (bedrockDimension == player.getDimension()) + if (javaDimension.equals(player.getDimension())) return; session.getEntityCache().removeAllEntities(); @@ -55,7 +60,7 @@ public class DimensionUtils { changeDimensionPacket.setRespawn(true); changeDimensionPacket.setPosition(pos.toFloat()); session.sendUpstreamPacket(changeDimensionPacket); - player.setDimension(bedrockDimension); + player.setDimension(javaDimension); player.setPosition(pos.toFloat()); session.setSpawned(false); session.setLastChunkPosition(null); @@ -83,14 +88,14 @@ public class DimensionUtils { * @param javaDimension Dimension ID to convert * @return Converted Bedrock edition dimension ID */ - public static int javaToBedrock(int javaDimension) { + public static int javaToBedrock(String javaDimension) { switch (javaDimension) { - case -1: + case NETHER: return BEDROCK_NETHER_ID; - case 1: + case THE_END: return 2; default: - return javaDimension; + return 0; } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/DockerCheck.java b/connector/src/main/java/org/geysermc/connector/utils/DockerCheck.java index 0a5a2278..a6eb6c9b 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/DockerCheck.java +++ b/connector/src/main/java/org/geysermc/connector/utils/DockerCheck.java @@ -49,10 +49,25 @@ public class DockerCheck { String output = new String(Files.readAllBytes(Paths.get("/proc/1/cgroup"))); if (output.contains("docker")) { - bootstrap.getGeyserLogger().warning("You are most likely in a Docker container, this may cause connection issues from Geyser to the Java server"); - bootstrap.getGeyserLogger().warning("We recommended using the following IP as the remote address: " + ipAddress); + bootstrap.getGeyserLogger().warning(LanguageUtils.getLocaleStringLog("geyser.bootstrap.docker_warn.line1")); + bootstrap.getGeyserLogger().warning(LanguageUtils.getLocaleStringLog("geyser.bootstrap.docker_warn.line2", ipAddress)); } } } catch (Exception e) { } // Ignore any errors, inc ip failed to fetch, process could not run or access denied } + + public static boolean checkBasic() { + try { + String OS = System.getProperty("os.name").toLowerCase(); + if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0) { + String output = new String(Files.readAllBytes(Paths.get("/proc/1/cgroup"))); + + if (output.contains("docker")) { + return true; + } + } + } catch (Exception ignored) { } // Ignore any errors, inc ip failed to fetch, process could not run or access denied + + return false; + } } 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 04b6ecc4..0b7b5c5c 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/FileUtils.java @@ -135,7 +135,7 @@ public class FileUtils { public static InputStream getResource(String resource) { InputStream stream = FileUtils.class.getClassLoader().getResourceAsStream(resource); if (stream == null) { - throw new AssertionError("Unable to find resource: " + resource); + throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.resource", resource)); } return stream; } diff --git a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java index ded47723..325710c6 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/InventoryUtils.java @@ -27,13 +27,13 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; -import com.nukkitx.nbt.CompoundTagBuilder; -import com.nukkitx.nbt.tag.StringTag; -import com.nukkitx.protocol.bedrock.data.ContainerId; -import com.nukkitx.protocol.bedrock.data.ItemData; -import com.nukkitx.protocol.bedrock.packet.ContainerClosePacket; +import com.nukkitx.nbt.NbtMap; +import com.nukkitx.nbt.NbtMapBuilder; +import com.nukkitx.nbt.NbtType; +import com.nukkitx.protocol.bedrock.data.inventory.ContainerId; +import com.nukkitx.protocol.bedrock.data.inventory.ItemData; import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket; -import org.geysermc.common.ChatColor; +import org.geysermc.connector.common.ChatColor; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.inventory.Inventory; import org.geysermc.connector.network.session.GeyserSession; @@ -97,18 +97,24 @@ public class InventoryUtils { } public static void closeWindow(GeyserSession session, int windowId) { + //TODO: Investigate client crash when force closing window and opening a new one + //Instead, the window will eventually close by removing the fake blocks + session.setLastWindowCloseTime(System.currentTimeMillis()); + + /* //Spamming close window packets can bug the client if (System.currentTimeMillis() - session.getLastWindowCloseTime() > 500) { ContainerClosePacket closePacket = new ContainerClosePacket(); - closePacket.setWindowId((byte) windowId); + closePacket.setId((byte) windowId); session.sendUpstreamPacket(closePacket); session.setLastWindowCloseTime(System.currentTimeMillis()); } + */ } public static void updateCursor(GeyserSession session) { InventorySlotPacket cursorPacket = new InventorySlotPacket(); - cursorPacket.setContainerId(ContainerId.CURSOR); + cursorPacket.setContainerId(ContainerId.UI); //TODO: CHECK IF ACCURATE cursorPacket.setSlot(0); cursorPacket.setItem(ItemTranslator.translateToBedrock(session, session.getInventory().getCursor())); session.sendUpstreamPacket(cursorPacket); @@ -131,13 +137,14 @@ public class InventoryUtils { * part of the inventory is unusable. */ public static ItemData createUnusableSpaceBlock(String description) { - CompoundTagBuilder root = CompoundTagBuilder.builder(); - CompoundTagBuilder display = CompoundTagBuilder.builder(); + NbtMapBuilder root = NbtMap.builder(); + NbtMapBuilder display = NbtMap.builder(); - display.stringTag("Name", ChatColor.RESET + "Unusable inventory space"); - display.listTag("Lore", StringTag.class, Collections.singletonList(new StringTag("", ChatColor.RESET + ChatColor.DARK_PURPLE + description))); + // Not ideal to use log here but we dont get a session + display.putString("Name", ChatColor.RESET + LanguageUtils.getLocaleStringLog("geyser.inventory.unusable_item.name")); + display.putList("Lore", NbtType.STRING, Collections.singletonList(ChatColor.RESET + ChatColor.DARK_PURPLE + description)); - root.tag(display.build("display")); - return ItemData.of(ItemRegistry.ITEM_ENTRIES.get(ItemRegistry.BARRIER_INDEX).getBedrockId(), (short) 0, 1, root.buildRootTag()); + root.put("display", display.build()); + return ItemData.of(ItemRegistry.ITEM_ENTRIES.get(ItemRegistry.BARRIER_INDEX).getBedrockId(), (short) 0, 1, root.build()); } } diff --git a/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java b/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java index b9600222..bb3cf0ed 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/ItemUtils.java @@ -26,12 +26,6 @@ package org.geysermc.connector.utils; import com.github.steveice10.opennbt.tag.builtin.*; -import com.nukkitx.nbt.CompoundTagBuilder; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; public class ItemUtils { diff --git a/connector/src/main/java/org/geysermc/connector/utils/LanguageUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LanguageUtils.java new file mode 100644 index 00000000..9dabc387 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/LanguageUtils.java @@ -0,0 +1,208 @@ +/* + * 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 org.geysermc.connector.GeyserConnector; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; + +public class LanguageUtils { + + /** + * If we determine the locale that the user wishes to use, use that locale + */ + private static String CACHED_LOCALE; + + private static final Map LOCALE_MAPPINGS = new HashMap<>(); + + static { + // Load it as a backup in case something goes really wrong + if (!"en_US".equals(formatLocale(getDefaultLocale()))) { // getDefaultLocale() loads the locale automatically + loadGeyserLocale("en_US"); + } + } + + /** + * Loads a Geyser locale from resources, if the file doesn't exist it just logs a warning + * + * @param locale Locale to load + */ + public static void loadGeyserLocale(String locale) { + locale = formatLocale(locale); + + InputStream localeStream = GeyserConnector.class.getClassLoader().getResourceAsStream("languages/texts/" + locale + ".properties"); + + // Load the locale + if (localeStream != null) { + Properties localeProp = new Properties(); + try { + localeProp.load(new InputStreamReader(localeStream, StandardCharsets.UTF_8)); + } catch (Exception e) { + throw new AssertionError(getLocaleStringLog("geyser.language.load_failed", locale), e); + } + + // Insert the locale into the mappings + LOCALE_MAPPINGS.put(locale, localeProp); + } else { + if (GeyserConnector.getInstance() != null && GeyserConnector.getInstance().getLogger() != null) { + GeyserConnector.getInstance().getLogger().warning("Missing locale: " + locale); + } + } + } + + /** + * Get a formatted language string with the default locale for Geyser + * + * @param key Language string to translate + * @param values Values to put into the string + * @return Translated string or the original message if it was not found in the given locale + */ + public static String getLocaleStringLog(String key, Object... values) { + return getPlayerLocaleString(key, getDefaultLocale(), values); + } + + /** + * Get a formatted language string with the given locale for Geyser + * + * @param key Language string to translate + * @param locale Locale to translate to + * @param values Values to put into the string + * @return Translated string or the original message if it was not found in the given locale + */ + public static String getPlayerLocaleString(String key, String locale, Object... values) { + locale = formatLocale(locale); + + Properties properties = LOCALE_MAPPINGS.get(locale); + String formatString = properties.getProperty(key); + + // Try and get the key from the default locale + if (formatString == null) { + properties = LOCALE_MAPPINGS.get(formatLocale(getDefaultLocale())); + formatString = properties.getProperty(key); + } + + // Try and get the key from en_US (this should only ever happen in development) + if (formatString == null) { + properties = LOCALE_MAPPINGS.get("en_US"); + formatString = properties.getProperty(key); + } + + // Final fallback + if (formatString == null) { + formatString = key; + } + + return MessageFormat.format(formatString.replace("&", "\u00a7"), values); + } + + /** + * Cleans up and formats a locale string + * + * @param locale The locale to format + * @return The formatted locale + */ + private static String formatLocale(String locale) { + try { + String[] parts = locale.toLowerCase().split("_"); + String newLocale = parts[0] + "_" + parts[1].toUpperCase(); + switch (newLocale) { // Fallback to the closest language if we don't support it but Bedrock does. + case "es_MX": + return "es_ES"; + case "pt_BR": + return "pt_PT"; + case "fr_CA": + return "fr_FR"; + default: + return newLocale; + } + } catch (Exception e) { + return locale; + } + } + + /** + * Get the default locale that Geyser should use + * @return the current default locale + */ + public static String getDefaultLocale() { + if (CACHED_LOCALE != null) return CACHED_LOCALE; // We definitely know the locale the user is using + String locale; + boolean isValid = true; + if (GeyserConnector.getInstance() != null && + GeyserConnector.getInstance().getConfig() != null && + GeyserConnector.getInstance().getConfig().getDefaultLocale() != null) { // If the config option for getDefaultLocale does not equal null, use that + locale = formatLocale(GeyserConnector.getInstance().getConfig().getDefaultLocale()); + if (isValidLanguage(locale)) { + CACHED_LOCALE = locale; + return locale; + } else { + isValid = false; + } + } + locale = formatLocale(Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry()); + if (!isValidLanguage(locale)) { // Bedrock does not support this language + locale = "en_US"; + loadGeyserLocale(locale); + } + if (GeyserConnector.getInstance() != null && + GeyserConnector.getInstance().getConfig() != null && (GeyserConnector.getInstance().getConfig().getDefaultLocale() == null || !isValid)) { // Means we should use the system locale for sure + CACHED_LOCALE = locale; + } + return locale; + } + + /** + * Ensures that the given locale is supported by Bedrock + * @param locale the locale to validate + * @return true if the given locale is supported by Bedrock and by extension Geyser + */ + private static boolean isValidLanguage(String locale) { + boolean result = true; + if (FileUtils.class.getResource("/languages/texts/" + locale + ".properties") == null) { + result = false; + if (GeyserConnector.getInstance() != null && GeyserConnector.getInstance().getLogger() != null) { // Could be too early for these to be initialized + GeyserConnector.getInstance().getLogger().warning(locale + " is not a valid Bedrock language."); // We can't translate this since we just loaded an invalid language + } + } else { + if (!LOCALE_MAPPINGS.containsKey(locale)) { + loadGeyserLocale(locale); + } + } + return result; + } + + public static void init() { + // no-op + } +} diff --git a/connector/src/main/java/org/geysermc/connector/utils/LoadstoneTracker.java b/connector/src/main/java/org/geysermc/connector/utils/LoadstoneTracker.java new file mode 100644 index 00000000..3bd54765 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/LoadstoneTracker.java @@ -0,0 +1,84 @@ +/* + * 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 it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +public class LoadstoneTracker { + + private static final Int2ObjectMap LOADSTONES = new Int2ObjectOpenHashMap<>(); + + /** + * Store the given coordinates and dimensions + * + * @param x The X position of the Loadstone + * @param y The Y position of the Loadstone + * @param z The Z position of the Loadstone + * @param dim The dimension containing of the Loadstone + * @return The id in the Map + */ + public static int store(int x, int y, int z, String dim) { + LoadstonePos pos = new LoadstonePos(x, y, z, dim); + + if (!LOADSTONES.containsValue(pos)) { + // Start at 1 as 0 seems to not work + LOADSTONES.put(LOADSTONES.size() + 1, pos); + } + + for (Int2ObjectMap.Entry loadstone : LOADSTONES.int2ObjectEntrySet()) { + if (loadstone.getValue().equals(pos)) { + return loadstone.getIntKey(); + } + } + + return 0; + } + + /** + * Get the loadstone data + * + * @param id The ID to get the data for + * @return The stored data + */ + public static LoadstonePos getPos(int id) { + return LOADSTONES.get(id); + } + + @Getter + @AllArgsConstructor + @EqualsAndHashCode + public static class LoadstonePos { + int x; + int y; + int z; + String dimension; + } +} \ No newline at end of file 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 78752591..285846a9 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java @@ -48,8 +48,6 @@ public class LocaleUtils { private static final Map ASSET_MAP = new HashMap<>(); - private static final String DEFAULT_LOCALE = (GeyserConnector.getInstance().getConfig().getDefaultLocale() != null ? GeyserConnector.getInstance().getConfig().getDefaultLocale() : "en_us"); - private static String smallestURL = ""; static { @@ -60,7 +58,7 @@ public class LocaleUtils { // Download the latest asset list and cache it generateAssetCache(); - downloadAndLoadLocale(DEFAULT_LOCALE); + downloadAndLoadLocale(LanguageUtils.getDefaultLocale()); } /** @@ -82,7 +80,7 @@ public class LocaleUtils { // Make sure we definitely got a version if (latestInfoURL.isEmpty()) { - throw new Exception("Unable to get latest Minecraft version"); + throw new Exception(LanguageUtils.getLocaleStringLog("geyser.locale.fail.latest_version")); } // Get the individual version manifest @@ -105,7 +103,7 @@ public class LocaleUtils { ASSET_MAP.put(entry.getKey(), asset); } } catch (Exception e) { - GeyserConnector.getInstance().getLogger().info("Failed to load locale asset cache: " + (!e.getMessage().isEmpty() ? e.getMessage() : e.getStackTrace())); + GeyserConnector.getInstance().getLogger().info(LanguageUtils.getLocaleStringLog("geyser.locale.fail.asset_cache", (!e.getMessage().isEmpty() ? e.getMessage() : e.getStackTrace()))); } } @@ -119,7 +117,7 @@ public class LocaleUtils { // Check the locale isn't already loaded if (!ASSET_MAP.containsKey("minecraft/lang/" + locale + ".json") && !locale.equals("en_us")) { - GeyserConnector.getInstance().getLogger().warning("Invalid locale requested to download and load: " + locale); + GeyserConnector.getInstance().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.locale.fail.invalid", locale)); return; } @@ -170,7 +168,7 @@ public class LocaleUtils { try { localeStream = new FileInputStream(localeFile); } catch (FileNotFoundException e) { - throw new AssertionError("Unable to load locale: " + locale + " (" + e.getMessage() + ")"); + throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.locale.fail.file", locale, e.getMessage())); } // Parse the file as json @@ -178,7 +176,7 @@ public class LocaleUtils { try { localeObj = GeyserConnector.JSON_MAPPER.readTree(localeStream); } catch (Exception e) { - throw new AssertionError("Unable to load Java edition lang map for " + locale, e); + throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.locale.fail.json", locale), e); } // Parse all the locale fields @@ -192,7 +190,7 @@ public class LocaleUtils { // Insert the locale into the mappings LOCALE_MAPPINGS.put(locale.toLowerCase(), langMap); } else { - GeyserConnector.getInstance().getLogger().warning("Missing locale file: " + locale); + GeyserConnector.getInstance().getLogger().warning(LanguageUtils.getLocaleStringLog("geyser.locale.fail.missing", locale)); } } @@ -204,7 +202,7 @@ public class LocaleUtils { private static void downloadEN_US(File localeFile) { try { // Let the user know we are downloading the JAR - GeyserConnector.getInstance().getLogger().info("Downloading Minecraft JAR to extract en_us locale, please wait... (this may take some time depending on the speed of your internet connection)"); + GeyserConnector.getInstance().getLogger().info(LanguageUtils.getLocaleStringLog("geyser.locale.download.en_us")); GeyserConnector.getInstance().getLogger().debug("Download URL: " + smallestURL); // Download the smallest JAR (client or server) @@ -233,7 +231,7 @@ public class LocaleUtils { // Delete the nolonger needed client/server jar Files.delete(tmpFilePath); } catch (Exception e) { - throw new AssertionError("Unable to download and extract en_us locale!", e); + throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.locale.fail.en_us"), e); } } @@ -247,7 +245,7 @@ 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(DEFAULT_LOCALE); + localeStrings = LocaleUtils.LOCALE_MAPPINGS.get(LanguageUtils.getDefaultLocale()); return localeStrings.getOrDefault(messageText, messageText); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java index f9a7fec2..3d4dd506 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/LoginEncryptionUtils.java @@ -156,18 +156,20 @@ public class LoginEncryptionUtils { private static int AUTH_DETAILS_FORM_ID = 1337; public static void showLoginWindow(GeyserSession session) { - SimpleFormWindow window = new SimpleFormWindow("Login", "You need a Java Edition account to play on this server."); - window.getButtons().add(new FormButton("Login with Minecraft")); - window.getButtons().add(new FormButton("Disconnect")); + String userLanguage = session.getClientData().getLanguageCode(); + SimpleFormWindow window = new SimpleFormWindow(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.notice.title", userLanguage), LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.notice.desc", userLanguage)); + window.getButtons().add(new FormButton(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.notice.btn_login", userLanguage))); + window.getButtons().add(new FormButton(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.notice.btn_disconnect", userLanguage))); session.sendForm(window, AUTH_FORM_ID); } public static void showLoginDetailsWindow(GeyserSession session) { - CustomFormWindow window = new CustomFormBuilder("Login Details") - .addComponent(new LabelComponent("Enter the credentials for your Minecraft: Java Edition account below.")) - .addComponent(new InputComponent("Email/Username", "account@geysermc.org", "")) - .addComponent(new InputComponent("Password", "123456", "")) + String userLanguage = session.getClientData().getLanguageCode(); + CustomFormWindow window = new CustomFormBuilder(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.details.title", userLanguage)) + .addComponent(new LabelComponent(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.details.desc", userLanguage))) + .addComponent(new InputComponent(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.details.email", userLanguage), "account@geysermc.org", "")) + .addComponent(new InputComponent(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.details.pass", userLanguage), "123456", "")) .build(); session.sendForm(window, AUTH_DETAILS_FORM_ID); @@ -203,8 +205,8 @@ public class LoginEncryptionUtils { if (response != null) { if (response.getClickedButtonId() == 0) { showLoginDetailsWindow(session); - } else if (response.getClickedButtonId() == 1) { - session.disconnect("Login is required"); + } else if(response.getClickedButtonId() == 1) { + session.disconnect(LanguageUtils.getPlayerLocaleString("geyser.auth.login.form.disconnect", session.getClientData().getLanguageCode())); } } else { showLoginWindow(session); diff --git a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java index d79cdab8..bf196224 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/MessageUtils.java @@ -26,50 +26,121 @@ package org.geysermc.connector.utils; import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor; -import com.github.steveice10.mc.protocol.data.message.*; -import com.google.gson.*; -import net.kyori.text.Component; -import net.kyori.text.serializer.gson.GsonComponentSerializer; -import net.kyori.text.serializer.legacy.LegacyComponentSerializer; +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.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class MessageUtils { - public static List getTranslationParams(Message[] messages, String locale) { + 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 + */ + 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.getTranslationKey(); + String builder = "%" + translation.getKey(); strings.add(builder); } - if (translation.getTranslationKey().equals("commands.gamemode.success.other")) { + if (translation.getKey().equals("commands.gamemode.success.other")) { strings.add(""); } - if (translation.getTranslationKey().equals("command.context.here")) { + if (translation.getKey().equals("command.context.here")) { strings.add(" - no permission or invalid command!"); } - List furtherParams = getTranslationParams(translation.getTranslationParams(), locale); + // 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) { - strings.add(insertParams(LocaleUtils.getLocaleString(translation.getTranslationKey(), locale), furtherParams)); + strings.add(insertParams(LocaleUtils.getLocaleString(translation.getKey(), locale), furtherParams)); } else { strings.addAll(furtherParams); } } else { String builder = getFormat(message.getStyle().getFormats()) + - getColorOrParent(message.getStyle()); - builder += getTranslatedBedrockMessage(message, locale, false); + getColor(message.getStyle().getColor()); + builder += getTranslatedBedrockMessage(message, locale, false, parent); strings.add(builder); } } @@ -77,44 +148,54 @@ public class MessageUtils { return strings; } - public static List getTranslationParams(Message[] messages) { - return getTranslationParams(messages, null); - } - - public static String getTranslationText(TranslationMessage message) { - return getFormat(message.getStyle().getFormats()) + getColorOrParent(message.getStyle()) - + "%" + message.getTranslationKey(); + 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 + * @param shouldTranslate + * @param parent + * @return + */ + public static String getTranslatedBedrockMessage(Message message, String locale, boolean shouldTranslate, Message parent) { JsonParser parser = new JsonParser(); - if (isMessage(message.getText())) { - JsonObject object = parser.parse(message.getText()).getAsJsonObject(); - message = Message.fromJson(formatJson(object)); + if (isMessage(message.toString())) { + JsonObject object = parser.parse(message.toString()).getAsJsonObject(); + message = MessageSerializer.fromJson(object); } - String messageText = message.getText(); + 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(getColorOrParent(message.getStyle())); + builder.append(getColor(message.getStyle().getColor())); builder.append(messageText); for (Message msg : message.getExtra()) { builder.append(getFormat(msg.getStyle().getFormats())); - builder.append(getColorOrParent(msg.getStyle())); - if (!(msg.getText() == null)) { + builder.append(getColor(msg.getStyle().getColor())); + if (!(msg.toString() == null)) { boolean isTranslationMessage = (msg instanceof TranslationMessage); String extraText = ""; if (isTranslationMessage) { - List paramsTranslated = getTranslationParams(((TranslationMessage) msg).getTranslationParams(), locale); - extraText = insertParams(getTranslatedBedrockMessage(msg, locale, isTranslationMessage), paramsTranslated); + List paramsTranslated = getTranslationParams(((TranslationMessage) msg).getWith(), locale, message); + extraText = insertParams(getTranslatedBedrockMessage(msg, locale, isTranslationMessage, message), paramsTranslated); } else { - extraText = getTranslatedBedrockMessage(msg, locale, isTranslationMessage); + extraText = getTranslatedBedrockMessage(msg, locale, isTranslationMessage, message); } builder.append(extraText); @@ -125,15 +206,37 @@ public class MessageUtils { return builder.toString(); } - public static String getTranslatedBedrockMessage(Message message, String locale) { - return getTranslatedBedrockMessage(message, locale, true); + /** + * 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(message.getText())) { - return getBedrockMessage(message.getText()); + if (isMessage(((TextMessage) message).getText())) { + return getBedrockMessage(((TextMessage) message).getText()); } else { - return getBedrockMessage(message.toJsonString()); + return getBedrockMessage(MessageSerializer.toJsonString(message)); } } @@ -160,12 +263,12 @@ public class MessageUtils { } public static Component phraseJavaMessage(String message) { - return GsonComponentSerializer.INSTANCE.deserialize(message); + return GsonComponentSerializer.gson().deserialize(message); } public static String getJavaMessage(String message) { Component component = LegacyComponentSerializer.legacy().deserialize(message); - return GsonComponentSerializer.INSTANCE.serialize(component); + return GsonComponentSerializer.gson().serialize(component); } /** @@ -197,90 +300,118 @@ public class MessageUtils { return newMessage; } - /** - * Gets the colour for the message style or fetches it from the parent (recursive) - * - * @param style The style to get the colour from - * @return Colour string to be used - */ - private static String getColorOrParent(MessageStyle style) { - ChatColor chatColor = style.getColor(); - - if (chatColor == ChatColor.NONE && style.getParent() != null) { - return getColorOrParent(style.getParent()); - } - - return getColor(chatColor); - } - /** * Convert a ChatColor into a string for inserting into messages * * @param color ChatColor to convert * @return The converted color string */ - private static String getColor(ChatColor color) { + private static String getColor(String color) { String base = "\u00a7"; switch (color) { - case BLACK: + case ChatColor.BLACK: base += "0"; break; - case DARK_BLUE: + case ChatColor.DARK_BLUE: base += "1"; break; - case DARK_GREEN: + case ChatColor.DARK_GREEN: base += "2"; break; - case DARK_AQUA: + case ChatColor.DARK_AQUA: base += "3"; break; - case DARK_RED: + case ChatColor.DARK_RED: base += "4"; break; - case DARK_PURPLE: + case ChatColor.DARK_PURPLE: base += "5"; break; - case GOLD: + case ChatColor.GOLD: base += "6"; break; - case GRAY: + case ChatColor.GRAY: base += "7"; break; - case DARK_GRAY: + case ChatColor.DARK_GRAY: base += "8"; break; - case BLUE: + case ChatColor.BLUE: base += "9"; break; - case GREEN: + case ChatColor.GREEN: base += "a"; break; - case AQUA: + case ChatColor.AQUA: base += "b"; break; - case RED: + case ChatColor.RED: base += "c"; break; - case LIGHT_PURPLE: + case ChatColor.LIGHT_PURPLE: base += "d"; break; - case YELLOW: + case ChatColor.YELLOW: base += "e"; break; - case WHITE: + case ChatColor.WHITE: base += "f"; break; - case RESET: - case NONE: + case ChatColor.RESET: + //case NONE: base += "r"; break; - default: + 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) { + return testColor.getKey(); + } + + 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 rDiff = Math.abs(testR - r); + int gDiff = Math.abs(testG - g); + int bDiff = Math.abs(testB - b); + int maxDiff = Math.max(Math.max(rDiff, gDiff), bDiff); + if (closest == null || maxDiff < smallestDiff) { + closest = testColor.getKey(); + smallestDiff = maxDiff; + } + } + + return getColor(closest); + } + /** * Convert a list of ChatFormats into a string for inserting into messages * @@ -328,7 +459,7 @@ public class MessageUtils { try { JsonObject object = parser.parse(text).getAsJsonObject(); try { - Message.fromJson(formatJson(object)); + MessageSerializer.fromJson(object); } catch (Exception ex) { return false; } @@ -338,42 +469,8 @@ public class MessageUtils { return true; } - public static JsonObject formatJson(JsonObject object) { - if (object.has("hoverEvent")) { - JsonObject sub = (JsonObject) object.get("hoverEvent"); - JsonElement element = sub.get("value"); - - if (element instanceof JsonArray) { - JsonObject newobj = new JsonObject(); - newobj.add("extra", element); - newobj.addProperty("text", ""); - sub.remove("value"); - sub.add("value", newobj); - } - } - - if (object.has("extra")) { - JsonArray a = object.getAsJsonArray("extra"); - for (int i = 0; i < a.size(); i++) { - if (!(a.get(i) instanceof JsonPrimitive)) - formatJson((JsonObject) a.get(i)); - } - } - return object; - } - public static String toChatColor(TeamColor teamColor) { - for (ChatColor color : ChatColor.values()) { - if (color.name().equals(teamColor.name())) { - return getColor(color); - } - } - for (ChatFormat format : ChatFormat.values()) { - if (format.name().equals(teamColor.name())) { - return getFormat(Collections.singletonList(format)); - } - } - return ""; + return TEAM_COLORS.getOrDefault(teamColor, ""); } /** 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 aea9ba18..aa01ada8 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinProvider.java @@ -537,7 +537,7 @@ public class SkinProvider { OPTIFINE("http://s.optifine.net/capes/%s.png", CapeUrlType.USERNAME), LABYMOD("https://www.labymod.net/page/php/getCapeTexture.php?uuid=%s", CapeUrlType.UUID_DASHED), FIVEZIG("https://textures.5zigreborn.eu/profile/%s", CapeUrlType.UUID_DASHED), - MINECRAFTCAPES("https://www.minecraftcapes.co.uk/getCape/%s", CapeUrlType.UUID); + MINECRAFTCAPES("https://minecraftcapes.net/profile/%s/cape", CapeUrlType.UUID); public static final CapeProvider[] VALUES = Arrays.copyOfRange(values(), 1, 5); private String url; @@ -573,7 +573,7 @@ public class SkinProvider { @NoArgsConstructor @Getter public enum EarsProvider { - MINECRAFTCAPES("https://www.minecraftcapes.co.uk/getEars/%s", CapeUrlType.UUID); + MINECRAFTCAPES("https://minecraftcapes.net/profile/%s/ears", CapeUrlType.UUID); public static final EarsProvider[] VALUES = values(); private String url; diff --git a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java index 48e4c4c8..22588576 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/SkinUtils.java @@ -28,14 +28,12 @@ package org.geysermc.connector.utils; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.steveice10.mc.auth.data.GameProfile; -import com.nukkitx.protocol.bedrock.data.ImageData; -import com.nukkitx.protocol.bedrock.data.SerializedSkin; +import com.nukkitx.protocol.bedrock.data.skin.ImageData; +import com.nukkitx.protocol.bedrock.data.skin.SerializedSkin; import com.nukkitx.protocol.bedrock.packet.PlayerListPacket; - import lombok.AllArgsConstructor; import lombok.Getter; - -import org.geysermc.common.AuthType; +import org.geysermc.connector.common.AuthType; import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.network.session.GeyserSession; @@ -98,6 +96,7 @@ public class SkinUtils { entry.setXuid(""); entry.setPlatformChatId(""); entry.setTeacher(false); + entry.setTrustedSkin(true); return entry; } @@ -247,7 +246,7 @@ public class SkinUtils { } } } catch (Exception e) { - GeyserConnector.getInstance().getLogger().error("Failed getting skin for " + entity.getUuid(), e); + GeyserConnector.getInstance().getLogger().error(LanguageUtils.getLocaleStringLog("geyser.skin.fail", entity.getUuid()), e); } if (skinAndCapeConsumer != null) skinAndCapeConsumer.accept(skinAndCape); @@ -258,7 +257,7 @@ public class SkinUtils { public static void handleBedrockSkin(PlayerEntity playerEntity, BedrockClientData clientData) { GameProfileData data = GameProfileData.from(playerEntity.getProfile()); - GeyserConnector.getInstance().getLogger().info("Registering bedrock skin for " + playerEntity.getUsername() + " (" + playerEntity.getUuid() + ")"); + GeyserConnector.getInstance().getLogger().info(LanguageUtils.getLocaleStringLog("geyser.skin.bedrock.register", playerEntity.getUsername(), playerEntity.getUuid())); try { byte[] skinBytes = com.github.steveice10.mc.auth.util.Base64.decode(clientData.getSkinData().getBytes("UTF-8")); @@ -271,7 +270,7 @@ public class SkinUtils { SkinProvider.storeBedrockSkin(playerEntity.getUuid(), data.getSkinUrl(), skinBytes); SkinProvider.storeBedrockGeometry(playerEntity.getUuid(), geometryNameBytes, geometryBytes); } else { - GeyserConnector.getInstance().getLogger().info("Unable to load bedrock skin for '" + playerEntity.getUsername() + "' as they are likely using a customised skin"); + GeyserConnector.getInstance().getLogger().info(LanguageUtils.getLocaleStringLog("geyser.skin.bedrock.fail", playerEntity.getUsername())); GeyserConnector.getInstance().getLogger().debug("The size of '" + playerEntity.getUsername() + "' skin is: " + clientData.getSkinImageWidth() + "x" + clientData.getSkinImageHeight()); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java b/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java index 50ab76d0..7a1a0215 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java @@ -25,11 +25,10 @@ package org.geysermc.connector.utils; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.*; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; @@ -81,4 +80,31 @@ public class WebUtils { throw new AssertionError("Unable to download and save file: " + fileLocation + " (" + reqURL + ")", e); } } + + public static String post(String reqURL, String postContent) throws IOException { + URL url = null; + url = new URL(reqURL); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("POST"); + con.setRequestProperty("Content-Type", "text/plain"); + con.setDoOutput(true); + + OutputStream out = con.getOutputStream(); + out.write(postContent.getBytes(StandardCharsets.UTF_8)); + out.close(); + + BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuffer content = new StringBuffer(); + + while ((inputLine = in.readLine()) != null) { + content.append(inputLine); + content.append("\n"); + } + + in.close(); + con.disconnect(); + + return content.toString(); + } } diff --git a/connector/src/main/resources/bedrock/biome_definitions.dat b/connector/src/main/resources/bedrock/biome_definitions.dat index b8c6df4a..6d72cc92 100644 Binary files a/connector/src/main/resources/bedrock/biome_definitions.dat and b/connector/src/main/resources/bedrock/biome_definitions.dat differ diff --git a/connector/src/main/resources/bedrock/creative_items.json b/connector/src/main/resources/bedrock/creative_items.json index 8045b219..eea92a95 100644 --- a/connector/src/main/resources/bedrock/creative_items.json +++ b/connector/src/main/resources/bedrock/creative_items.json @@ -23,6 +23,12 @@ "id" : 5, "damage" : 5 }, + { + "id" : -242 + }, + { + "id" : -243 + }, { "id" : 139 }, @@ -78,6 +84,15 @@ "id" : 139, "damage" : 11 }, + { + "id" : -277 + }, + { + "id" : -297 + }, + { + "id" : -278 + }, { "id" : 85 }, @@ -104,6 +119,12 @@ { "id" : 113 }, + { + "id" : -256 + }, + { + "id" : -257 + }, { "id" : 107 }, @@ -122,6 +143,12 @@ { "id" : 186 }, + { + "id" : -258 + }, + { + "id" : -259 + }, { "id" : -180 }, @@ -215,6 +242,21 @@ { "id" : -4 }, + { + "id" : -254 + }, + { + "id" : -255 + }, + { + "id" : -276 + }, + { + "id" : -292 + }, + { + "id" : -275 + }, { "id" : 324 }, @@ -236,6 +278,12 @@ { "id" : 330 }, + { + "id" : 755 + }, + { + "id" : 756 + }, { "id" : 96 }, @@ -257,9 +305,18 @@ { "id" : 167 }, + { + "id" : -246 + }, + { + "id" : -247 + }, { "id" : 101 }, + { + "id" : 758 + }, { "id" : 20 }, @@ -529,9 +586,33 @@ "id" : 182, "damage" : 4 }, + { + "id" : -264 + }, + { + "id" : -265 + }, + { + "id" : -282 + }, + { + "id" : -293 + }, + { + "id" : -284 + }, { "id" : 45 }, + { + "id" : -302 + }, + { + "id" : -303 + }, + { + "id" : -304 + }, { "id" : 98 }, @@ -554,6 +635,18 @@ "id" : 168, "damage" : 2 }, + { + "id" : -274 + }, + { + "id" : -280 + }, + { + "id" : -281 + }, + { + "id" : -279 + }, { "id" : 4 }, @@ -648,18 +741,72 @@ { "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 + }, + { + "id" : -222 + }, { "id" : 35 }, @@ -1082,6 +1229,12 @@ { "id" : 153 }, + { + "id" : -288 + }, + { + "id" : -271 + }, { "id" : 13 }, @@ -1097,6 +1250,9 @@ "id" : 1, "damage" : 5 }, + { + "id" : -273 + }, { "id" : 1, "damage" : 2 @@ -1109,6 +1265,9 @@ "id" : 1, "damage" : 6 }, + { + "id" : -291 + }, { "id" : 12 }, @@ -1252,7 +1411,8 @@ "damage" : 5 }, { - "id" : -218 + "id" : -218, + "damage" : 3 }, { "id" : 295 @@ -1333,6 +1493,9 @@ "id" : 175, "damage" : 2 }, + { + "id" : 760 + }, { "id" : -131, "damage" : 3 @@ -1416,6 +1579,12 @@ { "id" : -130 }, + { + "id" : -223 + }, + { + "id" : -224 + }, { "id" : 37 }, @@ -1562,6 +1731,12 @@ { "id" : 106 }, + { + "id" : -231 + }, + { + "id" : -287 + }, { "id" : 111 }, @@ -1619,6 +1794,12 @@ { "id" : 40 }, + { + "id" : -228 + }, + { + "id" : -229 + }, { "id" : 99, "damage" : 14 @@ -1871,6 +2052,22 @@ "id" : 383, "damage" : 42 }, + { + "id" : 383, + "damage" : 125 + }, + { + "id" : 383, + "damage" : 124 + }, + { + "id" : 383, + "damage" : 123 + }, + { + "id" : 383, + "damage" : 126 + }, { "id" : 383, "damage" : 41 @@ -1922,6 +2119,9 @@ { "id" : 49 }, + { + "id" : -289 + }, { "id" : 7 }, @@ -2013,6 +2213,9 @@ { "id" : 310 }, + { + "id" : 748 + }, { "id" : 299 }, @@ -2028,6 +2231,9 @@ { "id" : 311 }, + { + "id" : 749 + }, { "id" : 300 }, @@ -2043,6 +2249,9 @@ { "id" : 312 }, + { + "id" : 750 + }, { "id" : 301 }, @@ -2058,6 +2267,9 @@ { "id" : 313 }, + { + "id" : 751 + }, { "id" : 268 }, @@ -2073,6 +2285,9 @@ { "id" : 276 }, + { + "id" : 743 + }, { "id" : 271 }, @@ -2088,6 +2303,9 @@ { "id" : 279 }, + { + "id" : 746 + }, { "id" : 270 }, @@ -2103,6 +2321,9 @@ { "id" : 278 }, + { + "id" : 745 + }, { "id" : 269 }, @@ -2118,6 +2339,9 @@ { "id" : 277 }, + { + "id" : 744 + }, { "id" : 290 }, @@ -2133,6 +2357,9 @@ { "id" : 293 }, + { + "id" : 747 + }, { "id" : 261 }, @@ -2290,6 +2517,10 @@ "id" : 262, "damage" : 42 }, + { + "id" : 262, + "damage" : 43 + }, { "id" : 513 }, @@ -2347,6 +2578,9 @@ { "id" : 398 }, + { + "id" : 757 + }, { "id" : 332 }, @@ -2572,6 +2806,10 @@ "id" : 373, "damage" : 41 }, + { + "id" : 373, + "damage" : 42 + }, { "id" : 438 }, @@ -2739,6 +2977,10 @@ "id" : 438, "damage" : 41 }, + { + "id" : 438, + "damage" : 42 + }, { "id" : 441 }, @@ -2906,6 +3148,10 @@ "id" : 441, "damage" : 41 }, + { + "id" : 441, + "damage" : 42 + }, { "id" : 280 }, @@ -2975,12 +3221,18 @@ { "id" : 50 }, + { + "id" : -268 + }, { "id" : -156 }, { "id" : -208 }, + { + "id" : -269 + }, { "id" : 58 }, @@ -2994,11 +3246,15 @@ "id" : -202 }, { - "id" : -219 + "id" : -219, + "damage" : 3 }, { "id" : 720 }, + { + "id" : 801 + }, { "id" : 61 }, @@ -3008,6 +3264,9 @@ { "id" : -198 }, + { + "id" : -272 + }, { "id" : 379 }, @@ -3163,6 +3422,9 @@ { "id" : 511 }, + { + "id" : 759 + }, { "id" : 348 }, @@ -3193,6 +3455,12 @@ { "id" : 476 }, + { + "id" : 753 + }, + { + "id" : 754 + }, { "id" : 321 }, @@ -3293,6 +3561,12 @@ { "id" : 265 }, + { + "id" : 752 + }, + { + "id" : 742 + }, { "id" : 371 }, @@ -3732,6 +4006,14 @@ "id" : 403, "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBoAAAA=" }, + { + "id" : 403, + "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBsAAAA=" + }, + { + "id" : 403, + "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZBwAAAA=" + }, { "id" : 403, "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZB0AAAA=" @@ -3812,6 +4094,18 @@ "id" : 403, "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZCMAAAA=" }, + { + "id" : 403, + "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAQACAgBpZCQAAAA=" + }, + { + "id" : 403, + "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAgACAgBpZCQAAAA=" + }, + { + "id" : 403, + "nbt_b64" : "CgAACQQAZW5jaAoBAAAAAgMAbHZsAwACAgBpZCQAAAA=" + }, { "id" : 333 }, @@ -3892,6 +4186,15 @@ { "id" : 77 }, + { + "id" : -260 + }, + { + "id" : -261 + }, + { + "id" : -296 + }, { "id" : 131 }, @@ -3913,6 +4216,12 @@ { "id" : -152 }, + { + "id" : -262 + }, + { + "id" : -263 + }, { "id" : 70 }, @@ -3922,6 +4231,9 @@ { "id" : 148 }, + { + "id" : -295 + }, { "id" : 251 }, @@ -4053,6 +4365,10 @@ "id" : 434, "damage" : 5 }, + { + "id" : 434, + "damage" : 6 + }, { "id" : 401, "nbt_b64" : "CgAACgkARmlyZXdvcmtzAQYARmxpZ2h0AQkKAEV4cGxvc2lvbnMAAAAAAAAA" diff --git a/connector/src/main/resources/bedrock/entity_identifiers.dat b/connector/src/main/resources/bedrock/entity_identifiers.dat index cb8f0481..c9477ba8 100644 Binary files a/connector/src/main/resources/bedrock/entity_identifiers.dat and b/connector/src/main/resources/bedrock/entity_identifiers.dat differ diff --git a/connector/src/main/resources/bedrock/items.json b/connector/src/main/resources/bedrock/items.json index 87f85187..0614b364 100644 --- a/connector/src/main/resources/bedrock/items.json +++ b/connector/src/main/resources/bedrock/items.json @@ -1,2810 +1,3230 @@ [ - { - "name" : "minecraft:item.reeds", - "id" : 83 - }, - { - "name" : "minecraft:air", - "id" : -158 - }, - { - "name" : "minecraft:item.birch_door", - "id" : 194 - }, - { - "name" : "minecraft:apple", - "id" : 260 - }, - { - "name" : "minecraft:cooked_porkchop", - "id" : 320 - }, - { - "name" : "minecraft:beacon", - "id" : 138 - }, - { - "name" : "minecraft:stone_stairs", - "id" : 67 - }, - { - "name" : "minecraft:appleenchanted", - "id" : 466 - }, - { - "name" : "minecraft:tripwire", - "id" : 132 - }, - { - "name" : "minecraft:leather_leggings", - "id" : 300 - }, - { - "name" : "minecraft:bread", - "id" : 297 - }, - { - "name" : "minecraft:light_block", - "id" : -215 - }, - { - "name" : "minecraft:porkchop", - "id" : 319 - }, - { - "name" : "minecraft:spruce_fence_gate", - "id" : 183 - }, - { - "name" : "minecraft:fish", - "id" : 349 - }, - { - "name" : "minecraft:element_52", - "id" : -63 - }, - { - "name" : "minecraft:diamond_sword", - "id" : 276 - }, - { - "name" : "minecraft:element_38", - "id" : -49 - }, - { - "name" : "minecraft:sandstone_stairs", - "id" : 128 - }, - { - "name" : "minecraft:acacia_sign", - "id" : 475 - }, - { - "name" : "minecraft:rabbit_stew", - "id" : 413 - }, - { - "name" : "minecraft:birch_sign", - "id" : 473 - }, - { - "name" : "minecraft:horsearmorgold", - "id" : 418 - }, - { - "name" : "minecraft:element_74", - "id" : -85 - }, - { - "name" : "minecraft:pufferfish", - "id" : 462 - }, - { - "name" : "minecraft:redstone_block", - "id" : 152 - }, - { - "name" : "minecraft:golden_apple", - "id" : 322 - }, - { - "name" : "minecraft:item.wooden_door", - "id" : 64 - }, - { - "name" : "minecraft:emerald", - "id" : 388 - }, - { - "name" : "minecraft:element_47", - "id" : -58 - }, - { - "name" : "minecraft:mushroom_stew", - "id" : 282 - }, - { - "name" : "minecraft:stone_axe", - "id" : 275 - }, - { - "name" : "minecraft:salmon", - "id" : 460 - }, - { - "name" : "minecraft:feather", - "id" : 288 - }, - { - "name" : "minecraft:clownfish", - "id" : 461 - }, - { - "name" : "minecraft:diamond", - "id" : 264 - }, - { - "name" : "minecraft:cooked_fish", - "id" : 350 - }, - { - "name" : "minecraft:element_32", - "id" : -43 - }, - { - "name" : "minecraft:double_stone_slab4", - "id" : -166 - }, - { - "name" : "minecraft:element_5", - "id" : -16 - }, - { - "name" : "minecraft:element_25", - "id" : -36 - }, - { - "name" : "minecraft:polished_granite_stairs", - "id" : -172 - }, - { - "name" : "minecraft:bowl", - "id" : 281 - }, - { - "name" : "minecraft:red_mushroom_block", - "id" : 100 - }, - { - "name" : "minecraft:mossy_stone_brick_stairs", - "id" : -175 - }, - { - "name" : "minecraft:cooked_salmon", - "id" : 463 - }, - { - "name" : "minecraft:element_87", - "id" : -98 - }, - { - "name" : "minecraft:pumpkin_seeds", - "id" : 361 - }, - { - "name" : "minecraft:element_53", - "id" : -64 - }, - { - "name" : "minecraft:dried_kelp", - "id" : 464 - }, - { - "name" : "minecraft:brewingstandblock", - "id" : 117 - }, - { - "name" : "minecraft:wooden_pickaxe", - "id" : 270 - }, - { - "name" : "minecraft:cookie", - "id" : 357 - }, - { - "name" : "minecraft:gold_ingot", - "id" : 266 - }, - { - "name" : "minecraft:sweet_berries", - "id" : 477 - }, - { - "name" : "minecraft:melon", - "id" : 360 - }, - { - "name" : "minecraft:iron_pickaxe", - "id" : 257 - }, - { - "name" : "minecraft:glow_stick", - "id" : 166 - }, - { - "name" : "minecraft:beef", - "id" : 363 - }, - { - "name" : "minecraft:stone_hoe", - "id" : 291 - }, - { - "name" : "minecraft:cooked_beef", - "id" : 364 - }, - { - "name" : "minecraft:lime_glazed_terracotta", - "id" : 225 - }, - { - "name" : "minecraft:chicken", - "id" : 365 - }, - { - "name" : "minecraft:element_31", - "id" : -42 - }, - { - "name" : "minecraft:cooked_chicken", - "id" : 366 - }, - { - "name" : "minecraft:rotten_flesh", - "id" : 367 - }, - { - "name" : "minecraft:darkoak_sign", - "id" : 476 - }, - { - "name" : "minecraft:stone_sword", - "id" : 272 - }, - { - "name" : "minecraft:spider_eye", - "id" : 375 - }, - { - "name" : "minecraft:diamond_axe", - "id" : 279 - }, - { - "name" : "minecraft:element_105", - "id" : -116 - }, - { - "name" : "minecraft:carrot", - "id" : 391 - }, - { - "name" : "minecraft:stripped_birch_log", - "id" : -6 - }, - { - "name" : "minecraft:potato", - "id" : 392 - }, - { - "name" : "minecraft:baked_potato", - "id" : 393 - }, - { - "name" : "minecraft:element_15", - "id" : -26 - }, - { - "name" : "minecraft:carpet", - "id" : 171 - }, - { - "name" : "minecraft:poisonous_potato", - "id" : 394 - }, - { - "name" : "minecraft:beetroot_seeds", - "id" : 458 - }, - { - "name" : "minecraft:noteblock", - "id" : 25 - }, - { - "name" : "minecraft:golden_carrot", - "id" : 396 - }, - { - "name" : "minecraft:pumpkin_pie", - "id" : 400 - }, - { - "name" : "minecraft:beetroot", - "id" : 457 - }, - { - "name" : "minecraft:coral_fan_dead", - "id" : -134 - }, - { - "name" : "minecraft:iron_ingot", - "id" : 265 - }, - { - "name" : "minecraft:beetroot_soup", - "id" : 459 - }, - { - "name" : "minecraft:rabbit", - "id" : 411 - }, - { - "name" : "minecraft:cooked_rabbit", - "id" : 412 - }, - { - "name" : "minecraft:iron_helmet", - "id" : 306 - }, - { - "name" : "minecraft:wheat_seeds", - "id" : 295 - }, - { - "name" : "minecraft:melon_seeds", - "id" : 362 - }, - { - "name" : "minecraft:nether_wart", - "id" : 372 - }, - { - "name" : "minecraft:record_strad", - "id" : 508 - }, - { - "name" : "minecraft:iron_sword", - "id" : 267 - }, - { - "name" : "minecraft:iron_shovel", - "id" : 256 - }, - { - "name" : "minecraft:stone_pickaxe", - "id" : 274 - }, - { - "name" : "minecraft:leather", - "id" : 334 - }, - { - "name" : "minecraft:command_block_minecart", - "id" : 443 - }, - { - "name" : "minecraft:stone_shovel", - "id" : 273 - }, - { - "name" : "minecraft:written_book", - "id" : 387 - }, - { - "name" : "minecraft:diorite_stairs", - "id" : -170 - }, - { - "name" : "minecraft:arrow", - "id" : 262 - }, - { - "name" : "minecraft:element_97", - "id" : -108 - }, - { - "name" : "minecraft:campfire", - "id" : 720 - }, - { - "name" : "minecraft:polished_andesite_stairs", - "id" : -174 - }, - { - "name" : "minecraft:acacia_stairs", - "id" : 163 - }, - { - "name" : "minecraft:iron_axe", - "id" : 258 - }, - { - "name" : "minecraft:flint_and_steel", - "id" : 259 - }, - { - "name" : "minecraft:bow", - "id" : 261 - }, - { - "name" : "minecraft:nautilus_shell", - "id" : 465 - }, - { - "name" : "minecraft:coal", - "id" : 263 - }, - { - "name" : "minecraft:bookshelf", - "id" : 47 - }, - { - "name" : "minecraft:wooden_sword", - "id" : 268 - }, - { - "name" : "minecraft:diamond_pickaxe", - "id" : 278 - }, - { - "name" : "minecraft:deadbush", - "id" : 32 - }, - { - "name" : "minecraft:ender_chest", - "id" : 130 - }, - { - "name" : "minecraft:record_stal", - "id" : 507 - }, - { - "name" : "minecraft:wooden_shovel", - "id" : 269 - }, - { - "name" : "minecraft:dark_oak_trapdoor", - "id" : -147 - }, - { - "name" : "minecraft:record_mall", - "id" : 505 - }, - { - "name" : "minecraft:wooden_axe", - "id" : 271 - }, - { - "name" : "minecraft:powered_comparator", - "id" : 150 - }, - { - "name" : "minecraft:diamond_shovel", - "id" : 277 - }, - { - "name" : "minecraft:golden_rail", - "id" : 27 - }, - { - "name" : "minecraft:lit_furnace", - "id" : 62 - }, - { - "name" : "minecraft:stick", - "id" : 280 - }, - { - "name" : "minecraft:slime_ball", - "id" : 341 - }, - { - "name" : "minecraft:element_58", - "id" : -69 - }, - { - "name" : "minecraft:golden_sword", - "id" : 283 - }, - { - "name" : "minecraft:golden_shovel", - "id" : 284 - }, - { - "name" : "minecraft:chest", - "id" : 54 - }, - { - "name" : "minecraft:golden_pickaxe", - "id" : 285 - }, - { - "name" : "minecraft:golden_axe", - "id" : 286 - }, - { - "name" : "minecraft:element_62", - "id" : -73 - }, - { - "name" : "minecraft:string", - "id" : 287 - }, - { - "name" : "minecraft:glowstone_dust", - "id" : 348 - }, - { - "name" : "minecraft:gunpowder", - "id" : 289 - }, - { - "name" : "minecraft:spawn_egg", - "id" : 383 - }, - { - "name" : "minecraft:fence", - "id" : 85 - }, - { - "name" : "minecraft:wooden_hoe", - "id" : 290 - }, - { - "name" : "minecraft:shulker_shell", - "id" : 445 - }, - { - "name" : "minecraft:iron_hoe", - "id" : 292 - }, - { - "name" : "minecraft:diamond_hoe", - "id" : 293 - }, - { - "name" : "minecraft:golden_hoe", - "id" : 294 - }, - { - "name" : "minecraft:turtle_shell_piece", - "id" : 468 - }, - { - "name" : "minecraft:sweet_berry_bush", - "id" : -207 - }, - { - "name" : "minecraft:info_update2", - "id" : 249 - }, - { - "name" : "minecraft:muttoncooked", - "id" : 424 - }, - { - "name" : "minecraft:wheat", - "id" : 296 - }, - { - "name" : "minecraft:dark_oak_door", - "id" : 431 - }, - { - "name" : "minecraft:grindstone", - "id" : -195 - }, - { - "name" : "minecraft:element_46", - "id" : -57 - }, - { - "name" : "minecraft:potion", - "id" : 373 - }, - { - "name" : "minecraft:wither_rose", - "id" : -216 - }, - { - "name" : "minecraft:leather_helmet", - "id" : 298 - }, - { - "name" : "minecraft:element_48", - "id" : -59 - }, - { - "name" : "minecraft:leather_chestplate", - "id" : 299 - }, - { - "name" : "minecraft:leather_boots", - "id" : 301 - }, - { - "name" : "minecraft:lectern", - "id" : -194 - }, - { - "name" : "minecraft:smithing_table", - "id" : -202 - }, - { - "name" : "minecraft:bedrock", - "id" : 7 - }, - { - "name" : "minecraft:chainmail_helmet", - "id" : 302 - }, - { - "name" : "minecraft:stonebrick", - "id" : 98 - }, - { - "name" : "minecraft:stickypistonarmcollision", - "id" : -217 - }, - { - "name" : "minecraft:structure_void", - "id" : 217 - }, - { - "name" : "minecraft:chainmail_chestplate", - "id" : 303 - }, - { - "name" : "minecraft:lit_blast_furnace", - "id" : -214 - }, - { - "name" : "minecraft:element_11", - "id" : -22 - }, - { - "name" : "minecraft:chainmail_leggings", - "id" : 304 - }, - { - "name" : "minecraft:saddle", - "id" : 329 - }, - { - "name" : "minecraft:purpur_block", - "id" : 201 - }, - { - "name" : "minecraft:chainmail_boots", - "id" : 305 - }, - { - "name" : "minecraft:ladder", - "id" : 65 - }, - { - "name" : "minecraft:iron_chestplate", - "id" : 307 - }, - { - "name" : "minecraft:diamond_helmet", - "id" : 310 - }, - { - "name" : "minecraft:iron_leggings", - "id" : 308 - }, - { - "name" : "minecraft:iron_boots", - "id" : 309 - }, - { - "name" : "minecraft:element_104", - "id" : -115 - }, - { - "name" : "minecraft:chorus_fruit_popped", - "id" : 433 - }, - { - "name" : "minecraft:diamond_chestplate", - "id" : 311 - }, - { - "name" : "minecraft:diamond_leggings", - "id" : 312 - }, - { - "name" : "minecraft:element_75", - "id" : -86 - }, - { - "name" : "minecraft:diamond_boots", - "id" : 313 - }, - { - "name" : "minecraft:acacia_button", - "id" : -140 - }, - { - "name" : "minecraft:standing_banner", - "id" : 176 - }, - { - "name" : "minecraft:golden_helmet", - "id" : 314 - }, - { - "name" : "minecraft:golden_chestplate", - "id" : 315 - }, - { - "name" : "minecraft:golden_leggings", - "id" : 316 - }, - { - "name" : "minecraft:golden_boots", - "id" : 317 - }, - { - "name" : "minecraft:item.hopper", - "id" : 154 - }, - { - "name" : "minecraft:shield", - "id" : 513 - }, - { - "name" : "minecraft:flint", - "id" : 318 - }, - { - "name" : "minecraft:painting", - "id" : 321 - }, - { - "name" : "minecraft:sign", - "id" : 323 - }, - { - "name" : "minecraft:wooden_door", - "id" : 324 - }, - { - "name" : "minecraft:bucket", - "id" : 325 - }, - { - "name" : "minecraft:minecart", - "id" : 328 - }, - { - "name" : "minecraft:prismarine_stairs", - "id" : -2 - }, - { - "name" : "minecraft:iron_door", - "id" : 330 - }, - { - "name" : "minecraft:tripwire_hook", - "id" : 131 - }, - { - "name" : "minecraft:redstone", - "id" : 331 - }, - { - "name" : "minecraft:andesite_stairs", - "id" : -171 - }, - { - "name" : "minecraft:sponge", - "id" : 19 - }, - { - "name" : "minecraft:snowball", - "id" : 332 - }, - { - "name" : "minecraft:boat", - "id" : 333 - }, - { - "name" : "minecraft:item.dark_oak_door", - "id" : 197 - }, - { - "name" : "minecraft:kelp", - "id" : 335 - }, - { - "name" : "minecraft:brick", - "id" : 336 - }, - { - "name" : "minecraft:clay_ball", - "id" : 337 - }, - { - "name" : "minecraft:real_double_stone_slab", - "id" : 43 - }, - { - "name" : "minecraft:reeds", - "id" : 338 - }, - { - "name" : "minecraft:dirt", - "id" : 3 - }, - { - "name" : "minecraft:magma", - "id" : 213 - }, - { - "name" : "minecraft:red_mushroom", - "id" : 40 - }, - { - "name" : "minecraft:paper", - "id" : 339 - }, - { - "name" : "minecraft:book", - "id" : 340 - }, - { - "name" : "minecraft:chest_minecart", - "id" : 342 - }, - { - "name" : "minecraft:flowing_lava", - "id" : 10 - }, - { - "name" : "minecraft:element_86", - "id" : -97 - }, - { - "name" : "minecraft:red_glazed_terracotta", - "id" : 234 - }, - { - "name" : "minecraft:crafting_table", - "id" : 58 - }, - { - "name" : "minecraft:egg", - "id" : 344 - }, - { - "name" : "minecraft:real_double_stone_slab4", - "id" : -168 - }, - { - "name" : "minecraft:end_gateway", - "id" : 209 - }, - { - "name" : "minecraft:compass", - "id" : 345 - }, - { - "name" : "minecraft:horsearmordiamond", - "id" : 419 - }, - { - "name" : "minecraft:sapling", - "id" : 6 - }, - { - "name" : "minecraft:fishing_rod", - "id" : 346 - }, - { - "name" : "minecraft:name_tag", - "id" : 421 - }, - { - "name" : "minecraft:clock", - "id" : 347 - }, - { - "name" : "minecraft:element_96", - "id" : -107 - }, - { - "name" : "minecraft:dye", - "id" : 351 - }, - { - "name" : "minecraft:anvil", - "id" : 145 - }, - { - "name" : "minecraft:conduit", - "id" : -157 - }, - { - "name" : "minecraft:bone", - "id" : 352 - }, - { - "name" : "minecraft:soul_sand", - "id" : 88 - }, - { - "name" : "minecraft:sugar", - "id" : 353 - }, - { - "name" : "minecraft:cake", - "id" : 354 - }, - { - "name" : "minecraft:element_113", - "id" : -124 - }, - { - "name" : "minecraft:mossy_cobblestone", - "id" : 48 - }, - { - "name" : "minecraft:bed", - "id" : 355 - }, - { - "name" : "minecraft:flowing_water", - "id" : 8 - }, - { - "name" : "minecraft:item.frame", - "id" : 199 - }, - { - "name" : "minecraft:repeater", - "id" : 356 - }, - { - "name" : "minecraft:map", - "id" : 358 - }, - { - "name" : "minecraft:shears", - "id" : 359 - }, - { - "name" : "minecraft:double_stone_slab2", - "id" : 182 - }, - { - "name" : "minecraft:element_3", - "id" : -14 - }, - { - "name" : "minecraft:element_23", - "id" : -34 - }, - { - "name" : "minecraft:skull", - "id" : 397 - }, - { - "name" : "minecraft:ender_pearl", - "id" : 368 - }, - { - "name" : "minecraft:carved_pumpkin", - "id" : -155 - }, - { - "name" : "minecraft:yellow_flower", - "id" : 37 - }, - { - "name" : "minecraft:shulker_box", - "id" : 218 - }, - { - "name" : "minecraft:blaze_rod", - "id" : 369 - }, - { - "name" : "minecraft:lit_pumpkin", - "id" : 91 - }, - { - "name" : "minecraft:ghast_tear", - "id" : 370 - }, - { - "name" : "minecraft:gold_nugget", - "id" : 371 - }, - { - "name" : "minecraft:glass_bottle", - "id" : 374 - }, - { - "name" : "minecraft:emptymap", - "id" : 395 - }, - { - "name" : "minecraft:fermented_spider_eye", - "id" : 376 - }, - { - "name" : "minecraft:element_81", - "id" : -92 - }, - { - "name" : "minecraft:monster_egg", - "id" : 97 - }, - { - "name" : "minecraft:blaze_powder", - "id" : 377 - }, - { - "name" : "minecraft:armor_stand", - "id" : 425 - }, - { - "name" : "minecraft:magma_cream", - "id" : 378 - }, - { - "name" : "minecraft:brewing_stand", - "id" : 379 - }, - { - "name" : "minecraft:darkoak_standing_sign", - "id" : -192 - }, - { - "name" : "minecraft:glowingobsidian", - "id" : 246 - }, - { - "name" : "minecraft:cauldron", - "id" : 380 - }, - { - "name" : "minecraft:nether_brick", - "id" : 112 - }, - { - "name" : "minecraft:ender_eye", - "id" : 381 - }, - { - "name" : "minecraft:experience_bottle", - "id" : 384 - }, - { - "name" : "minecraft:speckled_melon", - "id" : 382 - }, - { - "name" : "minecraft:coral", - "id" : -131 - }, - { - "name" : "minecraft:fireball", - "id" : 385 - }, - { - "name" : "minecraft:writable_book", - "id" : 386 - }, - { - "name" : "minecraft:frame", - "id" : 389 - }, - { - "name" : "minecraft:smoker", - "id" : -198 - }, - { - "name" : "minecraft:flower_pot", - "id" : 390 - }, - { - "name" : "minecraft:carrotonastick", - "id" : 398 - }, - { - "name" : "minecraft:netherstar", - "id" : 399 - }, - { - "name" : "minecraft:element_16", - "id" : -27 - }, - { - "name" : "minecraft:fireworks", - "id" : 401 - }, - { - "name" : "minecraft:element_30", - "id" : -41 - }, - { - "name" : "minecraft:fireworkscharge", - "id" : 402 - }, - { - "name" : "minecraft:trident", - "id" : 455 - }, - { - "name" : "minecraft:enchanted_book", - "id" : 403 - }, - { - "name" : "minecraft:comparator", - "id" : 404 - }, - { - "name" : "minecraft:netherbrick", - "id" : 405 - }, - { - "name" : "minecraft:concrete", - "id" : 236 - }, - { - "name" : "minecraft:element_73", - "id" : -84 - }, - { - "name" : "minecraft:quartz", - "id" : 406 - }, - { - "name" : "minecraft:tnt_minecart", - "id" : 407 - }, - { - "name" : "minecraft:leaves2", - "id" : 161 - }, - { - "name" : "minecraft:element_102", - "id" : -113 - }, - { - "name" : "minecraft:coral_fan_hang2", - "id" : -136 - }, - { - "name" : "minecraft:element_67", - "id" : -78 - }, - { - "name" : "minecraft:hopper_minecart", - "id" : 408 - }, - { - "name" : "minecraft:lead", - "id" : 420 - }, - { - "name" : "minecraft:sea_pickle", - "id" : -156 - }, - { - "name" : "minecraft:hopper", - "id" : 410 - }, - { - "name" : "minecraft:rabbit_foot", - "id" : 414 - }, - { - "name" : "minecraft:rabbit_hide", - "id" : 415 - }, - { - "name" : "minecraft:acacia_standing_sign", - "id" : -190 - }, - { - "name" : "minecraft:horsearmorleather", - "id" : 416 - }, - { - "name" : "minecraft:item.wheat", - "id" : 59 - }, - { - "name" : "minecraft:horsearmoriron", - "id" : 417 - }, - { - "name" : "minecraft:record_13", - "id" : 500 - }, - { - "name" : "minecraft:stone_button", - "id" : 77 - }, - { - "name" : "minecraft:record_cat", - "id" : 501 - }, - { - "name" : "minecraft:element_89", - "id" : -100 - }, - { - "name" : "minecraft:record_blocks", - "id" : 502 - }, - { - "name" : "minecraft:bamboo", - "id" : -163 - }, - { - "name" : "minecraft:element_72", - "id" : -83 - }, - { - "name" : "minecraft:record_chirp", - "id" : 503 - }, - { - "name" : "minecraft:frosted_ice", - "id" : 207 - }, - { - "name" : "minecraft:record_far", - "id" : 504 - }, - { - "name" : "minecraft:record_wait", - "id" : 511 - }, - { - "name" : "minecraft:spruce_door", - "id" : 427 - }, - { - "name" : "minecraft:record_mellohi", - "id" : 506 - }, - { - "name" : "minecraft:vine", - "id" : 106 - }, - { - "name" : "minecraft:record_ward", - "id" : 509 - }, - { - "name" : "minecraft:jungle_stairs", - "id" : 136 - }, - { - "name" : "minecraft:ice_bomb", - "id" : 453 - }, - { - "name" : "minecraft:record_11", - "id" : 510 - }, - { - "name" : "minecraft:prismarine_crystals", - "id" : 422 - }, - { - "name" : "minecraft:banner", - "id" : 446 - }, - { - "name" : "minecraft:glass_pane", - "id" : 102 - }, - { - "name" : "minecraft:muttonraw", - "id" : 423 - }, - { - "name" : "minecraft:end_crystal", - "id" : 426 - }, - { - "name" : "minecraft:element_55", - "id" : -66 - }, - { - "name" : "minecraft:birch_door", - "id" : 428 - }, - { - "name" : "minecraft:darkoak_wall_sign", - "id" : -193 - }, - { - "name" : "minecraft:jungle_door", - "id" : 429 - }, - { - "name" : "minecraft:acacia_door", - "id" : 430 - }, - { - "name" : "minecraft:element_116", - "id" : -127 - }, - { - "name" : "minecraft:chorus_fruit", - "id" : 432 - }, - { - "name" : "minecraft:cobblestone_wall", - "id" : 139 - }, - { - "name" : "minecraft:cobblestone", - "id" : 4 - }, - { - "name" : "minecraft:dragon_breath", - "id" : 437 - }, - { - "name" : "minecraft:cactus", - "id" : 81 - }, - { - "name" : "minecraft:splash_potion", - "id" : 438 - }, - { - "name" : "minecraft:spruce_stairs", - "id" : 134 - }, - { - "name" : "minecraft:loom", - "id" : -204 - }, - { - "name" : "minecraft:powered_repeater", - "id" : 94 - }, - { - "name" : "minecraft:lingering_potion", - "id" : 441 - }, - { - "name" : "minecraft:elytra", - "id" : 444 - }, - { - "name" : "minecraft:prismarine_shard", - "id" : 409 - }, - { - "name" : "minecraft:element_112", - "id" : -123 - }, - { - "name" : "minecraft:totem", - "id" : 450 - }, - { - "name" : "minecraft:iron_nugget", - "id" : 452 - }, - { - "name" : "minecraft:pumpkin_stem", - "id" : 104 - }, - { - "name" : "minecraft:element_50", - "id" : -61 - }, - { - "name" : "minecraft:lever", - "id" : 69 - }, - { - "name" : "minecraft:heart_of_the_sea", - "id" : 467 - }, - { - "name" : "minecraft:element_92", - "id" : -103 - }, - { - "name" : "minecraft:grass", - "id" : 2 - }, - { - "name" : "minecraft:turtle_helmet", - "id" : 469 - }, - { - "name" : "minecraft:wall_banner", - "id" : 177 - }, - { - "name" : "minecraft:spruce_button", - "id" : -144 - }, - { - "name" : "minecraft:phantom_membrane", - "id" : 470 - }, - { - "name" : "minecraft:crossbow", - "id" : 471 - }, - { - "name" : "minecraft:spruce_sign", - "id" : 472 - }, - { - "name" : "minecraft:quartz_stairs", - "id" : 156 - }, - { - "name" : "minecraft:daylight_detector_inverted", - "id" : 178 - }, - { - "name" : "minecraft:jungle_sign", - "id" : 474 - }, - { - "name" : "minecraft:red_flower", - "id" : 38 - }, - { - "name" : "minecraft:tallgrass", - "id" : 31 - }, - { - "name" : "minecraft:banner_pattern", - "id" : 434 - }, - { - "name" : "minecraft:suspicious_stew", - "id" : 734 - }, - { - "name" : "minecraft:birch_fence_gate", - "id" : 184 - }, - { - "name" : "minecraft:honeycomb", - "id" : 736 - }, - { - "name" : "minecraft:element_115", - "id" : -126 - }, - { - "name" : "minecraft:honey_bottle", - "id" : 737 - }, - { - "name" : "minecraft:element_4", - "id" : -15 - }, - { - "name" : "minecraft:element_24", - "id" : -35 - }, - { - "name" : "minecraft:camera", - "id" : 498 - }, - { - "name" : "minecraft:compound", - "id" : 499 - }, - { - "name" : "minecraft:bleach", - "id" : 451 - }, - { - "name" : "minecraft:element_40", - "id" : -51 - }, - { - "name" : "minecraft:honey_block", - "id" : -220 - }, - { - "name" : "minecraft:rapid_fertilizer", - "id" : 449 - }, - { - "name" : "minecraft:balloon", - "id" : 448 - }, - { - "name" : "minecraft:redstone_ore", - "id" : 73 - }, - { - "name" : "minecraft:stonecutter_block", - "id" : -197 - }, - { - "name" : "minecraft:medicine", - "id" : 447 - }, - { - "name" : "minecraft:gold_block", - "id" : 41 - }, - { - "name" : "minecraft:stripped_oak_log", - "id" : -10 - }, - { - "name" : "minecraft:blue_ice", - "id" : -11 - }, - { - "name" : "minecraft:sparkler", - "id" : 442 - }, - { - "name" : "minecraft:stone", - "id" : 1 - }, - { - "name" : "minecraft:sand", - "id" : 12 - }, - { - "name" : "minecraft:stained_hardened_clay", - "id" : 159 - }, - { - "name" : "minecraft:wool", - "id" : 35 - }, - { - "name" : "minecraft:unpowered_comparator", - "id" : 149 - }, - { - "name" : "minecraft:log", - "id" : 17 - }, - { - "name" : "minecraft:item.kelp", - "id" : -138 - }, - { - "name" : "minecraft:coral_block", - "id" : -132 - }, - { - "name" : "minecraft:element_54", - "id" : -65 - }, - { - "name" : "minecraft:double_stone_slab", - "id" : 44 - }, - { - "name" : "minecraft:double_stone_slab3", - "id" : -162 - }, - { - "name" : "minecraft:element_2", - "id" : -13 - }, - { - "name" : "minecraft:element_22", - "id" : -33 - }, - { - "name" : "minecraft:real_double_stone_slab2", - "id" : 181 - }, - { - "name" : "minecraft:real_double_stone_slab3", - "id" : -167 - }, - { - "name" : "minecraft:coral_fan", - "id" : -133 - }, - { - "name" : "minecraft:leaves", - "id" : 18 - }, - { - "name" : "minecraft:element_10", - "id" : -21 - }, - { - "name" : "minecraft:birch_button", - "id" : -141 - }, - { - "name" : "minecraft:sandstone", - "id" : 24 - }, - { - "name" : "minecraft:red_sandstone", - "id" : 179 - }, - { - "name" : "minecraft:element_91", - "id" : -102 - }, - { - "name" : "minecraft:wooden_slab", - "id" : 158 - }, - { - "name" : "minecraft:end_stone", - "id" : 121 - }, - { - "name" : "minecraft:double_plant", - "id" : 175 - }, - { - "name" : "minecraft:waterlily", - "id" : 111 - }, - { - "name" : "minecraft:snow_layer", - "id" : 78 - }, - { - "name" : "minecraft:black_glazed_terracotta", - "id" : 235 - }, - { - "name" : "minecraft:planks", - "id" : 5 - }, - { - "name" : "minecraft:quartz_block", - "id" : 155 - }, - { - "name" : "minecraft:seagrass", - "id" : -130 - }, - { - "name" : "minecraft:brown_mushroom_block", - "id" : 99 - }, - { - "name" : "minecraft:log2", - "id" : 162 - }, - { - "name" : "minecraft:end_portal_frame", - "id" : 120 - }, - { - "name" : "minecraft:lantern", - "id" : -208 - }, - { - "name" : "minecraft:prismarine", - "id" : 168 - }, - { - "name" : "minecraft:sealantern", - "id" : 169 - }, - { - "name" : "minecraft:hard_stained_glass", - "id" : 254 - }, - { - "name" : "minecraft:concrete_powder", - "id" : 237 - }, - { - "name" : "minecraft:stained_glass", - "id" : 241 - }, - { - "name" : "minecraft:element_82", - "id" : -93 - }, - { - "name" : "minecraft:stained_glass_pane", - "id" : 160 - }, - { - "name" : "minecraft:quartz_ore", - "id" : 153 - }, - { - "name" : "minecraft:undyed_shulker_box", - "id" : 205 - }, - { - "name" : "minecraft:element_107", - "id" : -118 - }, - { - "name" : "minecraft:piston", - "id" : 33 - }, - { - "name" : "minecraft:sticky_piston", - "id" : 29 - }, - { - "name" : "minecraft:turtle_egg", - "id" : -159 - }, - { - "name" : "minecraft:acacia_fence_gate", - "id" : 187 - }, - { - "name" : "minecraft:colored_torch_bp", - "id" : 204 - }, - { - "name" : "minecraft:lava", - "id" : 11 - }, - { - "name" : "minecraft:scaffolding", - "id" : -165 - }, - { - "name" : "minecraft:blast_furnace", - "id" : -196 - }, - { - "name" : "minecraft:item.cauldron", - "id" : 118 - }, - { - "name" : "minecraft:barrel", - "id" : -203 - }, - { - "name" : "minecraft:bell", - "id" : -206 - }, - { - "name" : "minecraft:element_42", - "id" : -53 - }, - { - "name" : "minecraft:cartography_table", - "id" : -200 - }, - { - "name" : "minecraft:end_rod", - "id" : 208 - }, - { - "name" : "minecraft:fletching_table", - "id" : -201 - }, - { - "name" : "minecraft:wood", - "id" : -212 - }, - { - "name" : "minecraft:chemistry_table", - "id" : 238 - }, - { - "name" : "minecraft:element_70", - "id" : -81 - }, - { - "name" : "minecraft:tnt", - "id" : 46 - }, - { - "name" : "minecraft:hard_stained_glass_pane", - "id" : 191 - }, - { - "name" : "minecraft:colored_torch_rg", - "id" : 202 - }, - { - "name" : "minecraft:brown_mushroom", - "id" : 39 - }, - { - "name" : "minecraft:element_0", - "id" : 36 - }, - { - "name" : "minecraft:element_20", - "id" : -31 - }, - { - "name" : "minecraft:element_1", - "id" : -12 - }, - { - "name" : "minecraft:element_21", - "id" : -32 - }, - { - "name" : "minecraft:element_6", - "id" : -17 - }, - { - "name" : "minecraft:element_26", - "id" : -37 - }, - { - "name" : "minecraft:element_7", - "id" : -18 - }, - { - "name" : "minecraft:element_27", - "id" : -38 - }, - { - "name" : "minecraft:element_8", - "id" : -19 - }, - { - "name" : "minecraft:element_28", - "id" : -39 - }, - { - "name" : "minecraft:dark_oak_pressure_plate", - "id" : -152 - }, - { - "name" : "minecraft:element_9", - "id" : -20 - }, - { - "name" : "minecraft:element_29", - "id" : -40 - }, - { - "name" : "minecraft:item.spruce_door", - "id" : 193 - }, - { - "name" : "minecraft:element_12", - "id" : -23 - }, - { - "name" : "minecraft:cyan_glazed_terracotta", - "id" : 229 - }, - { - "name" : "minecraft:element_13", - "id" : -24 - }, - { - "name" : "minecraft:element_14", - "id" : -25 - }, - { - "name" : "minecraft:iron_ore", - "id" : 15 - }, - { - "name" : "minecraft:element_17", - "id" : -28 - }, - { - "name" : "minecraft:element_18", - "id" : -29 - }, - { - "name" : "minecraft:birch_pressure_plate", - "id" : -151 - }, - { - "name" : "minecraft:element_19", - "id" : -30 - }, - { - "name" : "minecraft:wooden_pressure_plate", - "id" : 72 - }, - { - "name" : "minecraft:element_33", - "id" : -44 - }, - { - "name" : "minecraft:element_34", - "id" : -45 - }, - { - "name" : "minecraft:element_35", - "id" : -46 - }, - { - "name" : "minecraft:composter", - "id" : -213 - }, - { - "name" : "minecraft:element_36", - "id" : -47 - }, - { - "name" : "minecraft:element_37", - "id" : -48 - }, - { - "name" : "minecraft:element_39", - "id" : -50 - }, - { - "name" : "minecraft:element_41", - "id" : -52 - }, - { - "name" : "minecraft:hay_block", - "id" : 170 - }, - { - "name" : "minecraft:element_43", - "id" : -54 - }, - { - "name" : "minecraft:lit_redstone_lamp", - "id" : 124 - }, - { - "name" : "minecraft:element_44", - "id" : -55 - }, - { - "name" : "minecraft:element_45", - "id" : -56 - }, - { - "name" : "minecraft:element_49", - "id" : -60 - }, - { - "name" : "minecraft:element_51", - "id" : -62 - }, - { - "name" : "minecraft:element_56", - "id" : -67 - }, - { - "name" : "minecraft:element_57", - "id" : -68 - }, - { - "name" : "minecraft:element_59", - "id" : -70 - }, - { - "name" : "minecraft:element_60", - "id" : -71 - }, - { - "name" : "minecraft:dropper", - "id" : 125 - }, - { - "name" : "minecraft:element_61", - "id" : -72 - }, - { - "name" : "minecraft:element_63", - "id" : -74 - }, - { - "name" : "minecraft:element_64", - "id" : -75 - }, - { - "name" : "minecraft:element_65", - "id" : -76 - }, - { - "name" : "minecraft:coral_fan_hang3", - "id" : -137 - }, - { - "name" : "minecraft:element_66", - "id" : -77 - }, - { - "name" : "minecraft:redstone_lamp", - "id" : 123 - }, - { - "name" : "minecraft:element_68", - "id" : -79 - }, - { - "name" : "minecraft:spruce_trapdoor", - "id" : -149 - }, - { - "name" : "minecraft:purple_glazed_terracotta", - "id" : 219 - }, - { - "name" : "minecraft:element_69", - "id" : -80 - }, - { - "name" : "minecraft:iron_block", - "id" : 42 - }, - { - "name" : "minecraft:element_71", - "id" : -82 - }, - { - "name" : "minecraft:element_76", - "id" : -87 - }, - { - "name" : "minecraft:element_77", - "id" : -88 - }, - { - "name" : "minecraft:water", - "id" : 9 - }, - { - "name" : "minecraft:element_78", - "id" : -89 - }, - { - "name" : "minecraft:element_79", - "id" : -90 - }, - { - "name" : "minecraft:element_80", - "id" : -91 - }, - { - "name" : "minecraft:netherreactor", - "id" : 247 - }, - { - "name" : "minecraft:element_83", - "id" : -94 - }, - { - "name" : "minecraft:element_84", - "id" : -95 - }, - { - "name" : "minecraft:jungle_wall_sign", - "id" : -189 - }, - { - "name" : "minecraft:end_brick_stairs", - "id" : -178 - }, - { - "name" : "minecraft:element_85", - "id" : -96 - }, - { - "name" : "minecraft:element_88", - "id" : -99 - }, - { - "name" : "minecraft:element_90", - "id" : -101 - }, - { - "name" : "minecraft:birch_standing_sign", - "id" : -186 - }, - { - "name" : "minecraft:gold_ore", - "id" : 14 - }, - { - "name" : "minecraft:element_93", - "id" : -104 - }, - { - "name" : "minecraft:element_94", - "id" : -105 - }, - { - "name" : "minecraft:element_95", - "id" : -106 - }, - { - "name" : "minecraft:glass", - "id" : 20 - }, - { - "name" : "minecraft:red_nether_brick", - "id" : 215 - }, - { - "name" : "minecraft:element_98", - "id" : -109 - }, - { - "name" : "minecraft:element_99", - "id" : -110 - }, - { - "name" : "minecraft:element_100", - "id" : -111 - }, - { - "name" : "minecraft:element_101", - "id" : -112 - }, - { - "name" : "minecraft:element_103", - "id" : -114 - }, - { - "name" : "minecraft:element_106", - "id" : -117 - }, - { - "name" : "minecraft:element_108", - "id" : -119 - }, - { - "name" : "minecraft:element_109", - "id" : -120 - }, - { - "name" : "minecraft:element_110", - "id" : -121 - }, - { - "name" : "minecraft:element_111", - "id" : -122 - }, - { - "name" : "minecraft:element_114", - "id" : -125 - }, - { - "name" : "minecraft:element_117", - "id" : -128 - }, - { - "name" : "minecraft:slime", - "id" : 165 - }, - { - "name" : "minecraft:spruce_standing_sign", - "id" : -181 - }, - { - "name" : "minecraft:element_118", - "id" : -129 - }, - { - "name" : "minecraft:gravel", - "id" : 13 - }, - { - "name" : "minecraft:detector_rail", - "id" : 28 - }, - { - "name" : "minecraft:oak_stairs", - "id" : 53 - }, - { - "name" : "minecraft:coal_ore", - "id" : 16 - }, - { - "name" : "minecraft:diamond_block", - "id" : 57 - }, - { - "name" : "minecraft:item.cake", - "id" : 92 - }, - { - "name" : "minecraft:spruce_pressure_plate", - "id" : -154 - }, - { - "name" : "minecraft:diamond_ore", - "id" : 56 - }, - { - "name" : "minecraft:furnace", - "id" : 61 - }, - { - "name" : "minecraft:underwater_torch", - "id" : 239 - }, - { - "name" : "minecraft:web", - "id" : 30 - }, - { - "name" : "minecraft:jungle_standing_sign", - "id" : -188 - }, - { - "name" : "minecraft:standing_sign", - "id" : 63 - }, - { - "name" : "minecraft:lapis_ore", - "id" : 21 - }, - { - "name" : "minecraft:beehive", - "id" : -219 - }, - { - "name" : "minecraft:item.bed", - "id" : 26 - }, - { - "name" : "minecraft:lapis_block", - "id" : 22 - }, - { - "name" : "minecraft:stripped_acacia_log", - "id" : -8 - }, - { - "name" : "minecraft:dispenser", - "id" : 23 - }, - { - "name" : "minecraft:obsidian", - "id" : 49 - }, - { - "name" : "minecraft:brick_block", - "id" : 45 - }, - { - "name" : "minecraft:dried_kelp_block", - "id" : -139 - }, - { - "name" : "minecraft:structure_block", - "id" : 252 - }, - { - "name" : "minecraft:pistonarmcollision", - "id" : 34 - }, - { - "name" : "minecraft:green_glazed_terracotta", - "id" : 233 - }, - { - "name" : "minecraft:acacia_trapdoor", - "id" : -145 - }, - { - "name" : "minecraft:carrots", - "id" : 141 - }, - { - "name" : "minecraft:rail", - "id" : 66 - }, - { - "name" : "minecraft:torch", - "id" : 50 - }, - { - "name" : "minecraft:mob_spawner", - "id" : 52 - }, - { - "name" : "minecraft:lava_cauldron", - "id" : -210 - }, - { - "name" : "minecraft:redstone_wire", - "id" : 55 - }, - { - "name" : "minecraft:farmland", - "id" : 60 - }, - { - "name" : "minecraft:wall_sign", - "id" : 68 - }, - { - "name" : "minecraft:stone_pressure_plate", - "id" : 70 - }, - { - "name" : "minecraft:red_sandstone_stairs", - "id" : 180 - }, - { - "name" : "minecraft:item.iron_door", - "id" : 71 - }, - { - "name" : "minecraft:lit_redstone_ore", - "id" : 74 - }, - { - "name" : "minecraft:stripped_jungle_log", - "id" : -7 - }, - { - "name" : "minecraft:unlit_redstone_torch", - "id" : 75 - }, - { - "name" : "minecraft:red_nether_brick_stairs", - "id" : -184 - }, - { - "name" : "minecraft:redstone_torch", - "id" : 76 - }, - { - "name" : "minecraft:ice", - "id" : 79 - }, - { - "name" : "minecraft:snow", - "id" : 80 - }, - { - "name" : "minecraft:command_block", - "id" : 137 - }, - { - "name" : "minecraft:clay", - "id" : 82 - }, - { - "name" : "minecraft:jukebox", - "id" : 84 - }, - { - "name" : "minecraft:pumpkin", - "id" : 86 - }, - { - "name" : "minecraft:item.acacia_door", - "id" : 196 - }, - { - "name" : "minecraft:nether_brick_stairs", - "id" : 114 - }, - { - "name" : "minecraft:netherrack", - "id" : 87 - }, - { - "name" : "minecraft:glowstone", - "id" : 89 - }, - { - "name" : "minecraft:hard_glass", - "id" : 253 - }, - { - "name" : "minecraft:portal", - "id" : 90 - }, - { - "name" : "minecraft:item.beetroot", - "id" : 244 - }, - { - "name" : "minecraft:unpowered_repeater", - "id" : 93 - }, - { - "name" : "minecraft:invisiblebedrock", - "id" : 95 - }, - { - "name" : "minecraft:trapdoor", - "id" : 96 - }, - { - "name" : "minecraft:item.jungle_door", - "id" : 195 - }, - { - "name" : "minecraft:iron_bars", - "id" : 101 - }, - { - "name" : "minecraft:chain_command_block", - "id" : 189 - }, - { - "name" : "minecraft:melon_block", - "id" : 103 - }, - { - "name" : "minecraft:emerald_block", - "id" : 133 - }, - { - "name" : "minecraft:chemical_heat", - "id" : 192 - }, - { - "name" : "minecraft:melon_stem", - "id" : 105 - }, - { - "name" : "minecraft:fence_gate", - "id" : 107 - }, - { - "name" : "minecraft:brick_stairs", - "id" : 108 - }, - { - "name" : "minecraft:stone_brick_stairs", - "id" : 109 - }, - { - "name" : "minecraft:mycelium", - "id" : 110 - }, - { - "name" : "minecraft:smooth_stone", - "id" : -183 - }, - { - "name" : "minecraft:nether_brick_fence", - "id" : 113 - }, - { - "name" : "minecraft:item.nether_wart", - "id" : 115 - }, - { - "name" : "minecraft:enchanting_table", - "id" : 116 - }, - { - "name" : "minecraft:end_portal", - "id" : 119 - }, - { - "name" : "minecraft:dragon_egg", - "id" : 122 - }, - { - "name" : "minecraft:granite_stairs", - "id" : -169 - }, - { - "name" : "minecraft:podzol", - "id" : 243 - }, - { - "name" : "minecraft:activator_rail", - "id" : 126 - }, - { - "name" : "minecraft:cocoa", - "id" : 127 - }, - { - "name" : "minecraft:emerald_ore", - "id" : 129 - }, - { - "name" : "minecraft:brown_glazed_terracotta", - "id" : 232 - }, - { - "name" : "minecraft:pink_glazed_terracotta", - "id" : 226 - }, - { - "name" : "minecraft:observer", - "id" : 251 - }, - { - "name" : "minecraft:info_update", - "id" : 248 - }, - { - "name" : "minecraft:birch_stairs", - "id" : 135 - }, - { - "name" : "minecraft:coral_fan_hang", - "id" : -135 - }, - { - "name" : "minecraft:packed_ice", - "id" : 174 - }, - { - "name" : "minecraft:item.flower_pot", - "id" : 140 - }, - { - "name" : "minecraft:potatoes", - "id" : 142 - }, - { - "name" : "minecraft:wooden_button", - "id" : 143 - }, - { - "name" : "minecraft:item.skull", - "id" : 144 - }, - { - "name" : "minecraft:trapped_chest", - "id" : 146 - }, - { - "name" : "minecraft:light_weighted_pressure_plate", - "id" : 147 - }, - { - "name" : "minecraft:heavy_weighted_pressure_plate", - "id" : 148 - }, - { - "name" : "minecraft:daylight_detector", - "id" : 151 - }, - { - "name" : "minecraft:smooth_sandstone_stairs", - "id" : -177 - }, - { - "name" : "minecraft:repeating_command_block", - "id" : 188 - }, - { - "name" : "minecraft:double_wooden_slab", - "id" : 157 - }, - { - "name" : "minecraft:dark_oak_stairs", - "id" : 164 - }, - { - "name" : "minecraft:iron_trapdoor", - "id" : 167 - }, - { - "name" : "minecraft:hardened_clay", - "id" : 172 - }, - { - "name" : "minecraft:coal_block", - "id" : 173 - }, - { - "name" : "minecraft:purpur_stairs", - "id" : 203 - }, - { - "name" : "minecraft:jungle_fence_gate", - "id" : 185 - }, - { - "name" : "minecraft:dark_oak_fence_gate", - "id" : 186 - }, - { - "name" : "minecraft:grass_path", - "id" : 198 - }, - { - "name" : "minecraft:bone_block", - "id" : 216 - }, - { - "name" : "minecraft:normal_stone_stairs", - "id" : -180 - }, - { - "name" : "minecraft:chorus_flower", - "id" : 200 - }, - { - "name" : "minecraft:jungle_pressure_plate", - "id" : -153 - }, - { - "name" : "minecraft:end_bricks", - "id" : 206 - }, - { - "name" : "minecraft:blue_glazed_terracotta", - "id" : 231 - }, - { - "name" : "minecraft:movingblock", - "id" : 250 - }, - { - "name" : "minecraft:light_blue_glazed_terracotta", - "id" : 223 - }, - { - "name" : "minecraft:nether_wart_block", - "id" : 214 - }, - { - "name" : "minecraft:white_glazed_terracotta", - "id" : 220 - }, - { - "name" : "minecraft:orange_glazed_terracotta", - "id" : 221 - }, - { - "name" : "minecraft:magenta_glazed_terracotta", - "id" : 222 - }, - { - "name" : "minecraft:yellow_glazed_terracotta", - "id" : 224 - }, - { - "name" : "minecraft:barrier", - "id" : -161 - }, - { - "name" : "minecraft:gray_glazed_terracotta", - "id" : 227 - }, - { - "name" : "minecraft:silver_glazed_terracotta", - "id" : 228 - }, - { - "name" : "minecraft:chorus_plant", - "id" : 240 - }, - { - "name" : "minecraft:fire", - "id" : 51 - }, - { - "name" : "minecraft:item.camera", - "id" : 242 - }, - { - "name" : "minecraft:stonecutter", - "id" : 245 - }, - { - "name" : "minecraft:reserved6", - "id" : 255 - }, - { - "name" : "minecraft:dark_prismarine_stairs", - "id" : -3 - }, - { - "name" : "minecraft:prismarine_bricks_stairs", - "id" : -4 - }, - { - "name" : "minecraft:stripped_spruce_log", - "id" : -5 - }, - { - "name" : "minecraft:stripped_dark_oak_log", - "id" : -9 - }, - { - "name" : "minecraft:hard_glass_pane", - "id" : 190 - }, - { - "name" : "minecraft:mossy_cobblestone_stairs", - "id" : -179 - }, - { - "name" : "minecraft:smooth_red_sandstone_stairs", - "id" : -176 - }, - { - "name" : "minecraft:bamboo_sapling", - "id" : -164 - }, - { - "name" : "minecraft:jungle_button", - "id" : -143 - }, - { - "name" : "minecraft:birch_wall_sign", - "id" : -187 - }, - { - "name" : "minecraft:spruce_wall_sign", - "id" : -182 - }, - { - "name" : "minecraft:jungle_trapdoor", - "id" : -148 - }, - { - "name" : "minecraft:dark_oak_button", - "id" : -142 - }, - { - "name" : "minecraft:birch_trapdoor", - "id" : -146 - }, - { - "name" : "minecraft:jigsaw", - "id" : -211 - }, - { - "name" : "minecraft:acacia_pressure_plate", - "id" : -150 - }, - { - "name" : "minecraft:bubble_column", - "id" : -160 - }, - { - "name" : "minecraft:polished_diorite_stairs", - "id" : -173 - }, - { - "name" : "minecraft:smooth_quartz_stairs", - "id" : -185 - }, - { - "name" : "minecraft:acacia_wall_sign", - "id" : -191 - }, - { - "name" : "minecraft:lit_smoker", - "id" : -199 - }, - { - "name" : "minecraft:item.campfire", - "id" : -209 - }, - { - "name" : "minecraft:bee_nest", - "id" : -218 - }, - { - "name" : "minecraft:honeycomb_block", - "id" : -221 - } + { + "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", + "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_door", + "id" : 430 + }, + { + "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_pressure_plate", + "id" : -150 + }, + { + "name" : "minecraft:tallgrass", + "id" : 31 + }, + { + "name" : "minecraft:brown_mushroom_block", + "id" : 99 + }, + { + "name" : "minecraft:element_103", + "id" : -114 + }, + { + "name" : "minecraft:crimson_fungus", + "id" : -228 + }, + { + "name" : "minecraft:item.frame", + "id" : 199 + }, + { + "name" : "minecraft:red_mushroom_block", + "id" : 100 + }, + { + "name" : "minecraft:log2", + "id" : 162 + }, + { + "name" : "minecraft:conduit", + "id" : -157 + }, + { + "name" : "minecraft:prismarine", + "id" : 168 + }, + { + "name" : "minecraft:magma", + "id" : 213 + }, + { + "name" : "minecraft:element_22", + "id" : -33 + }, + { + "name" : "minecraft:undyed_shulker_box", + "id" : 205 + }, + { + "name" : "minecraft:shulker_box", + "id" : 218 + }, + { + "name" : "minecraft:spruce_standing_sign", + "id" : -181 + }, + { + "name" : "minecraft:sticky_piston", + "id" : 29 + }, + { + "name" : "minecraft:element_10", + "id" : -21 + }, + { + "name" : "minecraft:turtle_egg", + "id" : -159 + }, + { + "name" : "minecraft:bamboo", + "id" : -163 + }, + { + "name" : "minecraft:observer", + "id" : 251 + }, + { + "name" : "minecraft:scaffolding", + "id" : -165 + }, + { + "name" : "minecraft:blast_furnace", + "id" : -196 + }, + { + "name" : "minecraft:grindstone", + "id" : -195 + }, + { + "name" : "minecraft:bell", + "id" : -206 + }, + { + "name" : "minecraft:end_rod", + "id" : 208 + }, + { + "name" : "minecraft:fletching_table", + "id" : -201 + }, + { + "name" : "minecraft:item.hopper", + "id" : 154 + }, + { + "name" : "minecraft:wood", + "id" : -212 + }, + { + "name" : "minecraft:chemistry_table", + "id" : 238 + }, + { + "name" : "minecraft:tnt", + "id" : 46 + }, + { + "name" : "minecraft:hard_stained_glass_pane", + "id" : 191 + }, + { + "name" : "minecraft:crimson_slab", + "id" : -264 + }, + { + "name" : "minecraft:element_87", + "id" : -98 + }, + { + "name" : "minecraft:warped_slab", + "id" : -265 + }, + { + "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_glazed_terracotta", + "id" : 235 + }, + { + "name" : "minecraft:lit_redstone_ore", + "id" : 74 + }, + { + "name" : "minecraft:crafting_table", + "id" : 58 + }, + { + "name" : "minecraft:element_57", + "id" : -68 + }, + { + "name" : "minecraft:element_58", + "id" : -69 + }, + { + "name" : "minecraft:element_60", + "id" : -71 + }, + { + "name" : "minecraft:element_64", + "id" : -75 + }, + { + "name" : "minecraft:element_65", + "id" : -76 + }, + { + "name" : "minecraft:element_67", + "id" : -78 + }, + { + "name" : "minecraft:element_70", + "id" : -81 + }, + { + "name" : "minecraft:element_72", + "id" : -83 + }, + { + "name" : "minecraft:element_76", + "id" : -87 + }, + { + "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_ice", + "id" : -11 + }, + { + "name" : "minecraft:element_83", + "id" : -94 + }, + { + "name" : "minecraft:element_89", + "id" : -100 + }, + { + "name" : "minecraft:element_91", + "id" : -102 + }, + { + "name" : "minecraft:element_96", + "id" : -107 + }, + { + "name" : "minecraft:element_97", + "id" : -108 + }, + { + "name" : "minecraft:cactus", + "id" : 81 + }, + { + "name" : "minecraft:element_99", + "id" : -110 + }, + { + "name" : "minecraft:element_105", + "id" : -116 + }, + { + "name" : "minecraft:element_106", + "id" : -117 + }, + { + "name" : "minecraft:cyan_glazed_terracotta", + "id" : 229 + }, + { + "name" : "minecraft:element_107", + "id" : -118 + }, + { + "name" : "minecraft:element_108", + "id" : -119 + }, + { + "name" : "minecraft:element_109", + "id" : -120 + }, + { + "name" : "minecraft:element_112", + "id" : -123 + }, + { + "name" : "minecraft:warped_button", + "id" : -261 + }, + { + "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:crying_obsidian", + "id" : -289 + }, + { + "name" : "minecraft:end_crystal", + "id" : 426 + }, + { + "name" : "minecraft:tripwire_hook", + "id" : 131 + }, + { + "name" : "minecraft:blue_glazed_terracotta", + "id" : 231 + }, + { + "name" : "minecraft:daylight_detector_inverted", + "id" : 178 + }, + { + "name" : "minecraft:warped_trapdoor", + "id" : -247 + }, + { + "name" : "minecraft:twisting_vines", + "id" : -287 + }, + { + "name" : "minecraft:noteblock", + "id" : 25 + }, + { + "name" : "minecraft:gravel", + "id" : 13 + }, + { + "name" : "minecraft:golden_rail", + "id" : 27 + }, + { + "name" : "minecraft:warped_wall_sign", + "id" : -253 + }, + { + "name" : "minecraft:oak_stairs", + "id" : 53 + }, + { + "name" : "minecraft:grass", + "id" : 2 + }, + { + "name" : "minecraft:acacia_button", + "id" : -140 + }, + { + "name" : "minecraft:snow", + "id" : 80 + }, + { + "name" : "minecraft:detector_rail", + "id" : 28 + }, + { + "name" : "minecraft:dark_oak_trapdoor", + "id" : -147 + }, + { + "name" : "minecraft:spruce_pressure_plate", + "id" : -154 + }, + { + "name" : "minecraft:water", + "id" : 9 + }, + { + "name" : "minecraft:furnace", + "id" : 61 + }, + { + "name" : "minecraft:item.wooden_door", + "id" : 64 + }, + { + "name" : "minecraft:gold_ore", + "id" : 14 + }, + { + "name" : "minecraft:web", + "id" : 30 + }, + { + "name" : "minecraft:unlit_redstone_torch", + "id" : 75 + }, + { + "name" : "minecraft:ladder", + "id" : 65 + }, + { + "name" : "minecraft:sweet_berry_bush", + "id" : -207 + }, + { + "name" : "minecraft:standing_sign", + "id" : 63 + }, + { + "name" : "minecraft:glass", + "id" : 20 + }, + { + "name" : "minecraft:lapis_ore", + "id" : 21 + }, + { + "name" : "minecraft:bookshelf", + "id" : 47 + }, + { + "name" : "minecraft:item.bed", + "id" : 26 + }, + { + "name" : "minecraft:stripped_warped_hyphae", + "id" : -301 + }, + { + "name" : "minecraft:wither_rose", + "id" : -216 + }, + { + "name" : "minecraft:wooden_pressure_plate", + "id" : 72 + }, + { + "name" : "minecraft:powered_comparator", + "id" : 150 + }, + { + "name" : "minecraft:lapis_block", + "id" : 22 + }, + { + "name" : "minecraft:dispenser", + "id" : 23 + }, + { + "name" : "minecraft:item.wheat", + "id" : 59 + }, + { + "name" : "minecraft:item.spruce_door", + "id" : 193 + }, + { + "name" : "minecraft:diamond_ore", + "id" : 56 + }, + { + "name" : "minecraft:deadbush", + "id" : 32 + }, + { + "name" : "minecraft:pistonarmcollision", + "id" : 34 + }, + { + "name" : "minecraft:blackstone_stairs", + "id" : -276 + }, + { + "name" : "minecraft:dried_kelp_block", + "id" : -139 + }, + { + "name" : "minecraft:item.soul_campfire", + "id" : -290 + }, + { + "name" : "minecraft:green_glazed_terracotta", + "id" : 233 + }, + { + "name" : "minecraft:crimson_pressure_plate", + "id" : -262 + }, + { + "name" : "minecraft:spruce_fence_gate", + "id" : 183 + }, + { + "name" : "minecraft:iron_block", + "id" : 42 + }, + { + "name" : "minecraft:lever", + "id" : 69 + }, + { + "name" : "minecraft:mossy_cobblestone", + "id" : 48 + }, + { + "name" : "minecraft:torch", + "id" : 50 + }, + { + "name" : "minecraft:acacia_fence_gate", + "id" : 187 + }, + { + "name" : "minecraft:quartz_stairs", + "id" : 156 + }, + { + "name" : "minecraft:dragon_egg", + "id" : 122 + }, + { + "name" : "minecraft:lava_cauldron", + "id" : -210 + }, + { + "name" : "minecraft:jungle_standing_sign", + "id" : -188 + }, + { + "name" : "minecraft:redstone_wire", + "id" : 55 + }, + { + "name" : "minecraft:jungle_wall_sign", + "id" : -189 + }, + { + "name" : "minecraft:lit_furnace", + "id" : 62 + }, + { + "name" : "minecraft:beehive", + "id" : -219 + }, + { + "name" : "minecraft:crimson_wall_sign", + "id" : -252 + }, + { + "name" : "minecraft:stone_stairs", + "id" : 67 + }, + { + "name" : "minecraft:orange_glazed_terracotta", + "id" : 221 + }, + { + "name" : "minecraft:brick_stairs", + "id" : 108 + }, + { + "name" : "minecraft:wall_sign", + "id" : 68 + }, + { + "name" : "minecraft:warped_nylium", + "id" : -233 + }, + { + "name" : "minecraft:quartz_bricks", + "id" : -304 + }, + { + "name" : "minecraft:item.iron_door", + "id" : 71 + }, + { + "name" : "minecraft:redstone_ore", + "id" : 73 + }, + { + "name" : "minecraft:lectern", + "id" : -194 + }, + { + "name" : "minecraft:gilded_blackstone", + "id" : -281 + }, + { + "name" : "minecraft:red_nether_brick_stairs", + "id" : -184 + }, + { + "name" : "minecraft:basalt", + "id" : -234 + }, + { + "name" : "minecraft:stone_button", + "id" : 77 + }, + { + "name" : "minecraft:netherrack", + "id" : 87 + }, + { + "name" : "minecraft:nether_brick_stairs", + "id" : 114 + }, + { + "name" : "minecraft:item.acacia_door", + "id" : 196 + }, + { + "name" : "minecraft:item.cake", + "id" : 92 + }, + { + "name" : "minecraft:unpowered_repeater", + "id" : 93 + }, + { + "name" : "minecraft:powered_repeater", + "id" : 94 + }, + { + "name" : "minecraft:trapdoor", + "id" : 96 + }, + { + "name" : "minecraft:coral_fan_hang3", + "id" : -137 + }, + { + "name" : "minecraft:item.jungle_door", + "id" : 195 + }, + { + "name" : "minecraft:glass_pane", + "id" : 102 + }, + { + "name" : "minecraft:emerald_ore", + "id" : 129 + }, + { + "name" : "minecraft:crimson_planks", + "id" : -242 + }, + { + "name" : "minecraft:crimson_stem", + "id" : -225 + }, + { + "name" : "minecraft:weeping_vines", + "id" : -231 + }, + { + "name" : "minecraft:pumpkin_stem", + "id" : 104 + }, + { + "name" : "minecraft:emerald_block", + "id" : 133 + }, + { + "name" : "minecraft:melon_stem", + "id" : 105 + }, + { + "name" : "minecraft:chemical_heat", + "id" : 192 + }, + { + "name" : "minecraft:warped_wart_block", + "id" : -227 + }, + { + "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:enchanting_table", + "id" : 116 + }, + { + "name" : "minecraft:end_stone", + "id" : 121 + }, + { + "name" : "minecraft:redstone_lamp", + "id" : 123 + }, + { + "name" : "minecraft:jungle_stairs", + "id" : 136 + }, + { + "name" : "minecraft:dropper", + "id" : 125 + }, + { + "name" : "minecraft:activator_rail", + "id" : 126 + }, + { + "name" : "minecraft:cocoa", + "id" : 127 + }, + { + "name" : "minecraft:soul_torch", + "id" : -268 + }, + { + "name" : "minecraft:info_update", + "id" : 248 + }, + { + "name" : "minecraft:packed_ice", + "id" : 174 + }, + { + "name" : "minecraft:coral_fan_hang", + "id" : -135 + }, + { + "name" : "minecraft:item.flower_pot", + "id" : 140 + }, + { + "name" : "minecraft:potatoes", + "id" : 142 + }, + { + "name" : "minecraft:wooden_button", + "id" : 143 + }, + { + "name" : "minecraft:item.skull", + "id" : 144 + }, + { + "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:fire", + "id" : 51 + }, + { + "name" : "minecraft:hard_glass", + "id" : 253 + }, + { + "name" : "minecraft:acacia_standing_sign", + "id" : -190 + }, + { + "name" : "minecraft:hard_glass_pane", + "id" : 190 + }, + { + "name" : "minecraft:mossy_cobblestone_stairs", + "id" : -179 + }, + { + "name" : "minecraft:crimson_fence_gate", + "id" : -258 + }, + { + "name" : "minecraft:mossy_stone_brick_stairs", + "id" : -175 + }, + { + "name" : "minecraft:item.nether_sprouts", + "id" : -238 + }, + { + "name" : "minecraft:polished_blackstone_brick_double_slab", + "id" : -285 + }, + { + "name" : "minecraft:cracked_polished_blackstone_bricks", + "id" : -280 + }, + { + "name" : "minecraft:smooth_red_sandstone_stairs", + "id" : -176 + }, + { + "name" : "minecraft:shroomlight", + "id" : -230 + }, + { + "name" : "minecraft:stripped_crimson_hyphae", + "id" : -300 + }, + { + "name" : "minecraft:crimson_button", + "id" : -260 + }, + { + "name" : "minecraft:soul_fire", + "id" : -237 + }, + { + "name" : "minecraft:polished_basalt", + "id" : -235 + }, + { + "name" : "minecraft:jungle_button", + "id" : -143 + }, + { + "name" : "minecraft:birch_pressure_plate", + "id" : -151 + }, + { + "name" : "minecraft:stripped_warped_stem", + "id" : -241 + }, + { + "name" : "minecraft:birch_wall_sign", + "id" : -187 + }, + { + "name" : "minecraft:jungle_trapdoor", + "id" : -148 + }, + { + "name" : "minecraft:item.kelp", + "id" : -138 + }, + { + "name" : "minecraft:birch_button", + "id" : -141 + }, + { + "name" : "minecraft:birch_trapdoor", + "id" : -146 + }, + { + "name" : "minecraft:bubble_column", + "id" : -160 + }, + { + "name" : "minecraft:polished_granite_stairs", + "id" : -172 + }, + { + "name" : "minecraft:polished_andesite_stairs", + "id" : -174 + }, + { + "name" : "minecraft:end_brick_stairs", + "id" : -178 + }, + { + "name" : "minecraft:spruce_wall_sign", + "id" : -182 + }, + { + "name" : "minecraft:chiseled_polished_blackstone", + "id" : -279 + }, + { + "name" : "minecraft:birch_standing_sign", + "id" : -186 + }, + { + "name" : "minecraft:darkoak_standing_sign", + "id" : -192 + }, + { + "name" : "minecraft:darkoak_wall_sign", + "id" : -193 + }, + { + "name" : "minecraft:lit_smoker", + "id" : -199 + }, + { + "name" : "minecraft:item.campfire", + "id" : -209 + }, + { + "name" : "minecraft:bee_nest", + "id" : -218 + }, + { + "name" : "minecraft:warped_fence_gate", + "id" : -259 + }, + { + "name" : "minecraft:warped_stem", + "id" : -226 + }, + { + "name" : "minecraft:blackstone_double_slab", + "id" : -283 + }, + { + "name" : "minecraft:target", + "id" : -239 + }, + { + "name" : "minecraft:crimson_trapdoor", + "id" : -246 + }, + { + "name" : "minecraft:polished_blackstone_brick_wall", + "id" : -278 + }, + { + "name" : "minecraft:warped_standing_sign", + "id" : -251 + }, + { + "name" : "minecraft:warped_stairs", + "id" : -255 + }, + { + "name" : "minecraft:crimson_fence", + "id" : -256 + }, + { + "name" : "minecraft:warped_pressure_plate", + "id" : -263 + }, + { + "name" : "minecraft:soul_lantern", + "id" : -269 + }, + { + "name" : "minecraft:blackstone_wall", + "id" : -277 + }, + { + "name" : "minecraft:polished_blackstone", + "id" : -291 + }, + { + "name" : "minecraft:polished_blackstone_stairs", + "id" : -292 + }, + { + "name" : "minecraft:polished_blackstone_pressure_plate", + "id" : -295 + }, + { + "name" : "minecraft:warped_hyphae", + "id" : -298 + }, + { + "name" : "minecraft:crimson_hyphae", + "id" : -299 + }, + { + "name" : "minecraft:cracked_nether_bricks", + "id" : -303 + } ] \ 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 index e5347d87..27594915 100644 --- a/connector/src/main/resources/bedrock/legacy_block_ids.json +++ b/connector/src/main/resources/bedrock/legacy_block_ids.json @@ -1,462 +1,555 @@ { - "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:magma": 213, - "minecraft:nether_wart_block": 214, - "minecraft:red_nether_brick": 215, - "minecraft:bone_block": 216, - "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: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: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 index 21989249..3f22c91c 100644 --- a/connector/src/main/resources/bedrock/legacy_item_ids.json +++ b/connector/src/main/resources/bedrock/legacy_item_ids.json @@ -1,229 +1,255 @@ { - "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:composter": 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:nametag": 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: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: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 index 0c79ab2f..feeeda66 100644 Binary files a/connector/src/main/resources/bedrock/runtime_block_states.dat and b/connector/src/main/resources/bedrock/runtime_block_states.dat differ diff --git a/connector/src/main/resources/config.yml b/connector/src/main/resources/config.yml index e0e0771d..91f95e6e 100644 --- a/connector/src/main/resources/config.yml +++ b/connector/src/main/resources/config.yml @@ -78,14 +78,14 @@ allow-third-party-ears: false # Allow a fake cooldown indicator to be sent. Bedrock players do not see a cooldown as they still use 1.8 combat show-cooldown: true -# The default locale if we dont have the one the client requested -default-locale: en_us +# The default locale if we dont have the one the client requested. Uncomment to not use the default system language. +# default-locale: en_us # Configures if chunk caching should be enabled or not. This keeps an individual # record of each block the client loads in. While this feature does allow for a few # things such as block break animations to show up in creative mode and among others, # it is HIGHLY recommended you disable this on a production environment as it can eat -# up a lot of RAM. However, when using the Bukkit version of Geyser, support for features +# up a lot of RAM. However, when using the Spigot version of Geyser, support for features # or implementations this allows is automatically enabled without the additional caching as # Geyser has direct access to the server itself. cache-chunks: false diff --git a/connector/src/main/resources/languages b/connector/src/main/resources/languages new file mode 160000 index 00000000..fc8f930a --- /dev/null +++ b/connector/src/main/resources/languages @@ -0,0 +1 @@ +Subproject commit fc8f930a238a375c7e3be6e5c7ea1720b61d0cca diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index a67cc940..848f16c2 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit a67cc940c0d47874c833ffeb58f38e33eabfcc33 +Subproject commit 848f16c2d5441dfa2bd0768e5b75f903e623d2d9 diff --git a/pom.xml b/pom.xml index 3e119eb1..acfdc3d6 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,10 @@ viaversion-repo https://repo.viaversion.com + + sonatype + https://oss.sonatype.org/content/repositories/snapshots/ +