diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..b0e07f6e3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,26 @@ +--- +name: Bug report +about: Create a bug report so we can fix it + +--- + +**Describe the bug, provide any errors** +A clear and concise description of what the bug is. Can you https://hastebin.com the error? + +**How can we reproduce it?** +Steps to reproduce the behavior: +1. Login on 1.12' +2. Click on '....' +3. The '....' is displayed wrong + +**Expected behaviour** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**ViaVersion Dump:** +- Type /viaversion dump, and put the link here. + +**Additional server info** +Do you use a proxy (eg. BungeeCord)? What software do you use and what plugins? diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..8bbc2c4fd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for ViaVersion + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Which versions is this for?** +Does the feature apply to any specific versions? If so put them here. diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index 80bbbc13c..000000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,11 +0,0 @@ -### What is the output link of /viaversion dump? - - -### Are you using any additional software like BungeeCord? If so, what software and version? (Please list your plugins as well) - - -### How does this error happen? login? Using an item? - - -### Is there an error in the console? Use pastebin.com. Is there a kick message? - diff --git a/bukkit/pom.xml b/bukkit/pom.xml index 59b61c638..d99698d30 100644 --- a/bukkit/pom.xml +++ b/bukkit/pom.xml @@ -5,7 +5,7 @@ viaversion-parent us.myles - 1.6.1-18w46a + 2.0.0-18w46a 4.0.0 diff --git a/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java b/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java index d4c326384..f597c65c1 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/ViaVersionPlugin.java @@ -34,7 +34,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform { private boolean lateBind = false; private boolean protocolSupport = false; @Getter - private BukkitConfigAPI conf; + private BukkitViaConfig conf; @Getter private ViaAPI api = new BukkitViaAPI(this); private List queuedTasks = new ArrayList<>(); @@ -51,7 +51,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform { .loader(new BukkitViaLoader(this)) .build()); // Config magic - conf = new BukkitConfigAPI(); + conf = new BukkitViaConfig(); // For compatibility ViaVersion.setInstance(this); diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitConfigAPI.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaConfig.java similarity index 94% rename from bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitConfigAPI.java rename to bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaConfig.java index 2aea4289e..ff4cf6d00 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitConfigAPI.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/platform/BukkitViaConfig.java @@ -11,10 +11,10 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -public class BukkitConfigAPI extends Config implements ViaVersionConfig { - private static List UNSUPPORTED = Arrays.asList("bungee-ping-interval", "bungee-ping-save", "bungee-servers"); +public class BukkitViaConfig extends Config implements ViaVersionConfig { + private static List UNSUPPORTED = Arrays.asList("bungee-ping-interval", "bungee-ping-save", "bungee-servers", "velocity-ping-interval", "velocity-ping-save", "velocity-servers"); - public BukkitConfigAPI() { + public BukkitViaConfig() { super(new File(((ViaVersionPlugin) Via.getPlatform()).getDataFolder(), "config.yml")); // Load config reloadConfig(); @@ -192,7 +192,7 @@ public class BukkitConfigAPI extends Config implements ViaVersionConfig { @Override public URL getDefaultConfigURL() { - return BukkitConfigAPI.class.getClassLoader().getResource("assets/viaversion/config.yml"); + return BukkitViaConfig.class.getClassLoader().getResource("assets/viaversion/config.yml"); } @Override diff --git a/bungee/pom.xml b/bungee/pom.xml index 89edea773..df7a48db5 100644 --- a/bungee/pom.xml +++ b/bungee/pom.xml @@ -5,7 +5,7 @@ viaversion-parent us.myles - 1.6.1-18w46a + 2.0.0-18w46a 4.0.0 diff --git a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java index 97e3a9c75..72142e311 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java +++ b/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java @@ -31,13 +31,13 @@ import java.util.concurrent.TimeUnit; public class BungeePlugin extends Plugin implements ViaPlatform, Listener { private BungeeViaAPI api; - private BungeeConfigAPI config; + private BungeeViaConfig config; private BungeeCommandHandler commandHandler; @Override public void onLoad() { api = new BungeeViaAPI(); - config = new BungeeConfigAPI(getDataFolder()); + config = new BungeeViaConfig(getDataFolder()); commandHandler = new BungeeCommandHandler(); ProxyServer.getInstance().getPluginManager().registerCommand(this, new BungeeCommand(commandHandler)); // Init platform @@ -134,7 +134,7 @@ public class BungeePlugin extends Plugin implements ViaPlatform, Listener { } @Override - public BungeeConfigAPI getConf() { + public BungeeViaConfig getConf() { return config; } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/subs/ProbeSubCmd.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/subs/ProbeSubCmd.java index fda215417..a6184efa6 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/subs/ProbeSubCmd.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/commands/subs/ProbeSubCmd.java @@ -3,7 +3,7 @@ package us.myles.ViaVersion.bungee.commands.subs; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.command.ViaSubCommand; -import us.myles.ViaVersion.bungee.platform.BungeeConfigAPI; +import us.myles.ViaVersion.bungee.platform.BungeeViaConfig; import us.myles.ViaVersion.bungee.service.ProtocolDetectorService; public class ProbeSubCmd extends ViaSubCommand { @@ -15,7 +15,7 @@ public class ProbeSubCmd extends ViaSubCommand { @Override public String description() { return "Forces ViaVersion to scan server protocol versions " + - (((BungeeConfigAPI) Via.getConfig()).getBungeePingInterval() == -1 ? + (((BungeeViaConfig) Via.getConfig()).getBungeePingInterval() == -1 ? "" : "(Also happens at an interval)"); } diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeConfigAPI.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaConfig.java similarity index 96% rename from bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeConfigAPI.java rename to bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaConfig.java index 5b773185d..18c0c2510 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeConfigAPI.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/platform/BungeeViaConfig.java @@ -9,10 +9,10 @@ import java.io.File; import java.net.URL; import java.util.*; -public class BungeeConfigAPI extends Config implements ViaVersionConfig { - private static List UNSUPPORTED = Arrays.asList("nms-player-ticking", "item-cache", "anti-xray-patch", "quick-move-action-fix"); +public class BungeeViaConfig extends Config implements ViaVersionConfig { + private static List UNSUPPORTED = Arrays.asList("nms-player-ticking", "item-cache", "anti-xray-patch", "quick-move-action-fix", "velocity-ping-interval", "velocity-ping-save", "velocity-servers"); - public BungeeConfigAPI(File configFile) { + public BungeeViaConfig(File configFile) { super(new File(configFile, "config.yml")); // Load config reloadConfig(); @@ -20,7 +20,7 @@ public class BungeeConfigAPI extends Config implements ViaVersionConfig { @Override public URL getDefaultConfigURL() { - return BungeeConfigAPI.class.getClassLoader().getResource("assets/viaversion/config.yml"); + return BungeeViaConfig.class.getClassLoader().getResource("assets/viaversion/config.yml"); } @Override diff --git a/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java b/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java index e3aa9defe..6f5f6a909 100644 --- a/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java +++ b/bungee/src/main/java/us/myles/ViaVersion/bungee/service/ProtocolDetectorService.java @@ -6,7 +6,7 @@ import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.config.ServerInfo; import us.myles.ViaVersion.BungeePlugin; import us.myles.ViaVersion.api.Via; -import us.myles.ViaVersion.bungee.platform.BungeeConfigAPI; +import us.myles.ViaVersion.bungee.platform.BungeeViaConfig; import us.myles.ViaVersion.bungee.providers.BungeeVersionProvider; import java.util.HashMap; @@ -26,7 +26,7 @@ public class ProtocolDetectorService implements Runnable { public static Integer getProtocolId(String serverName) { // Step 1. Check Config - Map servers = ((BungeeConfigAPI) Via.getConfig()).getBungeeServerProtocols(); + Map servers = ((BungeeViaConfig) Via.getConfig()).getBungeeServerProtocols(); Integer protocol = servers.get(serverName); if (protocol != null) { return protocol; @@ -58,19 +58,22 @@ public class ProtocolDetectorService implements Runnable { @Override public void done(ServerPing serverPing, Throwable throwable) { if (throwable == null && serverPing != null && serverPing.getVersion() != null) { - detectedProtocolIds.put(key, serverPing.getVersion().getProtocol()); - if (((BungeeConfigAPI) Via.getConfig()).isBungeePingSave()) { - Map servers = ((BungeeConfigAPI) Via.getConfig()).getBungeeServerProtocols(); - Integer protocol = servers.get(key); - if (protocol != null && protocol == serverPing.getVersion().getProtocol()) { - return; + // Ensure protocol is positive, some services will return -1 + if (serverPing.getVersion().getProtocol() > 0) { + detectedProtocolIds.put(key, serverPing.getVersion().getProtocol()); + if (((BungeeViaConfig) Via.getConfig()).isBungeePingSave()) { + Map servers = ((BungeeViaConfig) Via.getConfig()).getBungeeServerProtocols(); + Integer protocol = servers.get(key); + if (protocol != null && protocol == serverPing.getVersion().getProtocol()) { + return; + } + // Ensure we're the only ones writing to the config + synchronized (Via.getPlatform().getConfigurationProvider()) { + servers.put(key, serverPing.getVersion().getProtocol()); + } + // Save + Via.getPlatform().getConfigurationProvider().saveConfig(); } - // Ensure we're the only ones writing to the config - synchronized (Via.getPlatform().getConfigurationProvider()) { - servers.put(key, serverPing.getVersion().getProtocol()); - } - // Save - Via.getPlatform().getConfigurationProvider().saveConfig(); } } } diff --git a/common/pom.xml b/common/pom.xml index 8414d7dc2..549004b0b 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -5,7 +5,7 @@ viaversion-parent us.myles - 1.6.1-18w46a + 2.0.0-18w46a 4.0.0 @@ -17,7 +17,7 @@ org.yaml snakeyaml 1.18 - provided + compile \ No newline at end of file diff --git a/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java b/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java index ffc4b4a58..566240937 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java +++ b/common/src/main/java/us/myles/ViaVersion/api/data/UserConnection.java @@ -18,6 +18,8 @@ import us.myles.ViaVersion.util.PipelineUtil; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; @Data public class UserConnection { @@ -36,7 +38,7 @@ public class UserConnection { // Used for handling warnings (over time) private int secondsObserved = 0; private int warnings = 0; - + private ReadWriteLock velocityLock = new ReentrantReadWriteLock(); public UserConnection(Channel channel) { this.channel = channel; @@ -108,7 +110,8 @@ public class UserConnection { */ public ChannelFuture sendRawPacketFuture(final ByteBuf packet) { final ChannelHandler handler = channel.pipeline().get(Via.getManager().getInjector().getEncoderName()); - return channel.pipeline().context(handler).writeAndFlush(packet); + ChannelFuture future = channel.pipeline().context(handler).writeAndFlush(packet); + return future; } /** @@ -218,7 +221,8 @@ public class UserConnection { } buf.writeBytes(packet); packet.release(); - final ChannelHandlerContext context = PipelineUtil.getPreviousContext(Via.getManager().getInjector().getDecoderName(), getChannel().pipeline()); + final ChannelHandlerContext context = PipelineUtil + .getPreviousContext(Via.getManager().getInjector().getDecoderName(), getChannel().pipeline()); if (currentThread) { if (context != null) { context.fireChannelRead(buf); diff --git a/common/src/main/java/us/myles/ViaVersion/commands/ViaCommandHandler.java b/common/src/main/java/us/myles/ViaVersion/commands/ViaCommandHandler.java index c6afc0b6e..5610e2a50 100644 --- a/common/src/main/java/us/myles/ViaVersion/commands/ViaCommandHandler.java +++ b/common/src/main/java/us/myles/ViaVersion/commands/ViaCommandHandler.java @@ -74,7 +74,7 @@ public abstract class ViaCommandHandler implements ViaVersionCommand { //SubCommands tabcomplete if (args.length == 1) { - if (!args[0].equals("")) { + if (!args[0].isEmpty()) { for (ViaSubCommand sub : allowed) if (sub.name().toLowerCase().startsWith(args[0].toLowerCase())) output.add(sub.name()); diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13_1to1_13/Protocol1_13_1To1_13.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13_1to1_13/Protocol1_13_1To1_13.java index ff162030d..e06278f9d 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13_1to1_13/Protocol1_13_1To1_13.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13_1to1_13/Protocol1_13_1To1_13.java @@ -90,6 +90,22 @@ public class Protocol1_13_1To1_13 extends Protocol { } }); + // Set cooldown + registerOutgoing(State.PLAY, 0x18, 0x18, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // Item + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.set(Type.VAR_INT, 0, + InventoryPackets.getNewItemId(wrapper.get(Type.VAR_INT, 0)) + ); + } + }); + } + }); + // Boss bar registerOutgoing(State.PLAY, 0x0C, 0x0C, new PacketRemapper() { @Override diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13_2to1_13_1/Protocol1_13_2To1_13_1.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13_2to1_13_1/Protocol1_13_2To1_13_1.java index bd01d958c..c6750ad01 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13_2to1_13_1/Protocol1_13_2To1_13_1.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13_2to1_13_1/Protocol1_13_2To1_13_1.java @@ -22,14 +22,13 @@ public class Protocol1_13_2To1_13_1 extends Protocol { WorldPackets.register(this); EntityPackets.register(this); - //Edit Book - registerIncoming(State.PLAY, 0x0B, 0x0B, new PacketRemapper() { - @Override - public void registerMap() { - map(Type.FLAT_ITEM, Type.FLAT_VAR_INT_ITEM); - map(Type.BOOLEAN); - } - }); + //Edit Book + registerIncoming(State.PLAY, 0x0B, 0x0B, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.FLAT_VAR_INT_ITEM, Type.FLAT_ITEM); + } + }); // Advancements registerOutgoing(State.PLAY, 0x51, 0x51, new PacketRemapper() { diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/ChatRewriter.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/ChatRewriter.java index 047cecac6..d6e888402 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/ChatRewriter.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/ChatRewriter.java @@ -4,7 +4,9 @@ import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.api.chat.TranslatableComponent; import net.md_5.bungee.chat.ComponentSerializer; +import us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data.MappingData; import java.util.ArrayList; import java.util.regex.Matcher; @@ -115,4 +117,43 @@ public class ChatRewriter { public static String jsonTextToLegacy(String value) { return TextComponent.toLegacyText(ComponentSerializer.parse(value)); } + + public static String processTranslate(String value) { + BaseComponent[] components = ComponentSerializer.parse(value); + for (BaseComponent component : components) { + processTranslate(component); + } + if (components.length == 1) { + return ComponentSerializer.toString(components[0]); + } else { + return ComponentSerializer.toString(components); + } + } + + private static void processTranslate(BaseComponent component) { + if (component instanceof TranslatableComponent) { + String oldTranslate = ((TranslatableComponent) component).getTranslate(); + String newTranslate; + newTranslate = MappingData.translateMapping.get(oldTranslate); + if (newTranslate == null) MappingData.mojangTranslation.get(oldTranslate); + if (newTranslate != null) { + ((TranslatableComponent) component).setTranslate(newTranslate); + } + if (((TranslatableComponent) component).getWith() != null) { + for (BaseComponent baseComponent : ((TranslatableComponent) component).getWith()) { + processTranslate(baseComponent); + } + } + } + if (component.getHoverEvent() != null) { + for (BaseComponent baseComponent : component.getHoverEvent().getValue()) { + processTranslate(baseComponent); + } + } + if (component.getExtra() != null) { + for (BaseComponent baseComponent : component.getExtra()) { + processTranslate(baseComponent); + } + } + } } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/Protocol1_13To1_12_2.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/Protocol1_13To1_12_2.java index ca501ec8f..3ad9c9ab3 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/Protocol1_13To1_12_2.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/Protocol1_13To1_12_2.java @@ -47,77 +47,78 @@ public class Protocol1_13To1_12_2 extends Protocol { } }; - public static final PacketHandler SEND_DECLARE_COMMANDS_AND_TAGS = new PacketHandler() { // *insert here a good name* - @Override - public void handle(PacketWrapper w) throws Exception { - // Send fake declare commands - w.create(0x11, new ValueCreator() { + public static final PacketHandler SEND_DECLARE_COMMANDS_AND_TAGS = + new PacketHandler() { // *insert here a good name* @Override - public void write(PacketWrapper wrapper) { - wrapper.write(Type.VAR_INT, 2); // Size - // Write root node - wrapper.write(Type.VAR_INT, 0); // Mark as command - wrapper.write(Type.VAR_INT, 1); // 1 child - wrapper.write(Type.VAR_INT, 1); // Child is at 1 + public void handle(PacketWrapper w) throws Exception { + // Send fake declare commands + w.create(0x11, new ValueCreator() { + @Override + public void write(PacketWrapper wrapper) { + wrapper.write(Type.VAR_INT, 2); // Size + // Write root node + wrapper.write(Type.VAR_INT, 0); // Mark as command + wrapper.write(Type.VAR_INT, 1); // 1 child + wrapper.write(Type.VAR_INT, 1); // Child is at 1 - // Write arg node - wrapper.write(Type.VAR_INT, 0x02 | 0x04 | 0x10); // Mark as command - wrapper.write(Type.VAR_INT, 0); // No children - // Extra data - wrapper.write(Type.STRING, "args"); // Arg name - wrapper.write(Type.STRING, "brigadier:string"); - wrapper.write(Type.VAR_INT, 2); // Greedy - wrapper.write(Type.STRING, "minecraft:ask_server"); // Ask server + // Write arg node + wrapper.write(Type.VAR_INT, 0x02 | 0x04 | 0x10); // Mark as command + wrapper.write(Type.VAR_INT, 0); // No children + // Extra data + wrapper.write(Type.STRING, "args"); // Arg name + wrapper.write(Type.STRING, "brigadier:string"); + wrapper.write(Type.VAR_INT, 2); // Greedy + wrapper.write(Type.STRING, "minecraft:ask_server"); // Ask server - wrapper.write(Type.VAR_INT, 0); // Root node index + wrapper.write(Type.VAR_INT, 0); // Root node index + } + }).send(Protocol1_13To1_12_2.class); + + // Send tags packet + w.create(0x55, new ValueCreator() { + @Override + public void write(PacketWrapper wrapper) throws Exception { + wrapper.write(Type.VAR_INT, MappingData.blockTags.size()); // block tags + for (Map.Entry tag : MappingData.blockTags.entrySet()) { + wrapper.write(Type.STRING, tag.getKey()); + wrapper.write(Type.VAR_INT_ARRAY, tag.getValue().clone()); + } + wrapper.write(Type.VAR_INT, MappingData.itemTags.size()); // item tags + for (Map.Entry tag : MappingData.itemTags.entrySet()) { + wrapper.write(Type.STRING, tag.getKey()); + wrapper.write(Type.VAR_INT_ARRAY, tag.getValue().clone()); + } + wrapper.write(Type.VAR_INT, MappingData.fluidTags.size()); // fluid tags + for (Map.Entry tag : MappingData.fluidTags.entrySet()) { + wrapper.write(Type.STRING, tag.getKey()); + wrapper.write(Type.VAR_INT_ARRAY, tag.getValue().clone()); + } + } + }).send(Protocol1_13To1_12_2.class); } - }).send(Protocol1_13To1_12_2.class); - - // Send tags packet - w.create(0x55, new ValueCreator() { - @Override - public void write(PacketWrapper wrapper) throws Exception { - wrapper.write(Type.VAR_INT, MappingData.blockTags.size()); // block tags - for (Map.Entry tag : MappingData.blockTags.entrySet()) { - wrapper.write(Type.STRING, tag.getKey()); - wrapper.write(Type.VAR_INT_ARRAY, tag.getValue().clone()); - } - wrapper.write(Type.VAR_INT, MappingData.itemTags.size()); // item tags - for (Map.Entry tag : MappingData.itemTags.entrySet()) { - wrapper.write(Type.STRING, tag.getKey()); - wrapper.write(Type.VAR_INT_ARRAY, tag.getValue().clone()); - } - wrapper.write(Type.VAR_INT, MappingData.fluidTags.size()); // fluid tags - for (Map.Entry tag : MappingData.fluidTags.entrySet()) { - wrapper.write(Type.STRING, tag.getKey()); - wrapper.write(Type.VAR_INT_ARRAY, tag.getValue().clone()); - } - } - }).send(Protocol1_13To1_12_2.class); - } - }; + }; // These are arbitrary rewrite values, it just needs an invalid color code character. - protected static EnumMap SCOREBOARD_TEAM_NAME_REWRITE = new EnumMap(ChatColor.class) {{ - put(ChatColor.BLACK, ChatColor.COLOR_CHAR + "g"); - put(ChatColor.DARK_BLUE, ChatColor.COLOR_CHAR + "h"); - put(ChatColor.DARK_GREEN, ChatColor.COLOR_CHAR + "i"); - put(ChatColor.DARK_AQUA, ChatColor.COLOR_CHAR + "j"); - put(ChatColor.DARK_RED, ChatColor.COLOR_CHAR + "p"); - put(ChatColor.DARK_PURPLE, ChatColor.COLOR_CHAR + "q"); - put(ChatColor.GOLD, ChatColor.COLOR_CHAR + "s"); - put(ChatColor.GRAY, ChatColor.COLOR_CHAR + "t"); - put(ChatColor.DARK_GRAY, ChatColor.COLOR_CHAR + "u"); - put(ChatColor.BLUE, ChatColor.COLOR_CHAR + "v"); - put(ChatColor.GREEN, ChatColor.COLOR_CHAR + "w"); - put(ChatColor.AQUA, ChatColor.COLOR_CHAR + "x"); - put(ChatColor.RED, ChatColor.COLOR_CHAR + "y"); - put(ChatColor.LIGHT_PURPLE, ChatColor.COLOR_CHAR + "z"); - put(ChatColor.YELLOW, ChatColor.COLOR_CHAR + "!"); - put(ChatColor.WHITE, ChatColor.COLOR_CHAR + "?"); - }}; + protected static EnumMap SCOREBOARD_TEAM_NAME_REWRITE = new EnumMap<>(ChatColor.class); + // @formatter:on static { + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.BLACK, 'g'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.DARK_BLUE, 'h'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.DARK_GREEN, 'i'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.DARK_AQUA, 'j'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.DARK_RED, 'p'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.DARK_PURPLE, 'q'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.GOLD, 's'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.GRAY, 't'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.DARK_GRAY, 'u'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.BLUE, 'v'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.GREEN, 'w'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.AQUA, 'x'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.RED, 'y'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.LIGHT_PURPLE, 'z'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.YELLOW, '!'); + SCOREBOARD_TEAM_NAME_REWRITE.put(ChatColor.WHITE, '?'); MappingData.init(); } @@ -130,6 +131,19 @@ public class Protocol1_13To1_12_2 extends Protocol { // Outgoing packets + registerOutgoing(State.LOGIN, 0x0, 0x0, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.STRING); + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.set(Type.STRING, 0, ChatRewriter.processTranslate(wrapper.get(Type.STRING, 0))); + } + }); + } + }); + registerOutgoing(State.STATUS, 0x00, 0x00, new PacketRemapper() { @Override public void registerMap() { @@ -169,7 +183,36 @@ public class Protocol1_13To1_12_2 extends Protocol { } }); - registerOutgoing(State.PLAY, 0xF, 0xE); + // Boss bar + registerOutgoing(State.PLAY, 0xC, 0xC, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.UUID); + map(Type.VAR_INT); + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int action = wrapper.get(Type.VAR_INT, 0); + if (action == 0 || action == 3) { + wrapper.write(Type.STRING, ChatRewriter.processTranslate(wrapper.read(Type.STRING))); + } + } + }); + } + }); + // Chat message + registerOutgoing(State.PLAY, 0xF, 0xE, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.STRING); + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.set(Type.STRING, 0, ChatRewriter.processTranslate(wrapper.get(Type.STRING, 0))); + } + }); + } + }); // WorldPackets 0x10 -> 0x0F // Tab-Complete @@ -217,13 +260,77 @@ public class Protocol1_13To1_12_2 extends Protocol { // New packet 0x11, declare commands registerOutgoing(State.PLAY, 0x11, 0x12); registerOutgoing(State.PLAY, 0x12, 0x13); - registerOutgoing(State.PLAY, 0x13, 0x14); + // Open window + registerOutgoing(State.PLAY, 0x13, 0x14, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.UNSIGNED_BYTE); // Id + map(Type.STRING); // Window type + map(Type.STRING); // Title + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.set(Type.STRING, 1, ChatRewriter.processTranslate(wrapper.get(Type.STRING, 1))); + } + }); + } + }); // InventoryPackets 0x14 -> 0x15 // InventoryPackets 0x15 -> 0x16 // InventoryPackets 0x16 -> 0x17 - registerOutgoing(State.PLAY, 0x17, 0x18); + // Set cooldown + registerOutgoing(State.PLAY, 0x17, 0x18, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int item = wrapper.read(Type.VAR_INT); + int ticks = wrapper.read(Type.VAR_INT); + wrapper.cancel(); + if (item == 383) { // Spawn egg + for (int i = 0; i < 44; i++) { + Integer newItem = MappingData.oldToNewItems.get(item << 16 | i); + if (newItem != null) { + PacketWrapper packet = wrapper.create(0x18); + packet.write(Type.VAR_INT, newItem); + packet.write(Type.VAR_INT, ticks); + packet.send(Protocol1_13To1_12_2.class); + } else { + break; + } + } + } else { + for (int i = 0; i < 16; i++) { + Integer newItem = MappingData.oldToNewItems.get(item << 4 | i); + if (newItem != null) { + PacketWrapper packet = wrapper.create(0x18); + packet.write(Type.VAR_INT, newItem); + packet.write(Type.VAR_INT, ticks); + packet.send(Protocol1_13To1_12_2.class); + } else { + break; + } + } + } + } + }); + } + }); // WorldPackets 0x18 -> 0x19 - registerOutgoing(State.PLAY, 0x1A, 0x1B); + // Disconnect + registerOutgoing(State.PLAY, 0x1A, 0x1B, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.STRING); + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.set(Type.STRING, 0, ChatRewriter.processTranslate(wrapper.get(Type.STRING, 0))); + } + }); + } + }); registerOutgoing(State.PLAY, 0x1B, 0x1C); // New packet 0x1D - NBT Query registerOutgoing(State.PLAY, 0x1C, 0x1E); @@ -326,7 +433,23 @@ public class Protocol1_13To1_12_2 extends Protocol { } }); registerOutgoing(State.PLAY, 0x2C, 0x2E); - registerOutgoing(State.PLAY, 0x2D, 0x2F); + // Combat event + registerOutgoing(State.PLAY, 0x2D, 0x2F, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // Event + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + if (wrapper.get(Type.VAR_INT, 0) == 2) { // Entity dead + wrapper.passthrough(Type.VAR_INT); // Player id + wrapper.passthrough(Type.INT); // Entity id + wrapper.write(Type.STRING, ChatRewriter.processTranslate(wrapper.read(Type.STRING))); + } + } + }); + } + }); registerOutgoing(State.PLAY, 0x2E, 0x30); // New 0x31 - Face Player registerOutgoing(State.PLAY, 0x2F, 0x32); @@ -480,7 +603,22 @@ public class Protocol1_13To1_12_2 extends Protocol { }); registerOutgoing(State.PLAY, 0x46, 0x49); registerOutgoing(State.PLAY, 0x47, 0x4A); - registerOutgoing(State.PLAY, 0x48, 0x4B); + // Title + registerOutgoing(State.PLAY, 0x48, 0x4B, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.VAR_INT); // Action + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + int action = wrapper.get(Type.VAR_INT, 0); + if (action >= 0 && action <= 2) { + wrapper.write(Type.STRING, ChatRewriter.processTranslate(wrapper.read(Type.STRING))); + } + } + }); + } + }); // New 0x4C - Stop Sound // Sound Effect packet @@ -498,7 +636,21 @@ public class Protocol1_13To1_12_2 extends Protocol { }); } }); - registerOutgoing(State.PLAY, 0x4A, 0x4E); + // Player list header and footer + registerOutgoing(State.PLAY, 0x4A, 0x4E, new PacketRemapper() { + @Override + public void registerMap() { + map(Type.STRING); + map(Type.STRING); + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { + wrapper.set(Type.STRING, 0, ChatRewriter.processTranslate(wrapper.get(Type.STRING, 0))); + wrapper.set(Type.STRING, 1, ChatRewriter.processTranslate(wrapper.get(Type.STRING, 1))); + } + }); + } + }); registerOutgoing(State.PLAY, 0x4B, 0x4F); registerOutgoing(State.PLAY, 0x4C, 0x50); // Advancements @@ -520,8 +672,8 @@ public class Protocol1_13To1_12_2 extends Protocol { // Display data if (wrapper.passthrough(Type.BOOLEAN)) { - wrapper.passthrough(Type.STRING); // Title - wrapper.passthrough(Type.STRING); // Description + wrapper.write(Type.STRING, ChatRewriter.processTranslate(wrapper.read(Type.STRING))); // Title + wrapper.write(Type.STRING, ChatRewriter.processTranslate(wrapper.read(Type.STRING))); // Description Item icon = wrapper.read(Type.ITEM); InventoryPackets.toClient(icon); wrapper.write(Type.FLAT_ITEM, icon); // Translate item to flat item @@ -931,14 +1083,13 @@ public class Protocol1_13To1_12_2 extends Protocol { // will just send colour as 'invisible' character if (ChatColor.stripColor(name).length() == 0) { StringBuilder newName = new StringBuilder(); - for (int i = 0; i < name.length() / 2; i++) { - ChatColor color = ChatColor.getByChar(name.charAt(i * 2 + 1)); - String rewrite = SCOREBOARD_TEAM_NAME_REWRITE.get(color); - if (rewrite != null) { // just in case, should never happen - newName.append(rewrite); - } else { - newName.append(name); + for (int i = 1; i < name.length(); i += 2) { + char colorChar = name.charAt(i); + Character rewrite = SCOREBOARD_TEAM_NAME_REWRITE.get(ChatColor.getByChar(colorChar)); + if (rewrite == null) { + rewrite = colorChar; } + newName.append(ChatColor.COLOR_CHAR).append(rewrite); } name = newName.toString(); } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/data/MappingData.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/data/MappingData.java index 6ecbd93c9..c9f572aa1 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/data/MappingData.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/data/MappingData.java @@ -2,15 +2,19 @@ package us.myles.ViaVersion.protocols.protocol1_13to1_12_2.data; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; +import com.google.common.io.CharStreams; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.util.GsonUtil; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -21,6 +25,8 @@ public class MappingData { public static Map itemTags = new HashMap<>(); public static Map fluidTags = new HashMap<>(); public static BiMap oldEnchantmentsIds = HashBiMap.create(); + public static Map translateMapping = new HashMap<>(); + public static Map mojangTranslation = new HashMap<>(); public static EnchantmentMappings enchantmentMappings; public static SoundMappings soundMappings; public static BlockMappings blockMappings; @@ -42,6 +48,38 @@ public class MappingData { enchantmentMappings = new EnchantmentMappingByteArray(mapping1_12.getAsJsonObject("enchantments"), mapping1_13.getAsJsonObject("enchantments")); Via.getPlatform().getLogger().info("Loading 1.12.2 -> 1.13 sound mapping..."); soundMappings = new SoundMappingShortArray(mapping1_12.getAsJsonArray("sounds"), mapping1_13.getAsJsonArray("sounds")); + Via.getPlatform().getLogger().info("Loading translation mappping"); + translateMapping = new HashMap<>(); + Map translateData = GsonUtil.getGson().fromJson( + new InputStreamReader( + MappingData.class.getClassLoader() + .getResourceAsStream("assets/viaversion/data/mapping-lang-1.12-1.13.json") + ), + (new TypeToken>(){}).getType()); + try { + String[] lines; + try (Reader reader = new InputStreamReader(MappingData.class.getClassLoader() + .getResourceAsStream("mojang-translations/en_US.properties"), StandardCharsets.UTF_8)) { + lines = CharStreams.toString(reader).split("\n"); + } + for (String line : lines) { + if (line.isEmpty()) continue; + String[] keyAndTranslation = line.split("=", 2); + if (keyAndTranslation.length != 2) continue; + String key = keyAndTranslation[0]; + String translation = keyAndTranslation[1]; + if (!translateData.containsKey(key)) { + translateMapping.put(key, translation); + } else { + String dataValue = translateData.get(keyAndTranslation[0]); + if (dataValue != null) { + translateMapping.put(key, dataValue); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } } public static JsonObject loadData(String name) { diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java index c9f33c872..0a70d6747 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_13to1_12_2/packets/InventoryPackets.java @@ -447,7 +447,7 @@ public class InventoryPackets { case "WDL|REQUEST": return "wdl:request"; default: - return old.matches("[0-9a-z_-]+:[0-9a-z_/.-]+") // Identifier regex + return old.matches("([0-9a-z_-]*:)?[0-9a-z_/.-]*") // Identifier regex ? old : "viaversion:legacy/" + BaseEncoding.base32().lowerCase().withPadChar('-').encode( old.getBytes(StandardCharsets.UTF_8)); diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java index 40f593f84..ed3245220 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java @@ -17,6 +17,7 @@ import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.packets.State; import us.myles.ViaVersion.protocols.protocol1_9to1_8.ItemRewriter; import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.api.minecraft.chunks.Chunk1_8; import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.CommandBlockProvider; import us.myles.ViaVersion.protocols.protocol1_9to1_8.sounds.Effect; @@ -121,16 +122,20 @@ public class WorldPackets { @Override public void handle(PacketWrapper wrapper) throws Exception { ClientChunks clientChunks = wrapper.user().get(ClientChunks.class); - Chunk1_8 chunk = (Chunk1_8) wrapper.passthrough(new Chunk1_9to1_8Type(clientChunks)); + Chunk1_9to1_8Type type = new Chunk1_9to1_8Type(clientChunks); + Chunk1_8 chunk = (Chunk1_8) wrapper.read(type); if (chunk.isUnloadPacket()) { wrapper.setId(0x1D); + wrapper.write(Type.INT, chunk.getX()); + wrapper.write(Type.INT, chunk.getZ()); // Remove commandBlocks on chunk unload CommandBlockProvider provider = Via.getManager().getProviders().get(CommandBlockProvider.class); provider.unloadChunk(wrapper.user(), chunk.getX(), chunk.getZ()); + } else { + wrapper.write(type, chunk); + // eat any other data (Usually happens with unload packets) } - - // eat any other data (Usually happens with unload packets) wrapper.read(Type.REMAINING_BYTES); } }); diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/types/Chunk1_9to1_8Type.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/types/Chunk1_9to1_8Type.java index 6693f5ad0..4f2d47b18 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/types/Chunk1_9to1_8Type.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/types/Chunk1_9to1_8Type.java @@ -4,7 +4,6 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import io.netty.buffer.ByteBuf; import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.api.minecraft.chunks.Chunk; -import us.myles.ViaVersion.api.minecraft.chunks.Chunk1_8; import us.myles.ViaVersion.api.minecraft.chunks.ChunkSection; import us.myles.ViaVersion.api.type.PartialType; import us.myles.ViaVersion.api.type.Type; @@ -13,6 +12,7 @@ import us.myles.ViaVersion.api.type.types.version.Types1_8; import us.myles.ViaVersion.api.type.types.version.Types1_9; import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.protocols.protocol1_10to1_9_3.Protocol1_10To1_9_3_4; +import us.myles.ViaVersion.api.minecraft.chunks.Chunk1_8; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks; import java.util.ArrayList; diff --git a/common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java b/common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java index f5bdd51f9..6be8ac0b8 100644 --- a/common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java +++ b/common/src/main/java/us/myles/ViaVersion/util/PipelineUtil.java @@ -5,6 +5,8 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.MessageToByteEncoder; +import io.netty.handler.codec.MessageToMessageDecoder; +import io.netty.handler.codec.MessageToMessageEncoder; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -14,6 +16,7 @@ import java.util.List; public class PipelineUtil { private static Method DECODE_METHOD; private static Method ENCODE_METHOD; + private static Method MTM_DECODE; static { try { @@ -28,6 +31,12 @@ public class PipelineUtil { } catch (NoSuchMethodException e) { e.printStackTrace(); } + try { + MTM_DECODE = MessageToMessageDecoder.class.getDeclaredMethod("decode", ChannelHandlerContext.class, Object.class, List.class); + MTM_DECODE.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } } /** @@ -66,6 +75,16 @@ public class PipelineUtil { } } + public static List callDecode(MessageToMessageDecoder decoder, ChannelHandlerContext ctx, Object msg) throws InvocationTargetException { + List output = new ArrayList<>(); + try { + MTM_DECODE.invoke(decoder, ctx, msg, output); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return output; + } + /** * Check if a stack trace contains a certain exception * diff --git a/common/src/main/resources/assets/viaversion/config.yml b/common/src/main/resources/assets/viaversion/config.yml index 0252d7ffa..7675a477f 100644 --- a/common/src/main/resources/assets/viaversion/config.yml +++ b/common/src/main/resources/assets/viaversion/config.yml @@ -46,6 +46,28 @@ bungee-ping-save: true bungee-servers: {} # #----------------------------------------------------------# +# VELOCITY OPTIONS # +#----------------------------------------------------------# +# +# Velocity allows you to have different server versions inside. +# Instead of you entering all the versions of these servers, we can ping them. +# +# What interval would you like us to ping at? (in seconds) +# Use -1 to disable. +velocity-ping-interval: 60 +# If the above is enabled, should we save the info to the config (in the section below) +velocity-ping-save: true +# To get a servers protocol, ViaVersion will do the following: +# Look for the server in the following section, then look for the last ping if velocity-ping is enabled +# otherwise use default. +# +# The format for the following is: +# servername: protocolversion +# You can find protocol ids on http://wiki.vg/Protocol_version_numbers +# It will fallback to the default option if none found. +velocity-servers: {} +# +#----------------------------------------------------------# # GLOBAL PACKET LIMITER # #----------------------------------------------------------# # diff --git a/common/src/main/resources/assets/viaversion/data/mapping-lang-1.12-1.13.json b/common/src/main/resources/assets/viaversion/data/mapping-lang-1.12-1.13.json new file mode 100644 index 000000000..7fcc2d5c3 --- /dev/null +++ b/common/src/main/resources/assets/viaversion/data/mapping-lang-1.12-1.13.json @@ -0,0 +1,2748 @@ +{ + "language.name": null, + "language.region": null, + "language.code": null, + "gui.done": null, + "gui.cancel": null, + "gui.back": null, + "gui.toTitle": null, + "gui.toMenu": null, + "gui.up": null, + "gui.down": null, + "gui.yes": null, + "gui.no": null, + "gui.none": null, + "gui.all": null, + "gui.recipebook.moreRecipes": null, + "gui.recipebook.toggleRecipes.all": null, + "gui.recipebook.toggleRecipes.craftable": null, + "translation.test.none": null, + "translation.test.complex": null, + "translation.test.escape": null, + "translation.test.invalid": null, + "translation.test.invalid2": null, + "translation.test.args": null, + "translation.test.world": null, + "menu.game": null, + "menu.singleplayer": null, + "menu.multiplayer": null, + "menu.online": null, + "menu.options": null, + "menu.quit": null, + "menu.returnToMenu": null, + "menu.disconnect": null, + "menu.returnToGame": null, + "menu.generatingLevel": null, + "menu.loadingLevel": null, + "menu.generatingTerrain": null, + "menu.convertingLevel": null, + "menu.respawning": null, + "menu.shareToLan": null, + "selectWorld.title": null, + "selectWorld.empty": null, + "selectWorld.world": null, + "selectWorld.select": null, + "selectWorld.create": null, + "selectWorld.recreate": null, + "selectWorld.createDemo": null, + "selectWorld.delete": null, + "selectWorld.edit": null, + "selectWorld.edit.title": null, + "selectWorld.edit.resetIcon": null, + "selectWorld.deleteQuestion": null, + "selectWorld.deleteButton": "selectWorld.delete", + "selectWorld.conversion": null, + "selectWorld.newWorld": null, + "selectWorld.newWorld.copyOf": null, + "selectWorld.enterName": null, + "selectWorld.resultFolder": null, + "selectWorld.enterSeed": null, + "selectWorld.seedInfo": null, + "selectWorld.cheats": null, + "selectWorld.customizeType": null, + "selectWorld.version": null, + "selectWorld.versionUnknown": null, + "selectWorld.versionQuestion": null, + "selectWorld.tooltip.fromNewerVersion1": null, + "selectWorld.tooltip.fromNewerVersion2": null, + "selectWorld.tooltip.snapshot1": null, + "selectWorld.tooltip.snapshot2": null, + "selectWorld.unable_to_load": null, + "selectWorld.load_folder_access": null, + "createWorld.customize.presets": null, + "createWorld.customize.presets.title": null, + "createWorld.customize.presets.select": null, + "createWorld.customize.presets.share": null, + "createWorld.customize.presets.list": null, + "createWorld.customize.flat.title": null, + "createWorld.customize.flat.tile": null, + "createWorld.customize.flat.height": null, + "createWorld.customize.flat.addLayer": null, + "createWorld.customize.flat.editLayer": null, + "createWorld.customize.flat.removeLayer": null, + "createWorld.customize.flat.layer.top": null, + "createWorld.customize.flat.layer": null, + "createWorld.customize.flat.layer.bottom": null, + "createWorld.customize.preset.classic_flat": null, + "createWorld.customize.preset.tunnelers_dream": null, + "createWorld.customize.preset.water_world": null, + "createWorld.customize.preset.overworld": null, + "createWorld.customize.preset.snowy_kingdom": null, + "createWorld.customize.preset.bottomless_pit": null, + "createWorld.customize.preset.desert": null, + "createWorld.customize.preset.redstone_ready": null, + "createWorld.customize.preset.the_void": null, + "createWorld.customize.custom.page0": null, + "createWorld.customize.custom.page1": null, + "createWorld.customize.custom.page2": null, + "createWorld.customize.custom.page3": null, + "createWorld.customize.custom.randomize": null, + "createWorld.customize.custom.prev": null, + "createWorld.customize.custom.next": null, + "createWorld.customize.custom.defaults": null, + "createWorld.customize.custom.confirm1": null, + "createWorld.customize.custom.confirm2": null, + "createWorld.customize.custom.confirmTitle": null, + "createWorld.customize.custom.mainNoiseScaleX": null, + "createWorld.customize.custom.mainNoiseScaleY": null, + "createWorld.customize.custom.mainNoiseScaleZ": null, + "createWorld.customize.custom.depthNoiseScaleX": null, + "createWorld.customize.custom.depthNoiseScaleZ": null, + "createWorld.customize.custom.depthNoiseScaleExponent": null, + "createWorld.customize.custom.baseSize": null, + "createWorld.customize.custom.coordinateScale": null, + "createWorld.customize.custom.heightScale": null, + "createWorld.customize.custom.stretchY": null, + "createWorld.customize.custom.upperLimitScale": null, + "createWorld.customize.custom.lowerLimitScale": null, + "createWorld.customize.custom.biomeDepthWeight": null, + "createWorld.customize.custom.biomeDepthOffset": null, + "createWorld.customize.custom.biomeScaleWeight": null, + "createWorld.customize.custom.biomeScaleOffset": null, + "createWorld.customize.custom.seaLevel": null, + "createWorld.customize.custom.useCaves": null, + "createWorld.customize.custom.useStrongholds": null, + "createWorld.customize.custom.useVillages": null, + "createWorld.customize.custom.useMineShafts": null, + "createWorld.customize.custom.useTemples": null, + "createWorld.customize.custom.useMonuments": null, + "createWorld.customize.custom.useMansions": null, + "createWorld.customize.custom.useRavines": null, + "createWorld.customize.custom.useDungeons": null, + "createWorld.customize.custom.dungeonChance": null, + "createWorld.customize.custom.useWaterLakes": null, + "createWorld.customize.custom.waterLakeChance": null, + "createWorld.customize.custom.useLavaLakes": null, + "createWorld.customize.custom.lavaLakeChance": null, + "createWorld.customize.custom.useLavaOceans": null, + "createWorld.customize.custom.fixedBiome": null, + "createWorld.customize.custom.biomeSize": null, + "createWorld.customize.custom.riverSize": null, + "createWorld.customize.custom.size": null, + "createWorld.customize.custom.count": null, + "createWorld.customize.custom.minHeight": null, + "createWorld.customize.custom.maxHeight": null, + "createWorld.customize.custom.center": null, + "createWorld.customize.custom.spread": null, + "createWorld.customize.custom.presets.title": null, + "createWorld.customize.custom.presets": "createWorld.customize.presets", + "createWorld.customize.custom.preset.waterWorld": "createWorld.customize.preset.water_world", + "createWorld.customize.custom.preset.isleLand": null, + "createWorld.customize.custom.preset.caveDelight": null, + "createWorld.customize.custom.preset.mountains": null, + "createWorld.customize.custom.preset.drought": null, + "createWorld.customize.custom.preset.caveChaos": null, + "createWorld.customize.custom.preset.goodLuck": null, + "gameMode.survival": null, + "gameMode.creative": null, + "gameMode.adventure": null, + "gameMode.spectator": null, + "gameMode.hardcore": null, + "gameMode.changed": null, + "spectatorMenu.previous_page": "createWorld.customize.custom.prev", + "spectatorMenu.next_page": "createWorld.customize.custom.next", + "spectatorMenu.close": null, + "spectatorMenu.teleport": null, + "spectatorMenu.teleport.prompt": null, + "spectatorMenu.team_teleport": null, + "spectatorMenu.team_teleport.prompt": null, + "spectatorMenu.root.prompt": null, + "selectWorld.gameMode": null, + "selectWorld.gameMode.survival": null, + "selectWorld.gameMode.survival.line1": null, + "selectWorld.gameMode.survival.line2": null, + "selectWorld.gameMode.creative": null, + "selectWorld.gameMode.creative.line1": null, + "selectWorld.gameMode.creative.line2": null, + "selectWorld.gameMode.spectator": null, + "selectWorld.gameMode.spectator.line1": null, + "selectWorld.gameMode.spectator.line2": null, + "selectWorld.gameMode.hardcore": null, + "selectWorld.gameMode.hardcore.line1": null, + "selectWorld.gameMode.hardcore.line2": null, + "selectWorld.gameMode.adventure": null, + "selectWorld.gameMode.adventure.line1": null, + "selectWorld.gameMode.adventure.line2": null, + "selectWorld.moreWorldOptions": null, + "selectWorld.mapFeatures": null, + "selectWorld.mapFeatures.info": null, + "selectWorld.mapType": null, + "selectWorld.mapType.normal": null, + "selectWorld.allowCommands": null, + "selectWorld.hardcoreMode": null, + "selectWorld.hardcoreMode.info": null, + "selectWorld.bonusItems": null, + "generator.default": null, + "generator.flat": null, + "generator.largeBiomes": null, + "generator.amplified": null, + "generator.customized": null, + "generator.debug_all_block_states": null, + "generator.amplified.info": null, + "selectServer.title": null, + "selectServer.empty": "selectWorld.empty", + "selectServer.select": null, + "selectServer.direct": null, + "selectServer.edit": "selectWorld.edit", + "selectServer.delete": "selectWorld.delete", + "selectServer.add": null, + "selectServer.defaultName": null, + "selectServer.deleteQuestion": null, + "selectServer.deleteButton": "selectWorld.delete", + "selectServer.refresh": null, + "selectServer.hiddenAddress": null, + "addServer.title": null, + "addServer.enterName": null, + "addServer.enterIp": null, + "addServer.add": "gui.done", + "addServer.hideAddress": null, + "addServer.resourcePack": null, + "addServer.resourcePack.enabled": null, + "addServer.resourcePack.disabled": null, + "addServer.resourcePack.prompt": null, + "lanServer.title": null, + "lanServer.scanning": null, + "lanServer.start": null, + "lanServer.otherPlayers": null, + "mcoServer.title": null, + "multiplayer.title": null, + "multiplayer.connect": null, + "multiplayer.ipinfo": null, + "multiplayer.texturePrompt.line1": null, + "multiplayer.texturePrompt.line2": null, + "multiplayer.downloadingStats": null, + "multiplayer.stopSleeping": null, + "multiplayer.player.joined": null, + "multiplayer.player.joined.renamed": null, + "multiplayer.player.left": null, + "multiplayer.status.and_more": null, + "multiplayer.status.cancelled": null, + "multiplayer.status.cannot_connect": null, + "multiplayer.status.cannot_resolve": null, + "multiplayer.status.client_out_of_date": null, + "multiplayer.status.no_connection": null, + "multiplayer.status.old": null, + "multiplayer.status.pinging": null, + "multiplayer.status.server_out_of_date": null, + "multiplayer.status.unknown": null, + "multiplayer.status.unrequested": null, + "multiplayer.disconnect.authservers_down": null, + "multiplayer.disconnect.duplicate_login": null, + "multiplayer.disconnect.flying": null, + "multiplayer.disconnect.generic": null, + "multiplayer.disconnect.idling": null, + "multiplayer.disconnect.illegal_characters": null, + "multiplayer.disconnect.invalid_entity_attacked": null, + "multiplayer.disconnect.invalid_player_movement": null, + "multiplayer.disconnect.invalid_vehicle_movement": null, + "multiplayer.disconnect.outdated_client": null, + "multiplayer.disconnect.outdated_server": null, + "multiplayer.disconnect.server_shutdown": null, + "multiplayer.disconnect.slow_login": null, + "multiplayer.disconnect.unverified_username": null, + "chat.cannotSend": null, + "chat.type.text": null, + "chat.type.text.narrate": null, + "chat.type.emote": null, + "chat.type.announcement": null, + "chat.type.admin": null, + "chat.type.advancement.task": null, + "chat.type.advancement.challenge": null, + "chat.type.advancement.goal": null, + "chat.link.confirm": null, + "chat.link.warning": null, + "chat.copy": null, + "chat.link.confirmTrusted": null, + "chat.link.open": null, + "menu.playdemo": null, + "menu.resetdemo": null, + "demo.day.1": null, + "demo.day.2": null, + "demo.day.3": null, + "demo.day.4": null, + "demo.day.5": null, + "demo.day.warning": null, + "demo.reminder": null, + "demo.remainingTime": null, + "demo.demoExpired": null, + "demo.help.movement": null, + "demo.help.movementShort": null, + "demo.help.movementMouse": null, + "demo.help.jump": null, + "demo.help.inventory": null, + "demo.help.title": null, + "demo.help.fullWrapped": null, + "demo.help.buy": null, + "demo.help.later": null, + "connect.connecting": null, + "connect.authorizing": null, + "connect.failed": null, + "disconnect.genericReason": "createWorld.customize.flat.layer", + "disconnect.disconnected": null, + "disconnect.lost": null, + "disconnect.kicked": null, + "disconnect.timeout": null, + "disconnect.closed": null, + "disconnect.loginFailedInfo.serversUnavailable": null, + "disconnect.loginFailedInfo.invalidSession": null, + "disconnect.quitting": "multiplayer.status.quitting", + "disconnect.endOfStream": null, + "disconnect.overflow": null, + "disconnect.spam": null, + "soundCategory.master": null, + "soundCategory.music": null, + "soundCategory.record": null, + "soundCategory.weather": null, + "soundCategory.hostile": null, + "soundCategory.neutral": null, + "soundCategory.player": null, + "soundCategory.block": null, + "soundCategory.ambient": null, + "soundCategory.voice": null, + "record.nowPlaying": null, + "options.off": null, + "options.on": null, + "options.visible": null, + "options.hidden": null, + "options.title": null, + "options.controls": null, + "options.video": null, + "options.language": null, + "options.sounds": null, + "options.sounds.title": null, + "options.languageWarning": null, + "options.videoTitle": null, + "options.customizeTitle": null, + "options.music": "soundCategory.music", + "options.sound": null, + "options.invertMouse": null, + "options.fov": null, + "options.fov.min": "selectWorld.mapType.normal", + "options.fov.max": null, + "options.saturation": null, + "options.gamma": null, + "options.gamma.min": null, + "options.gamma.max": null, + "options.sensitivity": null, + "options.sensitivity.min": null, + "options.sensitivity.max": null, + "options.renderDistance": null, + "options.viewBobbing": null, + "options.ao": null, + "options.ao.off": "options.off", + "options.ao.min": null, + "options.ao.max": null, + "options.anaglyph": null, + "options.chunks": null, + "options.framerate": null, + "options.framerateLimit": null, + "options.framerateLimit.max": null, + "options.difficulty": null, + "options.difficulty.peaceful": null, + "options.difficulty.easy": null, + "options.difficulty.normal": "selectWorld.mapType.normal", + "options.difficulty.hard": null, + "options.difficulty.hardcore": "selectWorld.gameMode.hardcore", + "options.graphics": null, + "options.graphics.fancy": null, + "options.graphics.fast": null, + "options.clouds.fancy": "options.graphics.fancy", + "options.clouds.fast": "options.graphics.fast", + "options.guiScale": null, + "options.guiScale.auto": null, + "options.guiScale.normal": "selectWorld.mapType.normal", + "options.renderClouds": null, + "options.particles": null, + "options.particles.all": "gui.all", + "options.particles.decreased": null, + "options.particles.minimal": null, + "options.multiplayer.title": null, + "options.chat.title": null, + "options.chat.visibility": null, + "options.chat.visibility.full": "options.visible", + "options.chat.visibility.system": null, + "options.chat.visibility.hidden": "options.hidden", + "options.chat.color": null, + "options.chat.opacity": null, + "options.chat.links": null, + "options.chat.links.prompt": null, + "options.chat.scale": null, + "options.chat.width": null, + "options.chat.height.focused": null, + "options.chat.height.unfocused": null, + "options.skinCustomisation": null, + "options.skinCustomisation.title": null, + "options.modelPart.cape": null, + "options.modelPart.hat": null, + "options.modelPart.jacket": null, + "options.modelPart.left_sleeve": null, + "options.modelPart.right_sleeve": null, + "options.modelPart.left_pants_leg": null, + "options.modelPart.right_pants_leg": null, + "options.snooper": null, + "options.snooper.view": null, + "options.snooper.title": null, + "options.snooper.desc": null, + "options.resourcepack": null, + "options.fullscreen": null, + "options.vsync": null, + "options.vbo": null, + "options.touchscreen": null, + "options.reducedDebugInfo": null, + "options.entityShadows": null, + "options.mainHand": null, + "options.mainHand.left": null, + "options.mainHand.right": null, + "options.attackIndicator": null, + "options.attack.crosshair": null, + "options.attack.hotbar": null, + "options.showSubtitles": null, + "options.realmsNotifications": null, + "options.autoJump": null, + "options.narrator": null, + "options.narrator.all": null, + "options.narrator.chat": null, + "options.narrator.system": null, + "options.narrator.notavailable": null, + "options.mipmapLevels": null, + "options.forceUnicodeFont": null, + "narrator.toast.disabled": null, + "narrator.toast.enabled": null, + "difficulty.lock.title": null, + "difficulty.lock.question": null, + "title.oldgl1": null, + "title.oldgl2": null, + "controls.title": null, + "controls.reset": null, + "controls.resetAll": null, + "key.sprint": null, + "key.forward": null, + "key.left": null, + "key.back": null, + "key.right": null, + "key.jump": null, + "key.inventory": null, + "key.drop": null, + "key.swapHands": null, + "key.chat": null, + "key.sneak": null, + "key.playerlist": null, + "key.attack": null, + "key.use": null, + "key.pickItem": null, + "key.mouseButton": "key.mouse", + "key.command": null, + "key.screenshot": null, + "key.togglePerspective": null, + "key.smoothCamera": null, + "key.fullscreen": null, + "key.spectatorOutlines": null, + "key.hotbar.1": null, + "key.hotbar.2": null, + "key.hotbar.3": null, + "key.hotbar.4": null, + "key.hotbar.5": null, + "key.hotbar.6": null, + "key.hotbar.7": null, + "key.hotbar.8": null, + "key.hotbar.9": null, + "key.saveToolbarActivator": null, + "key.loadToolbarActivator": null, + "key.advancements": null, + "key.categories.movement": null, + "key.categories.misc": null, + "key.categories.multiplayer": "menu.multiplayer", + "key.categories.gameplay": null, + "key.categories.ui": null, + "key.categories.inventory": null, + "key.categories.creative": "gameMode.creative", + "resourcePack.openFolder": null, + "resourcePack.title": null, + "resourcePack.available.title": null, + "resourcePack.selected.title": null, + "resourcePack.folderInfo": null, + "resourcePack.incompatible": null, + "resourcePack.incompatible.old": null, + "resourcePack.incompatible.new": null, + "resourcePack.incompatible.confirm.title": null, + "resourcePack.incompatible.confirm.old": null, + "resourcePack.incompatible.confirm.new": null, + "sign.edit": null, + "book.pageIndicator": null, + "book.byAuthor": null, + "book.signButton": null, + "book.editTitle": null, + "book.finalizeButton": null, + "book.finalizeWarning": null, + "book.generation.0": null, + "book.generation.1": null, + "book.generation.2": null, + "book.generation.3": null, + "merchant.deprecated": null, + "tile.air.name": "block.minecraft.air", + "tile.barrier.name": "block.minecraft.barrier", + "tile.stone.stone.name": "block.minecraft.stone", + "tile.stone.granite.name": "block.minecraft.granite", + "tile.stone.graniteSmooth.name": "block.minecraft.polished_granite", + "tile.stone.diorite.name": "block.minecraft.diorite", + "tile.stone.dioriteSmooth.name": "block.minecraft.polished_diorite", + "tile.stone.andesite.name": "block.minecraft.andesite", + "tile.stone.andesiteSmooth.name": "block.minecraft.polished_andesite", + "tile.hayBlock.name": "block.minecraft.hay_block", + "tile.grass.name": "block.minecraft.grass_block", + "tile.dirt.name": "block.minecraft.dirt", + "tile.dirt.default.name": "block.minecraft.dirt", + "tile.dirt.coarse.name": "block.minecraft.coarse_dirt", + "tile.dirt.podzol.name": "block.minecraft.podzol", + "tile.stonebrick.name": "block.minecraft.cobblestone", + "tile.sapling.oak.name": "block.minecraft.oak_sapling", + "tile.sapling.spruce.name": "block.minecraft.spruce_sapling", + "tile.sapling.birch.name": "block.minecraft.birch_sapling", + "tile.sapling.jungle.name": "block.minecraft.jungle_sapling", + "tile.sapling.acacia.name": "block.minecraft.acacia_sapling", + "tile.sapling.big_oak.name": "block.minecraft.dark_oak_sapling", + "tile.deadbush.name": "block.minecraft.dead_bush", + "tile.bedrock.name": "block.minecraft.bedrock", + "tile.water.name": "block.minecraft.water", + "tile.lava.name": "block.minecraft.lava", + "tile.sand.name": "block.minecraft.sand", + "tile.sand.default.name": "block.minecraft.sand", + "tile.sand.red.name": "block.minecraft.red_sand", + "tile.sandStone.name": "block.minecraft.sandstone", + "tile.sandStone.default.name": "block.minecraft.sandstone", + "tile.sandStone.chiseled.name": "block.minecraft.chiseled_sandstone", + "tile.sandStone.smooth.name": "block.minecraft.smooth_sandstone", + "tile.redSandStone.name": "block.minecraft.red_sandstone", + "tile.redSandStone.default.name": "block.minecraft.red_sandstone", + "tile.redSandStone.chiseled.name": "block.minecraft.chiseled_red_sandstone", + "tile.redSandStone.smooth.name": "block.minecraft.smooth_red_sandstone", + "tile.gravel.name": "block.minecraft.gravel", + "tile.oreGold.name": "block.minecraft.gold_ore", + "tile.oreIron.name": "block.minecraft.iron_ore", + "tile.oreCoal.name": "block.minecraft.coal_ore", + "tile.log.oak.name": "block.minecraft.oak_wood", + "tile.log.spruce.name": "block.minecraft.spruce_wood", + "tile.log.birch.name": "block.minecraft.birch_wood", + "tile.log.jungle.name": "block.minecraft.jungle_wood", + "tile.log.acacia.name": "block.minecraft.acacia_wood", + "tile.log.big_oak.name": "block.minecraft.dark_oak_wood", + "tile.leaves.oak.name": "block.minecraft.oak_leaves", + "tile.leaves.spruce.name": "block.minecraft.spruce_leaves", + "tile.leaves.birch.name": "block.minecraft.birch_leaves", + "tile.leaves.jungle.name": "block.minecraft.jungle_leaves", + "tile.leaves.acacia.name": "block.minecraft.acacia_leaves", + "tile.leaves.big_oak.name": "block.minecraft.dark_oak_leaves", + "tile.tallgrass.name": "block.minecraft.grass", + "tile.tallgrass.grass.name": "block.minecraft.grass", + "tile.tallgrass.fern.name": "block.minecraft.fern", + "tile.sponge.dry.name": "block.minecraft.sponge", + "tile.sponge.wet.name": "block.minecraft.wet_sponge", + "tile.glass.name": "block.minecraft.glass", + "tile.stainedGlass.black.name": "block.minecraft.black_stained_glass", + "tile.stainedGlass.red.name": "block.minecraft.red_stained_glass", + "tile.stainedGlass.green.name": "block.minecraft.green_stained_glass", + "tile.stainedGlass.brown.name": "block.minecraft.brown_stained_glass", + "tile.stainedGlass.blue.name": "block.minecraft.blue_stained_glass", + "tile.stainedGlass.purple.name": "block.minecraft.purple_stained_glass", + "tile.stainedGlass.cyan.name": "block.minecraft.cyan_stained_glass", + "tile.stainedGlass.silver.name": "block.minecraft.light_gray_stained_glass", + "tile.stainedGlass.gray.name": "block.minecraft.gray_stained_glass", + "tile.stainedGlass.pink.name": "block.minecraft.pink_stained_glass", + "tile.stainedGlass.lime.name": "block.minecraft.lime_stained_glass", + "tile.stainedGlass.yellow.name": "block.minecraft.yellow_stained_glass", + "tile.stainedGlass.lightBlue.name": "block.minecraft.light_blue_stained_glass", + "tile.stainedGlass.magenta.name": "block.minecraft.magenta_stained_glass", + "tile.stainedGlass.orange.name": "block.minecraft.orange_stained_glass", + "tile.stainedGlass.white.name": "block.minecraft.white_stained_glass", + "tile.thinStainedGlass.black.name": "block.minecraft.black_stained_glass_pane", + "tile.thinStainedGlass.red.name": "block.minecraft.red_stained_glass_pane", + "tile.thinStainedGlass.green.name": "block.minecraft.green_stained_glass_pane", + "tile.thinStainedGlass.brown.name": "block.minecraft.brown_stained_glass_pane", + "tile.thinStainedGlass.blue.name": "block.minecraft.blue_stained_glass_pane", + "tile.thinStainedGlass.purple.name": "block.minecraft.purple_stained_glass_pane", + "tile.thinStainedGlass.cyan.name": "block.minecraft.cyan_stained_glass_pane", + "tile.thinStainedGlass.silver.name": "block.minecraft.light_gray_stained_glass_pane", + "tile.thinStainedGlass.gray.name": "block.minecraft.gray_stained_glass_pane", + "tile.thinStainedGlass.pink.name": "block.minecraft.pink_stained_glass_pane", + "tile.thinStainedGlass.lime.name": "block.minecraft.lime_stained_glass_pane", + "tile.thinStainedGlass.yellow.name": "block.minecraft.yellow_stained_glass_pane", + "tile.thinStainedGlass.lightBlue.name": "block.minecraft.light_blue_stained_glass_pane", + "tile.thinStainedGlass.magenta.name": "block.minecraft.magenta_stained_glass_pane", + "tile.thinStainedGlass.orange.name": "block.minecraft.orange_stained_glass_pane", + "tile.thinStainedGlass.white.name": "block.minecraft.white_stained_glass_pane", + "tile.thinGlass.name": "block.minecraft.glass_pane", + "tile.flower1.dandelion.name": "block.minecraft.dandelion", + "tile.flower2.poppy.name": "block.minecraft.poppy", + "tile.flower2.blueOrchid.name": "block.minecraft.blue_orchid", + "tile.flower2.allium.name": "block.minecraft.allium", + "tile.flower2.houstonia.name": "block.minecraft.azure_bluet", + "tile.flower2.tulipRed.name": "block.minecraft.red_tulip", + "tile.flower2.tulipOrange.name": "block.minecraft.orange_tulip", + "tile.flower2.tulipWhite.name": "block.minecraft.white_tulip", + "tile.flower2.tulipPink.name": "block.minecraft.pink_tulip", + "tile.flower2.oxeyeDaisy.name": "block.minecraft.oxeye_daisy", + "tile.doublePlant.sunflower.name": "block.minecraft.sunflower", + "tile.doublePlant.syringa.name": "block.minecraft.lilac", + "tile.doublePlant.fern.name": "block.minecraft.large_fern", + "tile.doublePlant.rose.name": "block.minecraft.rose_bush", + "tile.doublePlant.paeonia.name": "block.minecraft.peony", + "tile.blockGold.name": "block.minecraft.gold_block", + "tile.blockIron.name": "block.minecraft.iron_block", + "tile.stoneSlab.name": "block.minecraft.stone_slab", + "tile.stoneSlab.stone.name": "block.minecraft.stone_slab", + "tile.stoneSlab.sand.name": "block.minecraft.sandstone_slab", + "tile.stoneSlab.cobble.name": "block.minecraft.cobblestone_slab", + "tile.stoneSlab.netherBrick.name": "block.minecraft.nether_brick_slab", + "tile.stoneSlab.quartz.name": "block.minecraft.quartz_slab", + "tile.stoneSlab2.red_sandstone.name": "block.minecraft.red_sandstone_slab", + "tile.brick.name": "block.minecraft.bricks", + "tile.tnt.name": "block.minecraft.tnt", + "tile.bookshelf.name": "block.minecraft.bookshelf", + "tile.obsidian.name": "block.minecraft.obsidian", + "tile.torch.name": "block.minecraft.torch", + "tile.fire.name": "block.minecraft.fire", + "tile.chest.name": "block.minecraft.chest", + "tile.chestTrap.name": "block.minecraft.trapped_chest", + "tile.redstoneDust.name": "block.minecraft.redstone_wire", + "tile.oreDiamond.name": "block.minecraft.diamond_ore", + "tile.blockCoal.name": "block.minecraft.coal_block", + "tile.blockDiamond.name": "block.minecraft.diamond_block", + "tile.workbench.name": "block.minecraft.crafting_table", + "tile.farmland.name": "block.minecraft.farmland", + "tile.furnace.name": "block.minecraft.furnace", + "tile.sign.name": "book.signButton", + "tile.ladder.name": "block.minecraft.ladder", + "tile.rail.name": "block.minecraft.rail", + "tile.goldenRail.name": "block.minecraft.powered_rail", + "tile.activatorRail.name": "block.minecraft.activator_rail", + "tile.detectorRail.name": "block.minecraft.detector_rail", + "tile.stairsStone.name": "block.minecraft.cobblestone_stairs", + "tile.stairsSandStone.name": "block.minecraft.sandstone_stairs", + "tile.stairsRedSandStone.name": "block.minecraft.red_sandstone_stairs", + "tile.lever.name": "block.minecraft.lever", + "tile.pressurePlateStone.name": "block.minecraft.stone_pressure_plate", + "tile.doorIron.name": "block.minecraft.iron_door", + "tile.oreRedstone.name": "block.minecraft.redstone_ore", + "tile.notGate.name": "block.minecraft.redstone_torch", + "tile.snow.name": "block.minecraft.snow", + "tile.woolCarpet.black.name": "block.minecraft.black_carpet", + "tile.woolCarpet.red.name": "block.minecraft.red_carpet", + "tile.woolCarpet.green.name": "block.minecraft.green_carpet", + "tile.woolCarpet.brown.name": "block.minecraft.brown_carpet", + "tile.woolCarpet.blue.name": "block.minecraft.blue_carpet", + "tile.woolCarpet.purple.name": "block.minecraft.purple_carpet", + "tile.woolCarpet.cyan.name": "block.minecraft.cyan_carpet", + "tile.woolCarpet.silver.name": "block.minecraft.light_gray_carpet", + "tile.woolCarpet.gray.name": "block.minecraft.gray_carpet", + "tile.woolCarpet.pink.name": "block.minecraft.pink_carpet", + "tile.woolCarpet.lime.name": "block.minecraft.lime_carpet", + "tile.woolCarpet.yellow.name": "block.minecraft.yellow_carpet", + "tile.woolCarpet.lightBlue.name": "block.minecraft.light_blue_carpet", + "tile.woolCarpet.magenta.name": "block.minecraft.magenta_carpet", + "tile.woolCarpet.orange.name": "block.minecraft.orange_carpet", + "tile.woolCarpet.white.name": "block.minecraft.white_carpet", + "tile.ice.name": "block.minecraft.ice", + "tile.frostedIce.name": "block.minecraft.frosted_ice", + "tile.icePacked.name": "block.minecraft.packed_ice", + "tile.cactus.name": "block.minecraft.cactus", + "tile.clay.name": "block.minecraft.clay", + "tile.clayHardenedStained.black.name": "block.minecraft.black_terracotta", + "tile.clayHardenedStained.red.name": "block.minecraft.red_terracotta", + "tile.clayHardenedStained.green.name": "block.minecraft.green_terracotta", + "tile.clayHardenedStained.brown.name": "block.minecraft.brown_terracotta", + "tile.clayHardenedStained.blue.name": "block.minecraft.blue_terracotta", + "tile.clayHardenedStained.purple.name": "block.minecraft.purple_terracotta", + "tile.clayHardenedStained.cyan.name": "block.minecraft.cyan_terracotta", + "tile.clayHardenedStained.silver.name": "block.minecraft.light_gray_terracotta", + "tile.clayHardenedStained.gray.name": "block.minecraft.gray_terracotta", + "tile.clayHardenedStained.pink.name": "block.minecraft.pink_terracotta", + "tile.clayHardenedStained.lime.name": "block.minecraft.lime_terracotta", + "tile.clayHardenedStained.yellow.name": "block.minecraft.yellow_terracotta", + "tile.clayHardenedStained.lightBlue.name": "block.minecraft.light_blue_terracotta", + "tile.clayHardenedStained.magenta.name": "block.minecraft.magenta_terracotta", + "tile.clayHardenedStained.orange.name": "block.minecraft.orange_terracotta", + "tile.clayHardenedStained.white.name": "block.minecraft.white_terracotta", + "tile.clayHardened.name": "block.minecraft.terracotta", + "tile.jukebox.name": "block.minecraft.jukebox", + "tile.fence.name": "block.minecraft.oak_fence", + "tile.spruceFence.name": "block.minecraft.spruce_fence", + "tile.birchFence.name": "block.minecraft.birch_fence", + "tile.jungleFence.name": "block.minecraft.jungle_fence", + "tile.darkOakFence.name": "block.minecraft.dark_oak_fence", + "tile.acaciaFence.name": "block.minecraft.acacia_fence", + "tile.fenceGate.name": "block.minecraft.oak_fence_gate", + "tile.spruceFenceGate.name": "block.minecraft.spruce_fence_gate", + "tile.birchFenceGate.name": "block.minecraft.birch_fence_gate", + "tile.jungleFenceGate.name": "block.minecraft.jungle_fence_gate", + "tile.darkOakFenceGate.name": "block.minecraft.dark_oak_fence_gate", + "tile.acaciaFenceGate.name": "block.minecraft.acacia_fence_gate", + "tile.pumpkinStem.name": "block.minecraft.pumpkin_stem", + "tile.pumpkin.name": "block.minecraft.pumpkin", + "tile.litpumpkin.name": "block.minecraft.jack_o_lantern", + "tile.hellrock.name": "block.minecraft.netherrack", + "tile.hellsand.name": "block.minecraft.soul_sand", + "tile.lightgem.name": "block.minecraft.glowstone", + "tile.cloth.black.name": "block.minecraft.black_wool", + "tile.cloth.red.name": "block.minecraft.red_wool", + "tile.cloth.green.name": "block.minecraft.green_wool", + "tile.cloth.brown.name": "block.minecraft.brown_wool", + "tile.cloth.blue.name": "block.minecraft.blue_wool", + "tile.cloth.purple.name": "block.minecraft.purple_wool", + "tile.cloth.cyan.name": "block.minecraft.cyan_wool", + "tile.cloth.silver.name": "block.minecraft.light_gray_wool", + "tile.cloth.gray.name": "block.minecraft.gray_wool", + "tile.cloth.pink.name": "block.minecraft.pink_wool", + "tile.cloth.lime.name": "block.minecraft.lime_wool", + "tile.cloth.yellow.name": "block.minecraft.yellow_wool", + "tile.cloth.lightBlue.name": "block.minecraft.light_blue_wool", + "tile.cloth.magenta.name": "block.minecraft.magenta_wool", + "tile.cloth.orange.name": "block.minecraft.orange_wool", + "tile.cloth.white.name": "block.minecraft.white_wool", + "tile.oreLapis.name": "block.minecraft.lapis_ore", + "tile.blockLapis.name": "block.minecraft.lapis_block", + "tile.dispenser.name": "block.minecraft.dispenser", + "tile.dropper.name": "block.minecraft.dropper", + "tile.musicBlock.name": "block.minecraft.note_block", + "tile.cake.name": "block.minecraft.cake", + "tile.bed.occupied": "block.minecraft.bed.occupied", + "tile.bed.notValid": "block.minecraft.bed.not_valid", + "tile.ironTrapdoor.name": "block.minecraft.iron_trapdoor", + "tile.web.name": "block.minecraft.cobweb", + "tile.stonebricksmooth.name": "block.minecraft.stone_bricks", + "tile.stonebricksmooth.default.name": "block.minecraft.stone_bricks", + "tile.stonebricksmooth.mossy.name": "block.minecraft.mossy_stone_bricks", + "tile.stonebricksmooth.cracked.name": "block.minecraft.cracked_stone_bricks", + "tile.stonebricksmooth.chiseled.name": "block.minecraft.chiseled_stone_bricks", + "tile.pistonBase.name": "block.minecraft.piston", + "tile.pistonStickyBase.name": "block.minecraft.sticky_piston", + "tile.fenceIron.name": "block.minecraft.iron_bars", + "tile.melon.name": "block.minecraft.melon", + "tile.stairsBrick.name": "block.minecraft.brick_stairs", + "tile.stairsStoneBrickSmooth.name": "block.minecraft.stone_brick_stairs", + "tile.vine.name": "block.minecraft.vine", + "tile.netherBrick.name": "item.minecraft.nether_brick", + "tile.netherFence.name": "block.minecraft.nether_brick_fence", + "tile.stairsNetherBrick.name": "block.minecraft.nether_brick_stairs", + "tile.netherStalk.name": "block.minecraft.nether_wart", + "tile.cauldron.name": "block.minecraft.cauldron", + "tile.anvil.name": "block.minecraft.anvil", + "tile.anvil.intact.name": "block.minecraft.anvil", + "tile.whiteStone.name": "block.minecraft.end_stone", + "tile.endPortalFrame.name": "block.minecraft.end_portal", + "tile.mycel.name": "block.minecraft.mycelium", + "tile.waterlily.name": "block.minecraft.lily_pad", + "tile.dragonEgg.name": "block.minecraft.dragon_egg", + "tile.redstoneLight.name": "block.minecraft.redstone_lamp", + "tile.cocoa.name": "block.minecraft.cocoa", + "tile.enderChest.name": "block.minecraft.ender_chest", + "tile.oreEmerald.name": "block.minecraft.emerald_ore", + "tile.blockEmerald.name": "block.minecraft.emerald_block", + "tile.blockRedstone.name": "block.minecraft.redstone_block", + "tile.tripWire.name": "block.minecraft.tripwire", + "tile.tripWireSource.name": "block.minecraft.tripwire_hook", + "tile.commandBlock.name": "block.minecraft.command_block", + "tile.repeatingCommandBlock.name": "block.minecraft.repeating_command_block", + "tile.chainCommandBlock.name": "block.minecraft.chain_command_block", + "tile.beacon.name": "block.minecraft.beacon", + "tile.beacon.primary": "block.minecraft.beacon.primary", + "tile.beacon.secondary": "block.minecraft.beacon.secondary", + "tile.cobbleWall.normal.name": "block.minecraft.cobblestone_wall", + "tile.cobbleWall.mossy.name": "block.minecraft.mossy_cobblestone_wall", + "tile.carrots.name": "block.minecraft.carrots", + "tile.potatoes.name": "block.minecraft.potatoes", + "tile.netherquartz.name": "block.minecraft.nether_quartz_ore", + "tile.hopper.name": "block.minecraft.hopper", + "tile.quartzBlock.name": "block.minecraft.quartz_block", + "tile.quartzBlock.default.name": "block.minecraft.quartz_block", + "tile.quartzBlock.chiseled.name": "block.minecraft.chiseled_quartz_block", + "tile.stairsQuartz.name": "block.minecraft.quartz_stairs", + "tile.slime.name": "block.minecraft.slime_block", + "tile.prismarine.rough.name": "block.minecraft.prismarine", + "tile.prismarine.bricks.name": "block.minecraft.prismarine_bricks", + "tile.prismarine.dark.name": "block.minecraft.dark_prismarine", + "tile.seaLantern.name": "block.minecraft.sea_lantern", + "tile.endRod.name": "block.minecraft.end_rod", + "tile.chorusPlant.name": "block.minecraft.chorus_plant", + "tile.chorusFlower.name": "block.minecraft.chorus_flower", + "tile.purpurBlock.name": "block.minecraft.purpur_block", + "tile.purpurPillar.name": "block.minecraft.purpur_pillar", + "tile.stairsPurpur.name": "block.minecraft.purpur_stairs", + "tile.purpurSlab.name": "block.minecraft.purpur_slab", + "tile.endBricks.name": "block.minecraft.end_stone_bricks", + "tile.beetroots.name": "block.minecraft.beetroots", + "tile.grassPath.name": "block.minecraft.grass_path", + "tile.magma.name": "block.minecraft.magma_block", + "tile.netherWartBlock.name": "block.minecraft.nether_wart_block", + "tile.boneBlock.name": "block.minecraft.bone_block", + "tile.observer.name": "block.minecraft.observer", + "tile.shulkerBoxWhite.name": "block.minecraft.white_shulker_box", + "tile.shulkerBoxOrange.name": "block.minecraft.orange_shulker_box", + "tile.shulkerBoxMagenta.name": "block.minecraft.magenta_shulker_box", + "tile.shulkerBoxLightBlue.name": "block.minecraft.light_blue_shulker_box", + "tile.shulkerBoxYellow.name": "block.minecraft.yellow_shulker_box", + "tile.shulkerBoxLime.name": "block.minecraft.lime_shulker_box", + "tile.shulkerBoxPink.name": "block.minecraft.pink_shulker_box", + "tile.shulkerBoxGray.name": "block.minecraft.gray_shulker_box", + "tile.shulkerBoxSilver.name": "block.minecraft.light_gray_shulker_box", + "tile.shulkerBoxCyan.name": "block.minecraft.cyan_shulker_box", + "tile.shulkerBoxPurple.name": "block.minecraft.purple_shulker_box", + "tile.shulkerBoxBlue.name": "block.minecraft.blue_shulker_box", + "tile.shulkerBoxBrown.name": "block.minecraft.brown_shulker_box", + "tile.shulkerBoxGreen.name": "block.minecraft.green_shulker_box", + "tile.shulkerBoxRed.name": "block.minecraft.red_shulker_box", + "tile.shulkerBoxBlack.name": "block.minecraft.black_shulker_box", + "tile.glazedTerracottaWhite.name": "block.minecraft.white_glazed_terracotta", + "tile.glazedTerracottaOrange.name": "block.minecraft.orange_glazed_terracotta", + "tile.glazedTerracottaMagenta.name": "block.minecraft.magenta_glazed_terracotta", + "tile.glazedTerracottaLightBlue.name": "block.minecraft.light_blue_glazed_terracotta", + "tile.glazedTerracottaYellow.name": "block.minecraft.yellow_glazed_terracotta", + "tile.glazedTerracottaLime.name": "block.minecraft.lime_glazed_terracotta", + "tile.glazedTerracottaPink.name": "block.minecraft.pink_glazed_terracotta", + "tile.glazedTerracottaGray.name": "block.minecraft.gray_glazed_terracotta", + "tile.glazedTerracottaSilver.name": "block.minecraft.light_gray_glazed_terracotta", + "tile.glazedTerracottaCyan.name": "block.minecraft.cyan_glazed_terracotta", + "tile.glazedTerracottaPurple.name": "block.minecraft.purple_glazed_terracotta", + "tile.glazedTerracottaBlue.name": "block.minecraft.blue_glazed_terracotta", + "tile.glazedTerracottaBrown.name": "block.minecraft.brown_glazed_terracotta", + "tile.glazedTerracottaGreen.name": "block.minecraft.green_glazed_terracotta", + "tile.glazedTerracottaRed.name": "block.minecraft.red_glazed_terracotta", + "tile.glazedTerracottaBlack.name": "block.minecraft.black_glazed_terracotta", + "tile.concrete.black.name": "block.minecraft.black_concrete", + "tile.concrete.red.name": "block.minecraft.red_concrete", + "tile.concrete.green.name": "block.minecraft.green_concrete", + "tile.concrete.brown.name": "block.minecraft.brown_concrete", + "tile.concrete.blue.name": "block.minecraft.blue_concrete", + "tile.concrete.purple.name": "block.minecraft.purple_concrete", + "tile.concrete.cyan.name": "block.minecraft.cyan_concrete", + "tile.concrete.silver.name": "block.minecraft.light_gray_concrete", + "tile.concrete.gray.name": "block.minecraft.gray_concrete", + "tile.concrete.pink.name": "block.minecraft.pink_concrete", + "tile.concrete.lime.name": "block.minecraft.lime_concrete", + "tile.concrete.yellow.name": "block.minecraft.yellow_concrete", + "tile.concrete.lightBlue.name": "block.minecraft.light_blue_concrete", + "tile.concrete.magenta.name": "block.minecraft.magenta_concrete", + "tile.concrete.orange.name": "block.minecraft.orange_concrete", + "tile.concrete.white.name": "block.minecraft.white_concrete", + "tile.concretePowder.black.name": "block.minecraft.black_concrete_powder", + "tile.concretePowder.red.name": "block.minecraft.red_concrete_powder", + "tile.concretePowder.green.name": "block.minecraft.green_concrete_powder", + "tile.concretePowder.brown.name": "block.minecraft.brown_concrete_powder", + "tile.concretePowder.blue.name": "block.minecraft.blue_concrete_powder", + "tile.concretePowder.purple.name": "block.minecraft.purple_concrete_powder", + "tile.concretePowder.cyan.name": "block.minecraft.cyan_concrete_powder", + "tile.concretePowder.silver.name": "block.minecraft.light_gray_concrete_powder", + "tile.concretePowder.gray.name": "block.minecraft.gray_concrete_powder", + "tile.concretePowder.pink.name": "block.minecraft.pink_concrete_powder", + "tile.concretePowder.lime.name": "block.minecraft.lime_concrete_powder", + "tile.concretePowder.yellow.name": "block.minecraft.yellow_concrete_powder", + "tile.concretePowder.lightBlue.name": "block.minecraft.light_blue_concrete_powder", + "tile.concretePowder.magenta.name": "block.minecraft.magenta_concrete_powder", + "tile.concretePowder.orange.name": "block.minecraft.orange_concrete_powder", + "tile.concretePowder.white.name": "block.minecraft.white_concrete_powder", + "tile.structureVoid.name": "block.minecraft.structure_void", + "tile.structureBlock.name": "block.minecraft.structure_block", + "item.nameTag.name": "item.minecraft.name_tag", + "item.leash.name": "item.minecraft.lead", + "item.shovelIron.name": "item.minecraft.iron_shovel", + "item.pickaxeIron.name": "item.minecraft.iron_pickaxe", + "item.hatchetIron.name": "item.minecraft.iron_axe", + "item.flintAndSteel.name": "item.minecraft.flint_and_steel", + "item.apple.name": "item.minecraft.apple", + "item.cookie.name": "item.minecraft.cookie", + "item.bow.name": "item.minecraft.bow", + "item.arrow.name": "item.minecraft.arrow", + "item.spectral_arrow.name": "item.minecraft.spectral_arrow", + "item.tipped_arrow.name": "item.minecraft.tipped_arrow", + "item.coal.name": "item.minecraft.coal", + "item.charcoal.name": "item.minecraft.charcoal", + "item.diamond.name": "item.minecraft.diamond", + "item.emerald.name": "item.minecraft.emerald", + "item.ingotIron.name": "item.minecraft.iron_ingot", + "item.ingotGold.name": "item.minecraft.gold_ingot", + "item.swordIron.name": "item.minecraft.iron_sword", + "item.swordWood.name": "item.minecraft.wooden_sword", + "item.shovelWood.name": "item.minecraft.wooden_shovel", + "item.pickaxeWood.name": "item.minecraft.wooden_pickaxe", + "item.hatchetWood.name": "item.minecraft.wooden_axe", + "item.swordStone.name": "item.minecraft.stone_sword", + "item.shovelStone.name": "item.minecraft.stone_shovel", + "item.pickaxeStone.name": "item.minecraft.stone_pickaxe", + "item.hatchetStone.name": "item.minecraft.stone_axe", + "item.swordDiamond.name": "item.minecraft.diamond_sword", + "item.shovelDiamond.name": "item.minecraft.diamond_shovel", + "item.pickaxeDiamond.name": "item.minecraft.diamond_pickaxe", + "item.hatchetDiamond.name": "item.minecraft.diamond_axe", + "item.stick.name": "item.minecraft.stick", + "item.bowl.name": "item.minecraft.bowl", + "item.mushroomStew.name": "item.minecraft.mushroom_stew", + "item.swordGold.name": "item.minecraft.golden_sword", + "item.shovelGold.name": "item.minecraft.golden_shovel", + "item.pickaxeGold.name": "item.minecraft.golden_pickaxe", + "item.hatchetGold.name": "item.minecraft.golden_axe", + "item.string.name": "item.minecraft.string", + "item.feather.name": "item.minecraft.feather", + "item.sulphur.name": "item.minecraft.gunpowder", + "item.hoeWood.name": "item.minecraft.wooden_hoe", + "item.hoeStone.name": "item.minecraft.stone_hoe", + "item.hoeIron.name": "item.minecraft.iron_hoe", + "item.hoeDiamond.name": "item.minecraft.diamond_hoe", + "item.hoeGold.name": "item.minecraft.golden_hoe", + "item.seeds_pumpkin.name": "item.minecraft.pumpkin_seeds", + "item.seeds_melon.name": "item.minecraft.melon_seeds", + "item.melon.name": "block.minecraft.melon", + "item.wheat.name": "item.minecraft.wheat", + "item.bread.name": "item.minecraft.bread", + "item.helmetCloth.name": "item.minecraft.leather_helmet", + "item.chestplateCloth.name": "item.minecraft.leather_chestplate", + "item.leggingsCloth.name": "item.minecraft.leather_leggings", + "item.bootsCloth.name": "item.minecraft.leather_boots", + "item.helmetIron.name": "item.minecraft.iron_helmet", + "item.chestplateIron.name": "item.minecraft.iron_chestplate", + "item.leggingsIron.name": "item.minecraft.iron_leggings", + "item.bootsIron.name": "item.minecraft.iron_boots", + "item.helmetDiamond.name": "item.minecraft.diamond_helmet", + "item.chestplateDiamond.name": "item.minecraft.diamond_chestplate", + "item.leggingsDiamond.name": "item.minecraft.diamond_leggings", + "item.bootsDiamond.name": "item.minecraft.diamond_boots", + "item.helmetGold.name": "item.minecraft.golden_helmet", + "item.chestplateGold.name": "item.minecraft.golden_chestplate", + "item.leggingsGold.name": "item.minecraft.golden_leggings", + "item.bootsGold.name": "item.minecraft.golden_boots", + "item.flint.name": "item.minecraft.flint", + "item.porkchopRaw.name": "item.minecraft.porkchop", + "item.porkchopCooked.name": "item.minecraft.cooked_porkchop", + "item.chickenRaw.name": "item.minecraft.chicken", + "item.chickenCooked.name": "item.minecraft.cooked_chicken", + "item.muttonRaw.name": "item.minecraft.mutton", + "item.muttonCooked.name": "item.minecraft.cooked_mutton", + "item.rabbitRaw.name": "item.minecraft.rabbit", + "item.rabbitCooked.name": "item.minecraft.cooked_rabbit", + "item.rabbitStew.name": "item.minecraft.rabbit_stew", + "item.rabbitFoot.name": "item.minecraft.rabbit_foot", + "item.rabbitHide.name": "item.minecraft.rabbit_hide", + "item.beefRaw.name": "item.minecraft.beef", + "item.beefCooked.name": "item.minecraft.cooked_beef", + "item.painting.name": "item.minecraft.painting", + "item.frame.name": "item.minecraft.item_frame", + "item.appleGold.name": "item.minecraft.golden_apple", + "item.sign.name": "book.signButton", + "item.doorOak.name": "block.minecraft.oak_door", + "item.doorSpruce.name": "block.minecraft.spruce_door", + "item.doorBirch.name": "block.minecraft.birch_door", + "item.doorJungle.name": "block.minecraft.jungle_door", + "item.doorAcacia.name": "block.minecraft.acacia_door", + "item.doorDarkOak.name": "block.minecraft.dark_oak_door", + "item.bucket.name": "item.minecraft.bucket", + "item.bucketWater.name": "item.minecraft.water_bucket", + "item.bucketLava.name": "item.minecraft.lava_bucket", + "item.minecart.name": "item.minecraft.minecart", + "item.saddle.name": "item.minecraft.saddle", + "item.doorIron.name": "block.minecraft.iron_door", + "item.redstone.name": "item.minecraft.redstone", + "item.snowball.name": "item.minecraft.snowball", + "item.boat.oak.name": "item.minecraft.oak_boat", + "item.boat.spruce.name": "item.minecraft.spruce_boat", + "item.boat.birch.name": "item.minecraft.birch_boat", + "item.boat.jungle.name": "item.minecraft.jungle_boat", + "item.boat.acacia.name": "item.minecraft.acacia_boat", + "item.boat.dark_oak.name": "item.minecraft.dark_oak_boat", + "item.leather.name": "item.minecraft.leather", + "item.brick.name": "item.minecraft.brick", + "item.clay.name": "block.minecraft.clay", + "item.paper.name": "item.minecraft.paper", + "item.book.name": "item.minecraft.book", + "item.slimeball.name": "item.minecraft.slime_ball", + "item.minecartChest.name": "item.minecraft.chest_minecart", + "item.minecartFurnace.name": "item.minecraft.furnace_minecart", + "item.minecartTnt.name": "item.minecraft.tnt_minecart", + "item.minecartHopper.name": "item.minecraft.hopper_minecart", + "item.minecartCommandBlock.name": "item.minecraft.command_block_minecart", + "item.egg.name": "item.minecraft.egg", + "item.compass.name": "item.minecraft.compass", + "item.fishingRod.name": "item.minecraft.fishing_rod", + "item.clock.name": "item.minecraft.clock", + "item.yellowDust.name": "item.minecraft.glowstone_dust", + "item.fish.salmon.raw.name": "item.minecraft.salmon", + "item.fish.pufferfish.raw.name": "item.minecraft.pufferfish", + "item.fish.salmon.cooked.name": "item.minecraft.cooked_salmon", + "item.record.name": "item.minecraft.music_disc_13", + "item.record.13.desc": "item.minecraft.music_disc_13.desc", + "item.record.cat.desc": "item.minecraft.music_disc_cat.desc", + "item.record.blocks.desc": "item.minecraft.music_disc_blocks.desc", + "item.record.chirp.desc": "item.minecraft.music_disc_chirp.desc", + "item.record.far.desc": "item.minecraft.music_disc_far.desc", + "item.record.mall.desc": "item.minecraft.music_disc_mall.desc", + "item.record.mellohi.desc": "item.minecraft.music_disc_mellohi.desc", + "item.record.stal.desc": "item.minecraft.music_disc_stal.desc", + "item.record.strad.desc": "item.minecraft.music_disc_strad.desc", + "item.record.ward.desc": "item.minecraft.music_disc_ward.desc", + "item.record.11.desc": "item.minecraft.music_disc_11.desc", + "item.record.wait.desc": "item.minecraft.music_disc_wait.desc", + "item.bone.name": "item.minecraft.bone", + "item.dyePowder.black.name": "item.minecraft.ink_sac", + "item.dyePowder.red.name": "item.minecraft.rose_red", + "item.dyePowder.green.name": "item.minecraft.cactus_green", + "item.dyePowder.brown.name": "item.minecraft.cocoa_beans", + "item.dyePowder.blue.name": "item.minecraft.lapis_lazuli", + "item.dyePowder.purple.name": "item.minecraft.purple_dye", + "item.dyePowder.cyan.name": "item.minecraft.cyan_dye", + "item.dyePowder.silver.name": "item.minecraft.light_gray_dye", + "item.dyePowder.gray.name": "item.minecraft.gray_dye", + "item.dyePowder.pink.name": "item.minecraft.pink_dye", + "item.dyePowder.lime.name": "item.minecraft.lime_dye", + "item.dyePowder.yellow.name": "item.minecraft.dandelion_yellow", + "item.dyePowder.lightBlue.name": "item.minecraft.light_blue_dye", + "item.dyePowder.magenta.name": "item.minecraft.magenta_dye", + "item.dyePowder.orange.name": "item.minecraft.orange_dye", + "item.dyePowder.white.name": "item.minecraft.bone_meal", + "item.sugar.name": "item.minecraft.sugar", + "item.cake.name": "block.minecraft.cake", + "item.bed.black.name": "block.minecraft.black_bed", + "item.bed.red.name": "block.minecraft.red_bed", + "item.bed.green.name": "block.minecraft.green_bed", + "item.bed.brown.name": "block.minecraft.brown_bed", + "item.bed.blue.name": "block.minecraft.blue_bed", + "item.bed.purple.name": "block.minecraft.purple_bed", + "item.bed.cyan.name": "block.minecraft.cyan_bed", + "item.bed.silver.name": "block.minecraft.light_gray_bed", + "item.bed.gray.name": "block.minecraft.gray_bed", + "item.bed.pink.name": "block.minecraft.pink_bed", + "item.bed.lime.name": "block.minecraft.lime_bed", + "item.bed.yellow.name": "block.minecraft.yellow_bed", + "item.bed.lightBlue.name": "block.minecraft.light_blue_bed", + "item.bed.magenta.name": "block.minecraft.magenta_bed", + "item.bed.orange.name": "block.minecraft.orange_bed", + "item.bed.white.name": "block.minecraft.white_bed", + "item.diode.name": "block.minecraft.repeater", + "item.comparator.name": "block.minecraft.comparator", + "item.map.name": "item.minecraft.filled_map", + "item.shears.name": "item.minecraft.shears", + "item.rottenFlesh.name": "item.minecraft.rotten_flesh", + "item.enderPearl.name": "item.minecraft.ender_pearl", + "item.blazeRod.name": "item.minecraft.blaze_rod", + "item.ghastTear.name": "item.minecraft.ghast_tear", + "item.netherStalkSeeds.name": "block.minecraft.nether_wart", + "item.potion.name": "item.minecraft.potion", + "item.splash_potion.name": "item.minecraft.splash_potion", + "item.lingering_potion.name": "item.minecraft.lingering_potion", + "item.end_crystal.name": "item.minecraft.end_crystal", + "item.goldNugget.name": "item.minecraft.gold_nugget", + "item.glassBottle.name": "item.minecraft.glass_bottle", + "item.spiderEye.name": "item.minecraft.spider_eye", + "item.fermentedSpiderEye.name": "item.minecraft.fermented_spider_eye", + "item.blazePowder.name": "item.minecraft.blaze_powder", + "item.magmaCream.name": "item.minecraft.magma_cream", + "item.cauldron.name": "block.minecraft.cauldron", + "item.brewingStand.name": "block.minecraft.brewing_stand", + "item.eyeOfEnder.name": "item.minecraft.ender_eye", + "item.expBottle.name": "item.minecraft.experience_bottle", + "item.fireball.name": "item.minecraft.fire_charge", + "item.writingBook.name": "item.minecraft.writable_book", + "item.writtenBook.name": "item.minecraft.written_book", + "item.flowerPot.name": "block.minecraft.flower_pot", + "item.emptyMap.name": "item.minecraft.map", + "item.carrots.name": "item.minecraft.carrot", + "item.carrotGolden.name": "item.minecraft.golden_carrot", + "item.potato.name": "item.minecraft.potato", + "item.potatoBaked.name": "item.minecraft.baked_potato", + "item.potatoPoisonous.name": "item.minecraft.poisonous_potato", + "item.skull.skeleton.name": "block.minecraft.skeleton_skull", + "item.skull.wither.name": "block.minecraft.wither_skeleton_skull", + "item.skull.zombie.name": "block.minecraft.zombie_head", + "item.skull.player.name": "block.minecraft.player_head.named", + "item.skull.creeper.name": "block.minecraft.creeper_head", + "item.skull.dragon.name": "block.minecraft.dragon_head", + "item.carrotOnAStick.name": "item.minecraft.carrot_on_a_stick", + "item.netherStar.name": "item.minecraft.nether_star", + "item.pumpkinPie.name": "item.minecraft.pumpkin_pie", + "item.enchantedBook.name": "item.minecraft.enchanted_book", + "item.fireworks.name": "item.minecraft.firework_rocket", + "item.fireworks.flight": "item.minecraft.firework_rocket.flight", + "item.fireworksCharge.name": "item.minecraft.firework_star", + "item.fireworksCharge.black": "item.minecraft.firework_star.black", + "item.fireworksCharge.red": "item.minecraft.firework_star.red", + "item.fireworksCharge.green": "item.minecraft.firework_star.green", + "item.fireworksCharge.brown": "item.minecraft.firework_star.brown", + "item.fireworksCharge.blue": "item.minecraft.firework_star.blue", + "item.fireworksCharge.purple": "item.minecraft.firework_star.purple", + "item.fireworksCharge.cyan": "item.minecraft.firework_star.cyan", + "item.fireworksCharge.silver": "item.minecraft.firework_star.light_gray", + "item.fireworksCharge.gray": "item.minecraft.firework_star.gray", + "item.fireworksCharge.pink": "item.minecraft.firework_star.pink", + "item.fireworksCharge.lime": "item.minecraft.firework_star.lime", + "item.fireworksCharge.yellow": "item.minecraft.firework_star.yellow", + "item.fireworksCharge.lightBlue": "item.minecraft.firework_star.light_blue", + "item.fireworksCharge.magenta": "item.minecraft.firework_star.magenta", + "item.fireworksCharge.orange": "item.minecraft.firework_star.orange", + "item.fireworksCharge.white": "item.minecraft.firework_star.white", + "item.fireworksCharge.customColor": "item.minecraft.firework_star.custom_color", + "item.fireworksCharge.fadeTo": "item.minecraft.firework_star.fade_to", + "item.fireworksCharge.flicker": "item.minecraft.firework_star.flicker", + "item.fireworksCharge.trail": "item.minecraft.firework_star.trail", + "item.fireworksCharge.type.0": "item.minecraft.firework_star.shape.small_ball", + "item.fireworksCharge.type.1": "item.minecraft.firework_star.shape.large_ball", + "item.fireworksCharge.type.2": "item.minecraft.firework_star.shape.star", + "item.fireworksCharge.type.3": "item.minecraft.firework_star.shape.creeper", + "item.fireworksCharge.type.4": "item.minecraft.firework_star.shape.burst", + "item.fireworksCharge.type": "item.minecraft.firework_star.shape", + "item.netherbrick.name": "item.minecraft.nether_brick", + "item.netherquartz.name": "item.minecraft.quartz", + "item.armorStand.name": "item.minecraft.armor_stand", + "item.horsearmormetal.name": "item.minecraft.iron_horse_armor", + "item.horsearmordiamond.name": "item.minecraft.diamond_horse_armor", + "item.prismarineShard.name": "item.minecraft.prismarine_shard", + "item.prismarineCrystals.name": "item.minecraft.prismarine_crystals", + "item.chorusFruit.name": "item.minecraft.chorus_fruit", + "item.chorusFruitPopped.name": "item.minecraft.popped_chorus_fruit", + "item.beetroot.name": "item.minecraft.beetroot", + "item.beetroot_seeds.name": "item.minecraft.beetroot_seeds", + "item.beetroot_soup.name": "item.minecraft.beetroot_soup", + "item.dragon_breath.name": "item.minecraft.dragon_breath", + "item.elytra.name": "item.minecraft.elytra", + "item.totem.name": "item.minecraft.totem_of_undying", + "item.shulkerShell.name": "item.minecraft.shulker_shell", + "item.ironNugget.name": "item.minecraft.iron_nugget", + "item.knowledgeBook.name": "item.minecraft.knowledge_book", + "container.inventory": "key.categories.inventory", + "container.hopper": null, + "container.crafting": null, + "container.dispenser": "block.minecraft.dispenser", + "container.dropper": "block.minecraft.dropper", + "container.furnace": "block.minecraft.furnace", + "container.enchant": null, + "container.enchant.lapis.one": null, + "container.enchant.lapis.many": null, + "container.enchant.level.one": null, + "container.enchant.level.many": null, + "container.enchant.level.requirement": null, + "container.enchant.clue": null, + "container.repair": null, + "container.repair.cost": null, + "container.repair.expensive": null, + "container.creative": null, + "container.brewing": "block.minecraft.brewing_stand", + "container.chest": "block.minecraft.chest", + "container.chestDouble": null, + "container.enderchest": "block.minecraft.ender_chest", + "container.beacon": "block.minecraft.beacon", + "container.shulkerBox": "block.minecraft.shulker_box", + "container.shulkerBox.more": null, + "container.spectatorCantOpen": null, + "container.isLocked": null, + "structure_block.save_success": null, + "structure_block.save_failure": null, + "structure_block.load_success": null, + "structure_block.load_prepare": null, + "structure_block.load_not_found": null, + "structure_block.size_success": null, + "structure_block.mode.save": "selectWorld.edit.save", + "structure_block.mode.load": null, + "structure_block.mode.data": null, + "structure_block.mode.corner": null, + "structure_block.hover.save": null, + "structure_block.hover.load": null, + "structure_block.hover.data": null, + "structure_block.hover.corner": null, + "structure_block.mode_info.save": null, + "structure_block.mode_info.load": null, + "structure_block.mode_info.data": null, + "structure_block.mode_info.corner": null, + "structure_block.structure_name": null, + "structure_block.custom_data": null, + "structure_block.position": null, + "structure_block.size": null, + "structure_block.integrity": null, + "structure_block.include_entities": null, + "structure_block.detect_size": null, + "structure_block.button.detect_size": null, + "structure_block.button.save": null, + "structure_block.button.load": null, + "structure_block.show_air": null, + "structure_block.show_boundingbox": null, + "item.dyed": null, + "item.unbreakable": null, + "item.canBreak": null, + "item.canPlace": null, + "item.color": null, + "item.nbt_tags": null, + "item.durability": null, + "filled_map.mansion": null, + "filled_map.monument": null, + "filled_map.unknown": null, + "filled_map.level": null, + "filled_map.scale": null, + "entity.Item.name": "entity.minecraft.item", + "entity.XPOrb.name": "entity.minecraft.experience_orb", + "entity.SmallFireball.name": "entity.minecraft.small_fireball", + "entity.Fireball.name": "entity.minecraft.fireball", + "entity.DragonFireball.name": "entity.minecraft.dragon_fireball", + "entity.ThrownPotion.name": "item.minecraft.potion", + "entity.Arrow.name": "item.minecraft.arrow", + "entity.Snowball.name": "item.minecraft.snowball", + "entity.Painting.name": "item.minecraft.painting", + "entity.ArmorStand.name": "item.minecraft.armor_stand", + "entity.Creeper.name": "entity.minecraft.creeper", + "entity.Skeleton.name": "entity.minecraft.skeleton", + "entity.WitherSkeleton.name": "entity.minecraft.wither_skeleton", + "entity.Stray.name": "entity.minecraft.stray", + "entity.Spider.name": "entity.minecraft.spider", + "entity.Giant.name": "entity.minecraft.giant", + "entity.Zombie.name": "entity.minecraft.zombie", + "entity.Husk.name": "entity.minecraft.husk", + "entity.Slime.name": "entity.minecraft.slime", + "entity.Ghast.name": "entity.minecraft.ghast", + "entity.PigZombie.name": "entity.minecraft.zombie_pigman", + "entity.Enderman.name": "entity.minecraft.enderman", + "entity.Endermite.name": "entity.minecraft.endermite", + "entity.Silverfish.name": "entity.minecraft.silverfish", + "entity.CaveSpider.name": "entity.minecraft.cave_spider", + "entity.Blaze.name": "entity.minecraft.blaze", + "entity.LavaSlime.name": "entity.minecraft.magma_cube", + "entity.MushroomCow.name": "entity.minecraft.mooshroom", + "entity.Villager.name": "entity.minecraft.villager", + "entity.ZombieVillager.name": "entity.minecraft.zombie_villager", + "entity.VillagerGolem.name": "entity.minecraft.iron_golem", + "entity.SnowMan.name": "entity.minecraft.snow_golem", + "entity.EnderDragon.name": "entity.minecraft.ender_dragon", + "entity.WitherBoss.name": "entity.minecraft.wither", + "entity.Witch.name": "entity.minecraft.witch", + "entity.Guardian.name": "entity.minecraft.guardian", + "entity.ElderGuardian.name": "entity.minecraft.elder_guardian", + "entity.Shulker.name": "entity.minecraft.shulker", + "entity.PolarBear.name": "entity.minecraft.polar_bear", + "entity.EvocationIllager.name": "entity.minecraft.evoker", + "entity.Vex.name": "entity.minecraft.vex", + "entity.VindicationIllager.name": "entity.minecraft.vindicator", + "entity.Parrot.name": "entity.minecraft.parrot", + "entity.IllusionIllager.name": "entity.minecraft.illusioner", + "entity.Villager.farmer": "entity.minecraft.villager.farmer", + "entity.Villager.fisherman": "entity.minecraft.villager.fisherman", + "entity.Villager.shepherd": "entity.minecraft.villager.shepherd", + "entity.Villager.fletcher": "entity.minecraft.villager.fletcher", + "entity.Villager.librarian": "entity.minecraft.villager.librarian", + "entity.Villager.cleric": "entity.minecraft.villager.cleric", + "entity.Villager.armor": "entity.minecraft.villager.armorer", + "entity.Villager.weapon": "entity.minecraft.villager.weapon_smith", + "entity.Villager.tool": "entity.minecraft.villager.tool_smith", + "entity.Villager.butcher": "entity.minecraft.villager.butcher", + "entity.Villager.leather": "entity.minecraft.villager.leatherworker", + "entity.Villager.nitwit": "entity.minecraft.villager.nitwit", + "entity.Villager.cartographer": "entity.minecraft.villager.cartographer", + "entity.Pig.name": "entity.minecraft.pig", + "entity.Sheep.name": "entity.minecraft.sheep", + "entity.Cow.name": "entity.minecraft.cow", + "entity.Chicken.name": "entity.minecraft.chicken", + "entity.Squid.name": "entity.minecraft.squid", + "entity.Wolf.name": "entity.minecraft.wolf", + "entity.Ozelot.name": "entity.minecraft.ocelot", + "entity.Cat.name": "entity.minecraft.cat", + "entity.Bat.name": "entity.minecraft.bat", + "entity.Horse.name": "entity.minecraft.horse", + "entity.Donkey.name": "entity.minecraft.donkey", + "entity.Mule.name": "entity.minecraft.mule", + "entity.SkeletonHorse.name": "entity.minecraft.skeleton_horse", + "entity.ZombieHorse.name": "entity.minecraft.zombie_horse", + "entity.Rabbit.name": "entity.minecraft.rabbit", + "entity.KillerBunny.name": "entity.minecraft.killer_bunny", + "entity.Llama.name": "entity.minecraft.llama", + "entity.FallingSand.name": "entity.minecraft.falling_block", + "entity.Minecart.name": "item.minecraft.minecart", + "entity.MinecartHopper.name": "item.minecraft.hopper_minecart", + "entity.MinecartChest.name": "item.minecraft.chest_minecart", + "entity.Boat.name": "entity.minecraft.boat", + "entity.generic.name": "selectWorld.versionUnknown", + "death.fell.accident.ladder": null, + "death.fell.accident.vines": null, + "death.fell.accident.water": null, + "death.fell.accident.generic": null, + "death.fell.killer": null, + "death.fell.assist": null, + "death.fell.assist.item": null, + "death.fell.finish": null, + "death.fell.finish.item": null, + "death.attack.lightningBolt": null, + "death.attack.inFire": null, + "death.attack.inFire.player": null, + "death.attack.onFire": null, + "death.attack.onFire.player": null, + "death.attack.lava": null, + "death.attack.lava.player": null, + "death.attack.hotFloor.player": null, + "death.attack.inWall": null, + "death.attack.cramming": null, + "death.attack.drown": null, + "death.attack.drown.player": null, + "death.attack.starve": null, + "death.attack.cactus": null, + "death.attack.cactus.player": null, + "death.attack.generic": null, + "death.attack.explosion": null, + "death.attack.explosion.player": null, + "death.attack.magic": null, + "death.attack.wither": null, + "death.attack.anvil": null, + "death.attack.fallingBlock": null, + "death.attack.mob": null, + "death.attack.player": "death.attack.mob", + "death.attack.player.item": "death.attack.mob.item", + "death.attack.arrow": null, + "death.attack.arrow.item": null, + "death.attack.fireball": null, + "death.attack.fireball.item": null, + "death.attack.thrown": null, + "death.attack.thrown.item": null, + "death.attack.indirectMagic": null, + "death.attack.indirectMagic.item": null, + "death.attack.thorns": null, + "death.attack.fall": null, + "death.attack.outOfWorld": null, + "death.attack.dragonBreath": null, + "death.attack.flyIntoWall": null, + "death.attack.fireworks": null, + "deathScreen.respawn": null, + "deathScreen.spectate": null, + "deathScreen.deleteWorld": null, + "deathScreen.titleScreen": null, + "deathScreen.score": null, + "deathScreen.title.hardcore": null, + "deathScreen.title": null, + "deathScreen.leaveServer": null, + "deathScreen.quit.confirm": null, + "effect.none": null, + "effect.moveSpeed": "effect.minecraft.speed", + "effect.moveSlowdown": "effect.minecraft.slowness", + "effect.digSpeed": "effect.minecraft.haste", + "effect.digSlowDown": "effect.minecraft.mining_fatigue", + "effect.damageBoost": "effect.minecraft.strength", + "effect.heal": "effect.minecraft.instant_health", + "effect.harm": "effect.minecraft.instant_damage", + "effect.jump": "effect.minecraft.jump_boost", + "effect.confusion": "effect.minecraft.nausea", + "effect.regeneration": "effect.minecraft.regeneration", + "effect.resistance": "effect.minecraft.resistance", + "effect.fireResistance": "effect.minecraft.fire_resistance", + "effect.waterBreathing": "effect.minecraft.water_breathing", + "effect.invisibility": "effect.minecraft.invisibility", + "effect.blindness": "effect.minecraft.blindness", + "effect.nightVision": "effect.minecraft.night_vision", + "effect.hunger": "effect.minecraft.hunger", + "effect.weakness": "effect.minecraft.weakness", + "effect.poison": "effect.minecraft.poison", + "effect.wither": "entity.minecraft.wither", + "effect.healthBoost": "effect.minecraft.health_boost", + "effect.absorption": "effect.minecraft.absorption", + "effect.saturation": "options.saturation", + "effect.glowing": "effect.minecraft.glowing", + "effect.luck": "effect.minecraft.luck", + "effect.unluck": "effect.minecraft.unluck", + "effect.levitation": "effect.minecraft.levitation", + "tipped_arrow.effect.empty": "item.minecraft.tipped_arrow.effect.empty", + "tipped_arrow.effect.water": "item.minecraft.tipped_arrow.effect.water", + "tipped_arrow.effect.mundane": "item.minecraft.tipped_arrow", + "tipped_arrow.effect.thick": "item.minecraft.tipped_arrow", + "tipped_arrow.effect.awkward": "item.minecraft.tipped_arrow", + "tipped_arrow.effect.night_vision": "item.minecraft.tipped_arrow.effect.night_vision", + "tipped_arrow.effect.invisibility": "item.minecraft.tipped_arrow.effect.invisibility", + "tipped_arrow.effect.leaping": "item.minecraft.tipped_arrow.effect.leaping", + "tipped_arrow.effect.fire_resistance": "item.minecraft.tipped_arrow.effect.fire_resistance", + "tipped_arrow.effect.swiftness": "item.minecraft.tipped_arrow.effect.swiftness", + "tipped_arrow.effect.slowness": "item.minecraft.tipped_arrow.effect.slowness", + "tipped_arrow.effect.water_breathing": "item.minecraft.tipped_arrow.effect.water_breathing", + "tipped_arrow.effect.healing": "item.minecraft.tipped_arrow.effect.healing", + "tipped_arrow.effect.harming": "item.minecraft.tipped_arrow.effect.harming", + "tipped_arrow.effect.poison": "item.minecraft.tipped_arrow.effect.poison", + "tipped_arrow.effect.regeneration": "item.minecraft.tipped_arrow.effect.regeneration", + "tipped_arrow.effect.strength": "item.minecraft.tipped_arrow.effect.strength", + "tipped_arrow.effect.weakness": "item.minecraft.tipped_arrow.effect.weakness", + "tipped_arrow.effect.levitation": "item.minecraft.tipped_arrow.effect.levitation", + "tipped_arrow.effect.luck": "item.minecraft.tipped_arrow.effect.luck", + "potion.whenDrank": null, + "potion.effect.empty": "item.minecraft.potion.effect.empty", + "potion.effect.water": "item.minecraft.potion.effect.water", + "potion.effect.mundane": "item.minecraft.potion.effect.mundane", + "potion.effect.thick": "item.minecraft.potion.effect.thick", + "potion.effect.awkward": "item.minecraft.potion.effect.awkward", + "potion.effect.night_vision": "item.minecraft.potion.effect.night_vision", + "potion.effect.invisibility": "item.minecraft.potion.effect.invisibility", + "potion.effect.leaping": "item.minecraft.potion.effect.leaping", + "potion.effect.fire_resistance": "item.minecraft.potion.effect.fire_resistance", + "potion.effect.swiftness": "item.minecraft.potion.effect.swiftness", + "potion.effect.slowness": "item.minecraft.potion.effect.slowness", + "potion.effect.water_breathing": "item.minecraft.potion.effect.water_breathing", + "potion.effect.healing": "item.minecraft.potion.effect.healing", + "potion.effect.harming": "item.minecraft.potion.effect.harming", + "potion.effect.poison": "item.minecraft.potion.effect.poison", + "potion.effect.regeneration": "item.minecraft.potion.effect.regeneration", + "potion.effect.strength": "item.minecraft.potion.effect.strength", + "potion.effect.weakness": "item.minecraft.potion.effect.weakness", + "potion.effect.levitation": "item.minecraft.potion.effect.levitation", + "potion.effect.luck": "item.minecraft.potion.effect.luck", + "splash_potion.effect.empty": "item.minecraft.splash_potion.effect.empty", + "splash_potion.effect.water": "item.minecraft.splash_potion.effect.water", + "splash_potion.effect.mundane": "item.minecraft.splash_potion.effect.mundane", + "splash_potion.effect.thick": "item.minecraft.splash_potion.effect.thick", + "splash_potion.effect.awkward": "item.minecraft.splash_potion.effect.awkward", + "splash_potion.effect.night_vision": "item.minecraft.splash_potion.effect.night_vision", + "splash_potion.effect.invisibility": "item.minecraft.splash_potion.effect.invisibility", + "splash_potion.effect.leaping": "item.minecraft.splash_potion.effect.leaping", + "splash_potion.effect.fire_resistance": "item.minecraft.splash_potion.effect.fire_resistance", + "splash_potion.effect.swiftness": "item.minecraft.splash_potion.effect.swiftness", + "splash_potion.effect.slowness": "item.minecraft.splash_potion.effect.slowness", + "splash_potion.effect.water_breathing": "item.minecraft.splash_potion.effect.water_breathing", + "splash_potion.effect.healing": "item.minecraft.splash_potion.effect.healing", + "splash_potion.effect.harming": "item.minecraft.splash_potion.effect.harming", + "splash_potion.effect.poison": "item.minecraft.splash_potion.effect.poison", + "splash_potion.effect.regeneration": "item.minecraft.splash_potion.effect.regeneration", + "splash_potion.effect.strength": "item.minecraft.splash_potion.effect.strength", + "splash_potion.effect.weakness": "item.minecraft.splash_potion.effect.weakness", + "splash_potion.effect.levitation": "item.minecraft.splash_potion.effect.levitation", + "splash_potion.effect.luck": "item.minecraft.splash_potion.effect.luck", + "lingering_potion.effect.empty": "item.minecraft.lingering_potion.effect.empty", + "lingering_potion.effect.water": "item.minecraft.lingering_potion.effect.water", + "lingering_potion.effect.mundane": "item.minecraft.lingering_potion.effect.mundane", + "lingering_potion.effect.thick": "item.minecraft.lingering_potion.effect.thick", + "lingering_potion.effect.awkward": "item.minecraft.lingering_potion.effect.awkward", + "lingering_potion.effect.night_vision": "item.minecraft.lingering_potion.effect.night_vision", + "lingering_potion.effect.invisibility": "item.minecraft.lingering_potion.effect.invisibility", + "lingering_potion.effect.leaping": "item.minecraft.lingering_potion.effect.leaping", + "lingering_potion.effect.fire_resistance": "item.minecraft.lingering_potion.effect.fire_resistance", + "lingering_potion.effect.swiftness": "item.minecraft.lingering_potion.effect.swiftness", + "lingering_potion.effect.slowness": "item.minecraft.lingering_potion.effect.slowness", + "lingering_potion.effect.water_breathing": "item.minecraft.lingering_potion.effect.water_breathing", + "lingering_potion.effect.healing": "item.minecraft.lingering_potion.effect.healing", + "lingering_potion.effect.harming": "item.minecraft.lingering_potion.effect.harming", + "lingering_potion.effect.poison": "item.minecraft.lingering_potion.effect.poison", + "lingering_potion.effect.regeneration": "item.minecraft.lingering_potion.effect.regeneration", + "lingering_potion.effect.strength": "item.minecraft.lingering_potion.effect.strength", + "lingering_potion.effect.weakness": "item.minecraft.lingering_potion.effect.weakness", + "lingering_potion.effect.levitation": "item.minecraft.lingering_potion.effect.levitation", + "lingering_potion.effect.luck": "item.minecraft.lingering_potion.effect.luck", + "potion.potency.0": "selectWorld.gameMode.spectator.line2", + "potion.potency.1": null, + "potion.potency.2": null, + "enchantment.damage.all": "enchantment.minecraft.sharpness", + "enchantment.damage.undead": "enchantment.minecraft.smite", + "enchantment.damage.arthropods": "enchantment.minecraft.bane_of_arthropods", + "enchantment.knockback": "enchantment.minecraft.knockback", + "enchantment.fire": "enchantment.minecraft.fire_aspect", + "enchantment.sweeping": "enchantment.minecraft.sweeping", + "enchantment.protect.all": "enchantment.minecraft.protection", + "enchantment.protect.fire": "enchantment.minecraft.fire_protection", + "enchantment.protect.fall": "enchantment.minecraft.feather_falling", + "enchantment.protect.explosion": "enchantment.minecraft.blast_protection", + "enchantment.protect.projectile": "enchantment.minecraft.projectile_protection", + "enchantment.oxygen": "enchantment.minecraft.respiration", + "enchantment.waterWorker": "enchantment.minecraft.aqua_affinity", + "enchantment.waterWalker": "enchantment.minecraft.depth_strider", + "enchantment.frostWalker": "enchantment.minecraft.frost_walker", + "enchantment.digging": "enchantment.minecraft.efficiency", + "enchantment.untouching": "enchantment.minecraft.silk_touch", + "enchantment.durability": "enchantment.minecraft.unbreaking", + "enchantment.lootBonus": "enchantment.minecraft.looting", + "enchantment.lootBonusDigger": "enchantment.minecraft.fortune", + "enchantment.lootBonusFishing": "enchantment.minecraft.luck_of_the_sea", + "enchantment.fishingSpeed": "enchantment.minecraft.lure", + "enchantment.arrowDamage": "enchantment.minecraft.power", + "enchantment.arrowFire": "enchantment.minecraft.flame", + "enchantment.arrowKnockback": "enchantment.minecraft.punch", + "enchantment.arrowInfinite": "enchantment.minecraft.infinity", + "enchantment.thorns": "enchantment.minecraft.thorns", + "enchantment.mending": "enchantment.minecraft.mending", + "enchantment.binding_curse": "enchantment.minecraft.binding_curse", + "enchantment.vanishing_curse": "enchantment.minecraft.vanishing_curse", + "enchantment.level.1": null, + "enchantment.level.2": "potion.potency.1", + "enchantment.level.3": "potion.potency.2", + "enchantment.level.4": "potion.potency.3", + "enchantment.level.5": "potion.potency.4", + "enchantment.level.6": "potion.potency.5", + "enchantment.level.7": null, + "enchantment.level.8": null, + "enchantment.level.9": null, + "enchantment.level.10": null, + "gui.advancements": "key.advancements", + "gui.stats": null, + "advancements.empty": null, + "advancements.toast.task": null, + "advancements.toast.challenge": null, + "advancements.toast.goal": null, + "stats.tooltip.type.statistic": null, + "stat.generalButton": null, + "stat.blocksButton": "soundCategory.block", + "stat.itemsButton": null, + "stat.mobsButton": null, + "stat.used": "stat_type.minecraft.used", + "stat.mined": "stat_type.minecraft.mined", + "stat.crafted": "stat_type.minecraft.crafted", + "stat.entityKills": "stat_type.minecraft.killed", + "stat.entityKilledBy": "stat_type.minecraft.killed_by", + "stat.entityKills.none": "stat_type.minecraft.killed.none", + "stat.entityKilledBy.none": "stat_type.minecraft.killed_by.none", + "stat.leaveGame": "stat.minecraft.leave_game", + "stat.playOneMinute": "stat.minecraft.play_one_minute", + "stat.timeSinceDeath": "stat.minecraft.time_since_death", + "stat.sneakTime": "stat.minecraft.sneak_time", + "stat.walkOneCm": "stat.minecraft.walk_one_cm", + "stat.crouchOneCm": "stat.minecraft.crouch_one_cm", + "stat.sprintOneCm": "stat.minecraft.sprint_one_cm", + "stat.fallOneCm": "stat.minecraft.fall_one_cm", + "stat.swimOneCm": "stat.minecraft.swim_one_cm", + "stat.flyOneCm": "stat.minecraft.fly_one_cm", + "stat.climbOneCm": "stat.minecraft.climb_one_cm", + "stat.minecartOneCm": "stat.minecraft.minecart_one_cm", + "stat.boatOneCm": "stat.minecraft.boat_one_cm", + "stat.pigOneCm": "stat.minecraft.pig_one_cm", + "stat.horseOneCm": "stat.minecraft.horse_one_cm", + "stat.aviateOneCm": "stat.minecraft.aviate_one_cm", + "stat.jump": "stat.minecraft.jump", + "stat.drop": "stat.minecraft.drop", + "stat.dropped": "stat_type.minecraft.dropped", + "stat.pickup": "stat_type.minecraft.picked_up", + "stat.damageDealt": "stat.minecraft.damage_dealt", + "stat.damageTaken": "stat.minecraft.damage_taken", + "stat.deaths": "stat.minecraft.deaths", + "stat.mobKills": "stat.minecraft.mob_kills", + "stat.animalsBred": "stat.minecraft.animals_bred", + "stat.playerKills": "stat.minecraft.player_kills", + "stat.fishCaught": "stat.minecraft.fish_caught", + "stat.treasureFished": "stat.minecraft.treasure_fished", + "stat.junkFished": "stat.minecraft.junk_fished", + "stat.talkedToVillager": "stat.minecraft.talked_to_villager", + "stat.tradedWithVillager": "stat.minecraft.traded_with_villager", + "stat.cakeSlicesEaten": "stat.minecraft.eat_cake_slice", + "stat.cauldronFilled": "stat.minecraft.fill_cauldron", + "stat.cauldronUsed": "stat.minecraft.use_cauldron", + "stat.armorCleaned": "stat.minecraft.clean_armor", + "stat.bannerCleaned": "stat.minecraft.clean_banner", + "stat.brewingstandInteraction": "stat.minecraft.interact_with_brewingstand", + "stat.beaconInteraction": "stat.minecraft.interact_with_beacon", + "stat.dropperInspected": "stat.minecraft.inspect_dropper", + "stat.hopperInspected": "stat.minecraft.inspect_hopper", + "stat.dispenserInspected": "stat.minecraft.inspect_dispenser", + "stat.noteblockPlayed": "stat.minecraft.play_noteblock", + "stat.noteblockTuned": "stat.minecraft.tune_noteblock", + "stat.flowerPotted": "stat.minecraft.pot_flower", + "stat.trappedChestTriggered": "stat.minecraft.trigger_trapped_chest", + "stat.enderchestOpened": "stat.minecraft.open_enderchest", + "stat.itemEnchanted": "stat.minecraft.enchant_item", + "stat.furnaceInteraction": "stat.minecraft.interact_with_furnace", + "stat.workbenchInteraction": "stat.minecraft.interact_with_crafting_table", + "stat.chestOpened": "stat.minecraft.open_chest", + "stat.shulkerBoxOpened": "stat.minecraft.open_shulker_box", + "stat.sleepInBed": "stat.minecraft.sleep_in_bed", + "recipe.toast.title": null, + "recipe.toast.description": null, + "commands.setblock.success": "subtitles.block.generic.place", + "commands.time.set": null, + "commands.kill.successful": "commands.kill.success.single", + "commands.save-on.alreadyOn": "commands.save.alreadyOn", + "commands.save-off.alreadyOff": "commands.save.alreadyOff", + "commands.stop.start": "commands.stop.stopping", + "commands.tp.success": "commands.teleport.success.entity.single", + "commands.tp.success.coordinates": "commands.teleport.success.location.single", + "commands.teleport.success.coordinates": "commands.teleport.success.location.single", + "commands.whitelist.reloaded": null, + "commands.whitelist.add.success": null, + "commands.whitelist.remove.success": null, + "commands.advancement.advancementNotFound": null, + "commands.scoreboard.players.enable.success": "commands.scoreboard.players.enable.success.single", + "commands.scoreboard.teams.remove.success": "commands.team.remove.success", + "commands.gamemode.success.self": null, + "commands.gamemode.success.other": null, + "commands.publish.started": null, + "commands.publish.failed": null, + "commands.debug.start": "commands.debug.started", + "commands.message.display.outgoing": null, + "commands.message.display.incoming": null, + "commands.seed.success": null, + "itemGroup.buildingBlocks": null, + "itemGroup.decorations": null, + "itemGroup.redstone": "item.minecraft.redstone", + "itemGroup.transportation": null, + "itemGroup.misc": "key.categories.misc", + "itemGroup.search": null, + "itemGroup.food": null, + "itemGroup.tools": null, + "itemGroup.combat": null, + "itemGroup.brewing": null, + "itemGroup.materials": null, + "itemGroup.inventory": null, + "itemGroup.hotbar": null, + "inventory.binSlot": null, + "inventory.hotbarSaved": null, + "inventory.hotbarInfo": null, + "advMode.setCommand": null, + "advMode.setCommand.success": null, + "advMode.command": null, + "advMode.nearestPlayer": null, + "advMode.randomPlayer": null, + "advMode.allPlayers": null, + "advMode.allEntities": null, + "advMode.self": null, + "advMode.previousOutput": null, + "advMode.mode.sequence": null, + "advMode.mode.auto": null, + "advMode.mode.redstone": null, + "advMode.mode.conditional": null, + "advMode.mode.unconditional": null, + "advMode.mode.redstoneTriggered": null, + "advMode.mode.autoexec.bat": null, + "advMode.notEnabled": null, + "advMode.notAllowed": null, + "mount.onboard": null, + "build.tooHigh": null, + "item.modifiers.mainhand": null, + "item.modifiers.offhand": null, + "item.modifiers.feet": null, + "item.modifiers.legs": null, + "item.modifiers.chest": null, + "item.modifiers.head": null, + "attribute.modifier.plus.0": null, + "attribute.modifier.plus.1": null, + "attribute.modifier.plus.2": "attribute.modifier.plus.1", + "attribute.modifier.take.0": null, + "attribute.modifier.take.1": null, + "attribute.modifier.take.2": "attribute.modifier.take.1", + "attribute.modifier.equals.0": "translation.test.args", + "attribute.modifier.equals.1": null, + "attribute.modifier.equals.2": "attribute.modifier.equals.1", + "attribute.name.horse.jumpStrength": null, + "attribute.name.zombie.spawnReinforcements": null, + "attribute.name.generic.maxHealth": null, + "attribute.name.generic.followRange": null, + "attribute.name.generic.knockbackResistance": null, + "attribute.name.generic.movementSpeed": "effect.minecraft.speed", + "attribute.name.generic.attackDamage": null, + "attribute.name.generic.attackSpeed": null, + "attribute.name.generic.luck": "effect.minecraft.luck", + "attribute.name.generic.armor": null, + "attribute.name.generic.armorToughness": null, + "screenshot.success": null, + "screenshot.failure": null, + "item.banner.black.name": "block.minecraft.black_banner", + "item.banner.red.name": "block.minecraft.red_banner", + "item.banner.green.name": "block.minecraft.green_banner", + "item.banner.brown.name": "block.minecraft.brown_banner", + "item.banner.blue.name": "block.minecraft.blue_banner", + "item.banner.purple.name": "block.minecraft.purple_banner", + "item.banner.cyan.name": "block.minecraft.cyan_banner", + "item.banner.silver.name": "block.minecraft.light_gray_banner", + "item.banner.gray.name": "block.minecraft.gray_banner", + "item.banner.pink.name": "block.minecraft.pink_banner", + "item.banner.lime.name": "block.minecraft.lime_banner", + "item.banner.yellow.name": "block.minecraft.yellow_banner", + "item.banner.lightBlue.name": "block.minecraft.light_blue_banner", + "item.banner.magenta.name": "block.minecraft.magenta_banner", + "item.banner.orange.name": "block.minecraft.orange_banner", + "item.banner.white.name": "block.minecraft.white_banner", + "item.shield.name": "item.minecraft.shield", + "item.shield.black.name": "item.minecraft.shield.black", + "item.shield.red.name": "item.minecraft.shield.red", + "item.shield.green.name": "item.minecraft.shield.green", + "item.shield.brown.name": "item.minecraft.shield.brown", + "item.shield.blue.name": "item.minecraft.shield.blue", + "item.shield.purple.name": "item.minecraft.shield.purple", + "item.shield.cyan.name": "item.minecraft.shield.cyan", + "item.shield.silver.name": "item.minecraft.shield.light_gray", + "item.shield.gray.name": "item.minecraft.shield.gray", + "item.shield.pink.name": "item.minecraft.shield.pink", + "item.shield.lime.name": "item.minecraft.shield.lime", + "item.shield.yellow.name": "item.minecraft.shield.yellow", + "item.shield.lightBlue.name": "item.minecraft.shield.light_blue", + "item.shield.magenta.name": "item.minecraft.shield.magenta", + "item.shield.orange.name": "item.minecraft.shield.orange", + "item.shield.white.name": "item.minecraft.shield.white", + "item.banner.square_bottom_left.black": "block.minecraft.banner.square_bottom_left.black", + "item.banner.square_bottom_left.red": "block.minecraft.banner.square_bottom_left.red", + "item.banner.square_bottom_left.green": "block.minecraft.banner.square_bottom_left.green", + "item.banner.square_bottom_left.brown": "block.minecraft.banner.square_bottom_left.brown", + "item.banner.square_bottom_left.blue": "block.minecraft.banner.square_bottom_left.blue", + "item.banner.square_bottom_left.purple": "block.minecraft.banner.square_bottom_left.purple", + "item.banner.square_bottom_left.cyan": "block.minecraft.banner.square_bottom_left.cyan", + "item.banner.square_bottom_left.silver": "block.minecraft.banner.square_bottom_left.light_gray", + "item.banner.square_bottom_left.gray": "block.minecraft.banner.square_bottom_left.gray", + "item.banner.square_bottom_left.pink": "block.minecraft.banner.square_bottom_left.pink", + "item.banner.square_bottom_left.lime": "block.minecraft.banner.square_bottom_left.lime", + "item.banner.square_bottom_left.yellow": "block.minecraft.banner.square_bottom_left.yellow", + "item.banner.square_bottom_left.lightBlue": "block.minecraft.banner.square_bottom_left.light_blue", + "item.banner.square_bottom_left.magenta": "block.minecraft.banner.square_bottom_left.magenta", + "item.banner.square_bottom_left.orange": "block.minecraft.banner.square_bottom_left.orange", + "item.banner.square_bottom_left.white": "block.minecraft.banner.square_bottom_left.white", + "item.banner.square_bottom_right.black": "block.minecraft.banner.square_bottom_right.black", + "item.banner.square_bottom_right.red": "block.minecraft.banner.square_bottom_right.red", + "item.banner.square_bottom_right.green": "block.minecraft.banner.square_bottom_right.green", + "item.banner.square_bottom_right.brown": "block.minecraft.banner.square_bottom_right.brown", + "item.banner.square_bottom_right.blue": "block.minecraft.banner.square_bottom_right.blue", + "item.banner.square_bottom_right.purple": "block.minecraft.banner.square_bottom_right.purple", + "item.banner.square_bottom_right.cyan": "block.minecraft.banner.square_bottom_right.cyan", + "item.banner.square_bottom_right.silver": "block.minecraft.banner.square_bottom_right.light_gray", + "item.banner.square_bottom_right.gray": "block.minecraft.banner.square_bottom_right.gray", + "item.banner.square_bottom_right.pink": "block.minecraft.banner.square_bottom_right.pink", + "item.banner.square_bottom_right.lime": "block.minecraft.banner.square_bottom_right.lime", + "item.banner.square_bottom_right.yellow": "block.minecraft.banner.square_bottom_right.yellow", + "item.banner.square_bottom_right.lightBlue": "block.minecraft.banner.square_bottom_right.light_blue", + "item.banner.square_bottom_right.magenta": "block.minecraft.banner.square_bottom_right.magenta", + "item.banner.square_bottom_right.orange": "block.minecraft.banner.square_bottom_right.orange", + "item.banner.square_bottom_right.white": "block.minecraft.banner.square_bottom_right.white", + "item.banner.square_top_left.black": "block.minecraft.banner.square_top_left.black", + "item.banner.square_top_left.red": "block.minecraft.banner.square_top_left.red", + "item.banner.square_top_left.green": "block.minecraft.banner.square_top_left.green", + "item.banner.square_top_left.brown": "block.minecraft.banner.square_top_left.brown", + "item.banner.square_top_left.blue": "block.minecraft.banner.square_top_left.blue", + "item.banner.square_top_left.purple": "block.minecraft.banner.square_top_left.purple", + "item.banner.square_top_left.cyan": "block.minecraft.banner.square_top_left.cyan", + "item.banner.square_top_left.silver": "block.minecraft.banner.square_top_left.light_gray", + "item.banner.square_top_left.gray": "block.minecraft.banner.square_top_left.gray", + "item.banner.square_top_left.pink": "block.minecraft.banner.square_top_left.pink", + "item.banner.square_top_left.lime": "block.minecraft.banner.square_top_left.lime", + "item.banner.square_top_left.yellow": "block.minecraft.banner.square_top_left.yellow", + "item.banner.square_top_left.lightBlue": "block.minecraft.banner.square_top_left.light_blue", + "item.banner.square_top_left.magenta": "block.minecraft.banner.square_top_left.magenta", + "item.banner.square_top_left.orange": "block.minecraft.banner.square_top_left.orange", + "item.banner.square_top_left.white": "block.minecraft.banner.square_top_left.white", + "item.banner.square_top_right.black": "block.minecraft.banner.square_top_right.black", + "item.banner.square_top_right.red": "block.minecraft.banner.square_top_right.red", + "item.banner.square_top_right.green": "block.minecraft.banner.square_top_right.green", + "item.banner.square_top_right.brown": "block.minecraft.banner.square_top_right.brown", + "item.banner.square_top_right.blue": "block.minecraft.banner.square_top_right.blue", + "item.banner.square_top_right.purple": "block.minecraft.banner.square_top_right.purple", + "item.banner.square_top_right.cyan": "block.minecraft.banner.square_top_right.cyan", + "item.banner.square_top_right.silver": "block.minecraft.banner.square_top_right.light_gray", + "item.banner.square_top_right.gray": "block.minecraft.banner.square_top_right.gray", + "item.banner.square_top_right.pink": "block.minecraft.banner.square_top_right.pink", + "item.banner.square_top_right.lime": "block.minecraft.banner.square_top_right.lime", + "item.banner.square_top_right.yellow": "block.minecraft.banner.square_top_right.yellow", + "item.banner.square_top_right.lightBlue": "block.minecraft.banner.square_top_right.light_blue", + "item.banner.square_top_right.magenta": "block.minecraft.banner.square_top_right.magenta", + "item.banner.square_top_right.orange": "block.minecraft.banner.square_top_right.orange", + "item.banner.square_top_right.white": "block.minecraft.banner.square_top_right.white", + "item.banner.stripe_bottom.black": "block.minecraft.banner.stripe_bottom.black", + "item.banner.stripe_bottom.red": "block.minecraft.banner.stripe_bottom.red", + "item.banner.stripe_bottom.green": "block.minecraft.banner.stripe_bottom.green", + "item.banner.stripe_bottom.brown": "block.minecraft.banner.stripe_bottom.brown", + "item.banner.stripe_bottom.blue": "block.minecraft.banner.stripe_bottom.blue", + "item.banner.stripe_bottom.purple": "block.minecraft.banner.stripe_bottom.purple", + "item.banner.stripe_bottom.cyan": "block.minecraft.banner.stripe_bottom.cyan", + "item.banner.stripe_bottom.silver": "block.minecraft.banner.stripe_bottom.light_gray", + "item.banner.stripe_bottom.gray": "block.minecraft.banner.stripe_bottom.gray", + "item.banner.stripe_bottom.pink": "block.minecraft.banner.stripe_bottom.pink", + "item.banner.stripe_bottom.lime": "block.minecraft.banner.stripe_bottom.lime", + "item.banner.stripe_bottom.yellow": "block.minecraft.banner.stripe_bottom.yellow", + "item.banner.stripe_bottom.lightBlue": "block.minecraft.banner.stripe_bottom.light_blue", + "item.banner.stripe_bottom.magenta": "block.minecraft.banner.stripe_bottom.magenta", + "item.banner.stripe_bottom.orange": "block.minecraft.banner.stripe_bottom.orange", + "item.banner.stripe_bottom.white": "block.minecraft.banner.stripe_bottom.white", + "item.banner.stripe_top.black": "block.minecraft.banner.stripe_top.black", + "item.banner.stripe_top.red": "block.minecraft.banner.stripe_top.red", + "item.banner.stripe_top.green": "block.minecraft.banner.stripe_top.green", + "item.banner.stripe_top.brown": "block.minecraft.banner.stripe_top.brown", + "item.banner.stripe_top.blue": "block.minecraft.banner.stripe_top.blue", + "item.banner.stripe_top.purple": "block.minecraft.banner.stripe_top.purple", + "item.banner.stripe_top.cyan": "block.minecraft.banner.stripe_top.cyan", + "item.banner.stripe_top.silver": "block.minecraft.banner.stripe_top.light_gray", + "item.banner.stripe_top.gray": "block.minecraft.banner.stripe_top.gray", + "item.banner.stripe_top.pink": "block.minecraft.banner.stripe_top.pink", + "item.banner.stripe_top.lime": "block.minecraft.banner.stripe_top.lime", + "item.banner.stripe_top.yellow": "block.minecraft.banner.stripe_top.yellow", + "item.banner.stripe_top.lightBlue": "block.minecraft.banner.stripe_top.light_blue", + "item.banner.stripe_top.magenta": "block.minecraft.banner.stripe_top.magenta", + "item.banner.stripe_top.orange": "block.minecraft.banner.stripe_top.orange", + "item.banner.stripe_top.white": "block.minecraft.banner.stripe_top.white", + "item.banner.stripe_left.black": "block.minecraft.banner.stripe_left.black", + "item.banner.stripe_left.red": "block.minecraft.banner.stripe_left.red", + "item.banner.stripe_left.green": "block.minecraft.banner.stripe_left.green", + "item.banner.stripe_left.brown": "block.minecraft.banner.stripe_left.brown", + "item.banner.stripe_left.blue": "block.minecraft.banner.stripe_left.blue", + "item.banner.stripe_left.purple": "block.minecraft.banner.stripe_left.purple", + "item.banner.stripe_left.cyan": "block.minecraft.banner.stripe_left.cyan", + "item.banner.stripe_left.silver": "block.minecraft.banner.stripe_left.light_gray", + "item.banner.stripe_left.gray": "block.minecraft.banner.stripe_left.gray", + "item.banner.stripe_left.pink": "block.minecraft.banner.stripe_left.pink", + "item.banner.stripe_left.lime": "block.minecraft.banner.stripe_left.lime", + "item.banner.stripe_left.yellow": "block.minecraft.banner.stripe_left.yellow", + "item.banner.stripe_left.lightBlue": "block.minecraft.banner.stripe_left.light_blue", + "item.banner.stripe_left.magenta": "block.minecraft.banner.stripe_left.magenta", + "item.banner.stripe_left.orange": "block.minecraft.banner.stripe_left.orange", + "item.banner.stripe_left.white": "block.minecraft.banner.stripe_left.white", + "item.banner.stripe_right.black": "block.minecraft.banner.stripe_right.black", + "item.banner.stripe_right.red": "block.minecraft.banner.stripe_right.red", + "item.banner.stripe_right.green": "block.minecraft.banner.stripe_right.green", + "item.banner.stripe_right.brown": "block.minecraft.banner.stripe_right.brown", + "item.banner.stripe_right.blue": "block.minecraft.banner.stripe_right.blue", + "item.banner.stripe_right.purple": "block.minecraft.banner.stripe_right.purple", + "item.banner.stripe_right.cyan": "block.minecraft.banner.stripe_right.cyan", + "item.banner.stripe_right.silver": "block.minecraft.banner.stripe_right.light_gray", + "item.banner.stripe_right.gray": "block.minecraft.banner.stripe_right.gray", + "item.banner.stripe_right.pink": "block.minecraft.banner.stripe_right.pink", + "item.banner.stripe_right.lime": "block.minecraft.banner.stripe_right.lime", + "item.banner.stripe_right.yellow": "block.minecraft.banner.stripe_right.yellow", + "item.banner.stripe_right.lightBlue": "block.minecraft.banner.stripe_right.light_blue", + "item.banner.stripe_right.magenta": "block.minecraft.banner.stripe_right.magenta", + "item.banner.stripe_right.orange": "block.minecraft.banner.stripe_right.orange", + "item.banner.stripe_right.white": "block.minecraft.banner.stripe_right.white", + "item.banner.stripe_center.black": "block.minecraft.banner.stripe_center.black", + "item.banner.stripe_center.red": "block.minecraft.banner.stripe_center.red", + "item.banner.stripe_center.green": "block.minecraft.banner.stripe_center.green", + "item.banner.stripe_center.brown": "block.minecraft.banner.stripe_center.brown", + "item.banner.stripe_center.blue": "block.minecraft.banner.stripe_center.blue", + "item.banner.stripe_center.purple": "block.minecraft.banner.stripe_center.purple", + "item.banner.stripe_center.cyan": "block.minecraft.banner.stripe_center.cyan", + "item.banner.stripe_center.silver": "block.minecraft.banner.stripe_center.light_gray", + "item.banner.stripe_center.gray": "block.minecraft.banner.stripe_center.gray", + "item.banner.stripe_center.pink": "block.minecraft.banner.stripe_center.pink", + "item.banner.stripe_center.lime": "block.minecraft.banner.stripe_center.lime", + "item.banner.stripe_center.yellow": "block.minecraft.banner.stripe_center.yellow", + "item.banner.stripe_center.lightBlue": "block.minecraft.banner.stripe_center.light_blue", + "item.banner.stripe_center.magenta": "block.minecraft.banner.stripe_center.magenta", + "item.banner.stripe_center.orange": "block.minecraft.banner.stripe_center.orange", + "item.banner.stripe_center.white": "block.minecraft.banner.stripe_center.white", + "item.banner.stripe_middle.black": "block.minecraft.banner.stripe_middle.black", + "item.banner.stripe_middle.red": "block.minecraft.banner.stripe_middle.red", + "item.banner.stripe_middle.green": "block.minecraft.banner.stripe_middle.green", + "item.banner.stripe_middle.brown": "block.minecraft.banner.stripe_middle.brown", + "item.banner.stripe_middle.blue": "block.minecraft.banner.stripe_middle.blue", + "item.banner.stripe_middle.purple": "block.minecraft.banner.stripe_middle.purple", + "item.banner.stripe_middle.cyan": "block.minecraft.banner.stripe_middle.cyan", + "item.banner.stripe_middle.silver": "block.minecraft.banner.stripe_middle.light_gray", + "item.banner.stripe_middle.gray": "block.minecraft.banner.stripe_middle.gray", + "item.banner.stripe_middle.pink": "block.minecraft.banner.stripe_middle.pink", + "item.banner.stripe_middle.lime": "block.minecraft.banner.stripe_middle.lime", + "item.banner.stripe_middle.yellow": "block.minecraft.banner.stripe_middle.yellow", + "item.banner.stripe_middle.lightBlue": "block.minecraft.banner.stripe_middle.light_blue", + "item.banner.stripe_middle.magenta": "block.minecraft.banner.stripe_middle.magenta", + "item.banner.stripe_middle.orange": "block.minecraft.banner.stripe_middle.orange", + "item.banner.stripe_middle.white": "block.minecraft.banner.stripe_middle.white", + "item.banner.stripe_downright.black": "block.minecraft.banner.stripe_downright.black", + "item.banner.stripe_downright.red": "block.minecraft.banner.stripe_downright.red", + "item.banner.stripe_downright.green": "block.minecraft.banner.stripe_downright.green", + "item.banner.stripe_downright.brown": "block.minecraft.banner.stripe_downright.brown", + "item.banner.stripe_downright.blue": "block.minecraft.banner.stripe_downright.blue", + "item.banner.stripe_downright.purple": "block.minecraft.banner.stripe_downright.purple", + "item.banner.stripe_downright.cyan": "block.minecraft.banner.stripe_downright.cyan", + "item.banner.stripe_downright.silver": "block.minecraft.banner.stripe_downright.light_gray", + "item.banner.stripe_downright.gray": "block.minecraft.banner.stripe_downright.gray", + "item.banner.stripe_downright.pink": "block.minecraft.banner.stripe_downright.pink", + "item.banner.stripe_downright.lime": "block.minecraft.banner.stripe_downright.lime", + "item.banner.stripe_downright.yellow": "block.minecraft.banner.stripe_downright.yellow", + "item.banner.stripe_downright.lightBlue": "block.minecraft.banner.stripe_downright.light_blue", + "item.banner.stripe_downright.magenta": "block.minecraft.banner.stripe_downright.magenta", + "item.banner.stripe_downright.orange": "block.minecraft.banner.stripe_downright.orange", + "item.banner.stripe_downright.white": "block.minecraft.banner.stripe_downright.white", + "item.banner.stripe_downleft.black": "block.minecraft.banner.stripe_downleft.black", + "item.banner.stripe_downleft.red": "block.minecraft.banner.stripe_downleft.red", + "item.banner.stripe_downleft.green": "block.minecraft.banner.stripe_downleft.green", + "item.banner.stripe_downleft.brown": "block.minecraft.banner.stripe_downleft.brown", + "item.banner.stripe_downleft.blue": "block.minecraft.banner.stripe_downleft.blue", + "item.banner.stripe_downleft.purple": "block.minecraft.banner.stripe_downleft.purple", + "item.banner.stripe_downleft.cyan": "block.minecraft.banner.stripe_downleft.cyan", + "item.banner.stripe_downleft.silver": "block.minecraft.banner.stripe_downleft.light_gray", + "item.banner.stripe_downleft.gray": "block.minecraft.banner.stripe_downleft.gray", + "item.banner.stripe_downleft.pink": "block.minecraft.banner.stripe_downleft.pink", + "item.banner.stripe_downleft.lime": "block.minecraft.banner.stripe_downleft.lime", + "item.banner.stripe_downleft.yellow": "block.minecraft.banner.stripe_downleft.yellow", + "item.banner.stripe_downleft.lightBlue": "block.minecraft.banner.stripe_downleft.light_blue", + "item.banner.stripe_downleft.magenta": "block.minecraft.banner.stripe_downleft.magenta", + "item.banner.stripe_downleft.orange": "block.minecraft.banner.stripe_downleft.orange", + "item.banner.stripe_downleft.white": "block.minecraft.banner.stripe_downleft.white", + "item.banner.small_stripes.black": "block.minecraft.banner.small_stripes.black", + "item.banner.small_stripes.red": "block.minecraft.banner.small_stripes.red", + "item.banner.small_stripes.green": "block.minecraft.banner.small_stripes.green", + "item.banner.small_stripes.brown": "block.minecraft.banner.small_stripes.brown", + "item.banner.small_stripes.blue": "block.minecraft.banner.small_stripes.blue", + "item.banner.small_stripes.purple": "block.minecraft.banner.small_stripes.purple", + "item.banner.small_stripes.cyan": "block.minecraft.banner.small_stripes.cyan", + "item.banner.small_stripes.silver": "block.minecraft.banner.small_stripes.light_gray", + "item.banner.small_stripes.gray": "block.minecraft.banner.small_stripes.gray", + "item.banner.small_stripes.pink": "block.minecraft.banner.small_stripes.pink", + "item.banner.small_stripes.lime": "block.minecraft.banner.small_stripes.lime", + "item.banner.small_stripes.yellow": "block.minecraft.banner.small_stripes.yellow", + "item.banner.small_stripes.lightBlue": "block.minecraft.banner.small_stripes.light_blue", + "item.banner.small_stripes.magenta": "block.minecraft.banner.small_stripes.magenta", + "item.banner.small_stripes.orange": "block.minecraft.banner.small_stripes.orange", + "item.banner.small_stripes.white": "block.minecraft.banner.small_stripes.white", + "item.banner.cross.black": "block.minecraft.banner.cross.black", + "item.banner.cross.red": "block.minecraft.banner.cross.red", + "item.banner.cross.green": "block.minecraft.banner.cross.green", + "item.banner.cross.brown": "block.minecraft.banner.cross.brown", + "item.banner.cross.blue": "block.minecraft.banner.cross.blue", + "item.banner.cross.purple": "block.minecraft.banner.cross.purple", + "item.banner.cross.cyan": "block.minecraft.banner.cross.cyan", + "item.banner.cross.silver": "block.minecraft.banner.cross.light_gray", + "item.banner.cross.gray": "block.minecraft.banner.cross.gray", + "item.banner.cross.pink": "block.minecraft.banner.cross.pink", + "item.banner.cross.lime": "block.minecraft.banner.cross.lime", + "item.banner.cross.yellow": "block.minecraft.banner.cross.yellow", + "item.banner.cross.lightBlue": "block.minecraft.banner.cross.light_blue", + "item.banner.cross.magenta": "block.minecraft.banner.cross.magenta", + "item.banner.cross.orange": "block.minecraft.banner.cross.orange", + "item.banner.cross.white": "block.minecraft.banner.cross.white", + "item.banner.triangle_bottom.black": "block.minecraft.banner.triangle_bottom.black", + "item.banner.triangle_bottom.red": "block.minecraft.banner.triangle_bottom.red", + "item.banner.triangle_bottom.green": "block.minecraft.banner.triangle_bottom.green", + "item.banner.triangle_bottom.brown": "block.minecraft.banner.triangle_bottom.brown", + "item.banner.triangle_bottom.blue": "block.minecraft.banner.triangle_bottom.blue", + "item.banner.triangle_bottom.purple": "block.minecraft.banner.triangle_bottom.purple", + "item.banner.triangle_bottom.cyan": "block.minecraft.banner.triangle_bottom.cyan", + "item.banner.triangle_bottom.silver": "block.minecraft.banner.triangle_bottom.light_gray", + "item.banner.triangle_bottom.gray": "block.minecraft.banner.triangle_bottom.gray", + "item.banner.triangle_bottom.pink": "block.minecraft.banner.triangle_bottom.pink", + "item.banner.triangle_bottom.lime": "block.minecraft.banner.triangle_bottom.lime", + "item.banner.triangle_bottom.yellow": "block.minecraft.banner.triangle_bottom.yellow", + "item.banner.triangle_bottom.lightBlue": "block.minecraft.banner.triangle_bottom.light_blue", + "item.banner.triangle_bottom.magenta": "block.minecraft.banner.triangle_bottom.magenta", + "item.banner.triangle_bottom.orange": "block.minecraft.banner.triangle_bottom.orange", + "item.banner.triangle_bottom.white": "block.minecraft.banner.triangle_bottom.white", + "item.banner.triangle_top.black": "block.minecraft.banner.triangle_top.black", + "item.banner.triangle_top.red": "block.minecraft.banner.triangle_top.red", + "item.banner.triangle_top.green": "block.minecraft.banner.triangle_top.green", + "item.banner.triangle_top.brown": "block.minecraft.banner.triangle_top.brown", + "item.banner.triangle_top.blue": "block.minecraft.banner.triangle_top.blue", + "item.banner.triangle_top.purple": "block.minecraft.banner.triangle_top.purple", + "item.banner.triangle_top.cyan": "block.minecraft.banner.triangle_top.cyan", + "item.banner.triangle_top.silver": "block.minecraft.banner.triangle_top.light_gray", + "item.banner.triangle_top.gray": "block.minecraft.banner.triangle_top.gray", + "item.banner.triangle_top.pink": "block.minecraft.banner.triangle_top.pink", + "item.banner.triangle_top.lime": "block.minecraft.banner.triangle_top.lime", + "item.banner.triangle_top.yellow": "block.minecraft.banner.triangle_top.yellow", + "item.banner.triangle_top.lightBlue": "block.minecraft.banner.triangle_top.light_blue", + "item.banner.triangle_top.magenta": "block.minecraft.banner.triangle_top.magenta", + "item.banner.triangle_top.orange": "block.minecraft.banner.triangle_top.orange", + "item.banner.triangle_top.white": "block.minecraft.banner.triangle_top.white", + "item.banner.triangles_bottom.black": "block.minecraft.banner.triangles_bottom.black", + "item.banner.triangles_bottom.red": "block.minecraft.banner.triangles_bottom.red", + "item.banner.triangles_bottom.green": "block.minecraft.banner.triangles_bottom.green", + "item.banner.triangles_bottom.brown": "block.minecraft.banner.triangles_bottom.brown", + "item.banner.triangles_bottom.blue": "block.minecraft.banner.triangles_bottom.blue", + "item.banner.triangles_bottom.purple": "block.minecraft.banner.triangles_bottom.purple", + "item.banner.triangles_bottom.cyan": "block.minecraft.banner.triangles_bottom.cyan", + "item.banner.triangles_bottom.silver": "block.minecraft.banner.triangles_bottom.light_gray", + "item.banner.triangles_bottom.gray": "block.minecraft.banner.triangles_bottom.gray", + "item.banner.triangles_bottom.pink": "block.minecraft.banner.triangles_bottom.pink", + "item.banner.triangles_bottom.lime": "block.minecraft.banner.triangles_bottom.lime", + "item.banner.triangles_bottom.yellow": "block.minecraft.banner.triangles_bottom.yellow", + "item.banner.triangles_bottom.lightBlue": "block.minecraft.banner.triangles_bottom.light_blue", + "item.banner.triangles_bottom.magenta": "block.minecraft.banner.triangles_bottom.magenta", + "item.banner.triangles_bottom.orange": "block.minecraft.banner.triangles_bottom.orange", + "item.banner.triangles_bottom.white": "block.minecraft.banner.triangles_bottom.white", + "item.banner.triangles_top.black": "block.minecraft.banner.triangles_top.black", + "item.banner.triangles_top.red": "block.minecraft.banner.triangles_top.red", + "item.banner.triangles_top.green": "block.minecraft.banner.triangles_top.green", + "item.banner.triangles_top.brown": "block.minecraft.banner.triangles_top.brown", + "item.banner.triangles_top.blue": "block.minecraft.banner.triangles_top.blue", + "item.banner.triangles_top.purple": "block.minecraft.banner.triangles_top.purple", + "item.banner.triangles_top.cyan": "block.minecraft.banner.triangles_top.cyan", + "item.banner.triangles_top.silver": "block.minecraft.banner.triangles_top.light_gray", + "item.banner.triangles_top.gray": "block.minecraft.banner.triangles_top.gray", + "item.banner.triangles_top.pink": "block.minecraft.banner.triangles_top.pink", + "item.banner.triangles_top.lime": "block.minecraft.banner.triangles_top.lime", + "item.banner.triangles_top.yellow": "block.minecraft.banner.triangles_top.yellow", + "item.banner.triangles_top.lightBlue": "block.minecraft.banner.triangles_top.light_blue", + "item.banner.triangles_top.magenta": "block.minecraft.banner.triangles_top.magenta", + "item.banner.triangles_top.orange": "block.minecraft.banner.triangles_top.orange", + "item.banner.triangles_top.white": "block.minecraft.banner.triangles_top.white", + "item.banner.diagonal_left.black": "block.minecraft.banner.diagonal_left.black", + "item.banner.diagonal_left.red": "block.minecraft.banner.diagonal_left.red", + "item.banner.diagonal_left.green": "block.minecraft.banner.diagonal_left.green", + "item.banner.diagonal_left.brown": "block.minecraft.banner.diagonal_left.brown", + "item.banner.diagonal_left.blue": "block.minecraft.banner.diagonal_left.blue", + "item.banner.diagonal_left.purple": "block.minecraft.banner.diagonal_left.purple", + "item.banner.diagonal_left.cyan": "block.minecraft.banner.diagonal_left.cyan", + "item.banner.diagonal_left.silver": "block.minecraft.banner.diagonal_left.light_gray", + "item.banner.diagonal_left.gray": "block.minecraft.banner.diagonal_left.gray", + "item.banner.diagonal_left.pink": "block.minecraft.banner.diagonal_left.pink", + "item.banner.diagonal_left.lime": "block.minecraft.banner.diagonal_left.lime", + "item.banner.diagonal_left.yellow": "block.minecraft.banner.diagonal_left.yellow", + "item.banner.diagonal_left.lightBlue": "block.minecraft.banner.diagonal_left.light_blue", + "item.banner.diagonal_left.magenta": "block.minecraft.banner.diagonal_left.magenta", + "item.banner.diagonal_left.orange": "block.minecraft.banner.diagonal_left.orange", + "item.banner.diagonal_left.white": "block.minecraft.banner.diagonal_left.white", + "item.banner.diagonal_right.black": "block.minecraft.banner.diagonal_right.black", + "item.banner.diagonal_right.red": "block.minecraft.banner.diagonal_right.red", + "item.banner.diagonal_right.green": "block.minecraft.banner.diagonal_right.green", + "item.banner.diagonal_right.brown": "block.minecraft.banner.diagonal_right.brown", + "item.banner.diagonal_right.blue": "block.minecraft.banner.diagonal_right.blue", + "item.banner.diagonal_right.purple": "block.minecraft.banner.diagonal_right.purple", + "item.banner.diagonal_right.cyan": "block.minecraft.banner.diagonal_right.cyan", + "item.banner.diagonal_right.silver": "block.minecraft.banner.diagonal_right.light_gray", + "item.banner.diagonal_right.gray": "block.minecraft.banner.diagonal_right.gray", + "item.banner.diagonal_right.pink": "block.minecraft.banner.diagonal_right.pink", + "item.banner.diagonal_right.lime": "block.minecraft.banner.diagonal_right.lime", + "item.banner.diagonal_right.yellow": "block.minecraft.banner.diagonal_right.yellow", + "item.banner.diagonal_right.lightBlue": "block.minecraft.banner.diagonal_right.light_blue", + "item.banner.diagonal_right.magenta": "block.minecraft.banner.diagonal_right.magenta", + "item.banner.diagonal_right.orange": "block.minecraft.banner.diagonal_right.orange", + "item.banner.diagonal_right.white": "block.minecraft.banner.diagonal_right.white", + "item.banner.diagonal_up_left.black": "block.minecraft.banner.diagonal_up_left.black", + "item.banner.diagonal_up_left.red": "block.minecraft.banner.diagonal_up_left.red", + "item.banner.diagonal_up_left.green": "block.minecraft.banner.diagonal_up_left.green", + "item.banner.diagonal_up_left.brown": "block.minecraft.banner.diagonal_up_left.brown", + "item.banner.diagonal_up_left.blue": "block.minecraft.banner.diagonal_up_left.blue", + "item.banner.diagonal_up_left.purple": "block.minecraft.banner.diagonal_up_left.purple", + "item.banner.diagonal_up_left.cyan": "block.minecraft.banner.diagonal_up_left.cyan", + "item.banner.diagonal_up_left.silver": "block.minecraft.banner.diagonal_up_left.light_gray", + "item.banner.diagonal_up_left.gray": "block.minecraft.banner.diagonal_up_left.gray", + "item.banner.diagonal_up_left.pink": "block.minecraft.banner.diagonal_up_left.pink", + "item.banner.diagonal_up_left.lime": "block.minecraft.banner.diagonal_up_left.lime", + "item.banner.diagonal_up_left.yellow": "block.minecraft.banner.diagonal_up_left.yellow", + "item.banner.diagonal_up_left.lightBlue": "block.minecraft.banner.diagonal_up_left.light_blue", + "item.banner.diagonal_up_left.magenta": "block.minecraft.banner.diagonal_up_left.magenta", + "item.banner.diagonal_up_left.orange": "block.minecraft.banner.diagonal_up_left.orange", + "item.banner.diagonal_up_left.white": "block.minecraft.banner.diagonal_up_left.white", + "item.banner.diagonal_up_right.black": "block.minecraft.banner.diagonal_up_right.black", + "item.banner.diagonal_up_right.red": "block.minecraft.banner.diagonal_up_right.red", + "item.banner.diagonal_up_right.green": "block.minecraft.banner.diagonal_up_right.green", + "item.banner.diagonal_up_right.brown": "block.minecraft.banner.diagonal_up_right.brown", + "item.banner.diagonal_up_right.blue": "block.minecraft.banner.diagonal_up_right.blue", + "item.banner.diagonal_up_right.purple": "block.minecraft.banner.diagonal_up_right.purple", + "item.banner.diagonal_up_right.cyan": "block.minecraft.banner.diagonal_up_right.cyan", + "item.banner.diagonal_up_right.silver": "block.minecraft.banner.diagonal_up_right.light_gray", + "item.banner.diagonal_up_right.gray": "block.minecraft.banner.diagonal_up_right.gray", + "item.banner.diagonal_up_right.pink": "block.minecraft.banner.diagonal_up_right.pink", + "item.banner.diagonal_up_right.lime": "block.minecraft.banner.diagonal_up_right.lime", + "item.banner.diagonal_up_right.yellow": "block.minecraft.banner.diagonal_up_right.yellow", + "item.banner.diagonal_up_right.lightBlue": "block.minecraft.banner.diagonal_up_right.light_blue", + "item.banner.diagonal_up_right.magenta": "block.minecraft.banner.diagonal_up_right.magenta", + "item.banner.diagonal_up_right.orange": "block.minecraft.banner.diagonal_up_right.orange", + "item.banner.diagonal_up_right.white": "block.minecraft.banner.diagonal_up_right.white", + "item.banner.circle.black": "block.minecraft.banner.circle.black", + "item.banner.circle.red": "block.minecraft.banner.circle.red", + "item.banner.circle.green": "block.minecraft.banner.circle.green", + "item.banner.circle.brown": "block.minecraft.banner.circle.brown", + "item.banner.circle.blue": "block.minecraft.banner.circle.blue", + "item.banner.circle.purple": "block.minecraft.banner.circle.purple", + "item.banner.circle.cyan": "block.minecraft.banner.circle.cyan", + "item.banner.circle.silver": "block.minecraft.banner.circle.light_gray", + "item.banner.circle.gray": "block.minecraft.banner.circle.gray", + "item.banner.circle.pink": "block.minecraft.banner.circle.pink", + "item.banner.circle.lime": "block.minecraft.banner.circle.lime", + "item.banner.circle.yellow": "block.minecraft.banner.circle.yellow", + "item.banner.circle.lightBlue": "block.minecraft.banner.circle.light_blue", + "item.banner.circle.magenta": "block.minecraft.banner.circle.magenta", + "item.banner.circle.orange": "block.minecraft.banner.circle.orange", + "item.banner.circle.white": "block.minecraft.banner.circle.white", + "item.banner.rhombus.black": "block.minecraft.banner.rhombus.black", + "item.banner.rhombus.red": "block.minecraft.banner.rhombus.red", + "item.banner.rhombus.green": "block.minecraft.banner.rhombus.green", + "item.banner.rhombus.brown": "block.minecraft.banner.rhombus.brown", + "item.banner.rhombus.blue": "block.minecraft.banner.rhombus.blue", + "item.banner.rhombus.purple": "block.minecraft.banner.rhombus.purple", + "item.banner.rhombus.cyan": "block.minecraft.banner.rhombus.cyan", + "item.banner.rhombus.silver": "block.minecraft.banner.rhombus.light_gray", + "item.banner.rhombus.gray": "block.minecraft.banner.rhombus.gray", + "item.banner.rhombus.pink": "block.minecraft.banner.rhombus.pink", + "item.banner.rhombus.lime": "block.minecraft.banner.rhombus.lime", + "item.banner.rhombus.yellow": "block.minecraft.banner.rhombus.yellow", + "item.banner.rhombus.lightBlue": "block.minecraft.banner.rhombus.light_blue", + "item.banner.rhombus.magenta": "block.minecraft.banner.rhombus.magenta", + "item.banner.rhombus.orange": "block.minecraft.banner.rhombus.orange", + "item.banner.rhombus.white": "block.minecraft.banner.rhombus.white", + "item.banner.half_vertical.black": "block.minecraft.banner.half_vertical.black", + "item.banner.half_vertical.red": "block.minecraft.banner.half_vertical.red", + "item.banner.half_vertical.green": "block.minecraft.banner.half_vertical.green", + "item.banner.half_vertical.brown": "block.minecraft.banner.half_vertical.brown", + "item.banner.half_vertical.blue": "block.minecraft.banner.half_vertical.blue", + "item.banner.half_vertical.purple": "block.minecraft.banner.half_vertical.purple", + "item.banner.half_vertical.cyan": "block.minecraft.banner.half_vertical.cyan", + "item.banner.half_vertical.silver": "block.minecraft.banner.half_vertical.light_gray", + "item.banner.half_vertical.gray": "block.minecraft.banner.half_vertical.gray", + "item.banner.half_vertical.pink": "block.minecraft.banner.half_vertical.pink", + "item.banner.half_vertical.lime": "block.minecraft.banner.half_vertical.lime", + "item.banner.half_vertical.yellow": "block.minecraft.banner.half_vertical.yellow", + "item.banner.half_vertical.lightBlue": "block.minecraft.banner.half_vertical.light_blue", + "item.banner.half_vertical.magenta": "block.minecraft.banner.half_vertical.magenta", + "item.banner.half_vertical.orange": "block.minecraft.banner.half_vertical.orange", + "item.banner.half_vertical.white": "block.minecraft.banner.half_vertical.white", + "item.banner.half_horizontal.black": "block.minecraft.banner.half_horizontal.black", + "item.banner.half_horizontal.red": "block.minecraft.banner.half_horizontal.red", + "item.banner.half_horizontal.green": "block.minecraft.banner.half_horizontal.green", + "item.banner.half_horizontal.brown": "block.minecraft.banner.half_horizontal.brown", + "item.banner.half_horizontal.blue": "block.minecraft.banner.half_horizontal.blue", + "item.banner.half_horizontal.purple": "block.minecraft.banner.half_horizontal.purple", + "item.banner.half_horizontal.cyan": "block.minecraft.banner.half_horizontal.cyan", + "item.banner.half_horizontal.silver": "block.minecraft.banner.half_horizontal.light_gray", + "item.banner.half_horizontal.gray": "block.minecraft.banner.half_horizontal.gray", + "item.banner.half_horizontal.pink": "block.minecraft.banner.half_horizontal.pink", + "item.banner.half_horizontal.lime": "block.minecraft.banner.half_horizontal.lime", + "item.banner.half_horizontal.yellow": "block.minecraft.banner.half_horizontal.yellow", + "item.banner.half_horizontal.lightBlue": "block.minecraft.banner.half_horizontal.light_blue", + "item.banner.half_horizontal.magenta": "block.minecraft.banner.half_horizontal.magenta", + "item.banner.half_horizontal.orange": "block.minecraft.banner.half_horizontal.orange", + "item.banner.half_horizontal.white": "block.minecraft.banner.half_horizontal.white", + "item.banner.half_vertical_right.black": "block.minecraft.banner.half_vertical_right.black", + "item.banner.half_vertical_right.red": "block.minecraft.banner.half_vertical_right.red", + "item.banner.half_vertical_right.green": "block.minecraft.banner.half_vertical_right.green", + "item.banner.half_vertical_right.brown": "block.minecraft.banner.half_vertical_right.brown", + "item.banner.half_vertical_right.blue": "block.minecraft.banner.half_vertical_right.blue", + "item.banner.half_vertical_right.purple": "block.minecraft.banner.half_vertical_right.purple", + "item.banner.half_vertical_right.cyan": "block.minecraft.banner.half_vertical_right.cyan", + "item.banner.half_vertical_right.silver": "block.minecraft.banner.half_vertical_right.light_gray", + "item.banner.half_vertical_right.gray": "block.minecraft.banner.half_vertical_right.gray", + "item.banner.half_vertical_right.pink": "block.minecraft.banner.half_vertical_right.pink", + "item.banner.half_vertical_right.lime": "block.minecraft.banner.half_vertical_right.lime", + "item.banner.half_vertical_right.yellow": "block.minecraft.banner.half_vertical_right.yellow", + "item.banner.half_vertical_right.lightBlue": "block.minecraft.banner.half_vertical_right.light_blue", + "item.banner.half_vertical_right.magenta": "block.minecraft.banner.half_vertical_right.magenta", + "item.banner.half_vertical_right.orange": "block.minecraft.banner.half_vertical_right.orange", + "item.banner.half_vertical_right.white": "block.minecraft.banner.half_vertical_right.white", + "item.banner.half_horizontal_bottom.black": "block.minecraft.banner.half_horizontal_bottom.black", + "item.banner.half_horizontal_bottom.red": "block.minecraft.banner.half_horizontal_bottom.red", + "item.banner.half_horizontal_bottom.green": "block.minecraft.banner.half_horizontal_bottom.green", + "item.banner.half_horizontal_bottom.brown": "block.minecraft.banner.half_horizontal_bottom.brown", + "item.banner.half_horizontal_bottom.blue": "block.minecraft.banner.half_horizontal_bottom.blue", + "item.banner.half_horizontal_bottom.purple": "block.minecraft.banner.half_horizontal_bottom.purple", + "item.banner.half_horizontal_bottom.cyan": "block.minecraft.banner.half_horizontal_bottom.cyan", + "item.banner.half_horizontal_bottom.silver": "block.minecraft.banner.half_horizontal_bottom.light_gray", + "item.banner.half_horizontal_bottom.gray": "block.minecraft.banner.half_horizontal_bottom.gray", + "item.banner.half_horizontal_bottom.pink": "block.minecraft.banner.half_horizontal_bottom.pink", + "item.banner.half_horizontal_bottom.lime": "block.minecraft.banner.half_horizontal_bottom.lime", + "item.banner.half_horizontal_bottom.yellow": "block.minecraft.banner.half_horizontal_bottom.yellow", + "item.banner.half_horizontal_bottom.lightBlue": "block.minecraft.banner.half_horizontal_bottom.light_blue", + "item.banner.half_horizontal_bottom.magenta": "block.minecraft.banner.half_horizontal_bottom.magenta", + "item.banner.half_horizontal_bottom.orange": "block.minecraft.banner.half_horizontal_bottom.orange", + "item.banner.half_horizontal_bottom.white": "block.minecraft.banner.half_horizontal_bottom.white", + "item.banner.creeper.black": "block.minecraft.banner.creeper.black", + "item.banner.creeper.red": "block.minecraft.banner.creeper.red", + "item.banner.creeper.green": "block.minecraft.banner.creeper.green", + "item.banner.creeper.brown": "block.minecraft.banner.creeper.brown", + "item.banner.creeper.blue": "block.minecraft.banner.creeper.blue", + "item.banner.creeper.purple": "block.minecraft.banner.creeper.purple", + "item.banner.creeper.cyan": "block.minecraft.banner.creeper.cyan", + "item.banner.creeper.silver": "block.minecraft.banner.creeper.light_gray", + "item.banner.creeper.gray": "block.minecraft.banner.creeper.gray", + "item.banner.creeper.pink": "block.minecraft.banner.creeper.pink", + "item.banner.creeper.lime": "block.minecraft.banner.creeper.lime", + "item.banner.creeper.yellow": "block.minecraft.banner.creeper.yellow", + "item.banner.creeper.lightBlue": "block.minecraft.banner.creeper.light_blue", + "item.banner.creeper.magenta": "block.minecraft.banner.creeper.magenta", + "item.banner.creeper.orange": "block.minecraft.banner.creeper.orange", + "item.banner.creeper.white": "block.minecraft.banner.creeper.white", + "item.banner.bricks.black": "block.minecraft.banner.bricks.black", + "item.banner.bricks.red": "block.minecraft.banner.bricks.red", + "item.banner.bricks.green": "block.minecraft.banner.bricks.green", + "item.banner.bricks.brown": "block.minecraft.banner.bricks.brown", + "item.banner.bricks.blue": "block.minecraft.banner.bricks.blue", + "item.banner.bricks.purple": "block.minecraft.banner.bricks.purple", + "item.banner.bricks.cyan": "block.minecraft.banner.bricks.cyan", + "item.banner.bricks.silver": "block.minecraft.banner.bricks.light_gray", + "item.banner.bricks.gray": "block.minecraft.banner.bricks.gray", + "item.banner.bricks.pink": "block.minecraft.banner.bricks.pink", + "item.banner.bricks.lime": "block.minecraft.banner.bricks.lime", + "item.banner.bricks.yellow": "block.minecraft.banner.bricks.yellow", + "item.banner.bricks.lightBlue": "block.minecraft.banner.bricks.light_blue", + "item.banner.bricks.magenta": "block.minecraft.banner.bricks.magenta", + "item.banner.bricks.orange": "block.minecraft.banner.bricks.orange", + "item.banner.bricks.white": "block.minecraft.banner.bricks.white", + "item.banner.gradient.black": "block.minecraft.banner.gradient.black", + "item.banner.gradient.red": "block.minecraft.banner.gradient.red", + "item.banner.gradient.green": "block.minecraft.banner.gradient.green", + "item.banner.gradient.brown": "block.minecraft.banner.gradient.brown", + "item.banner.gradient.blue": "block.minecraft.banner.gradient.blue", + "item.banner.gradient.purple": "block.minecraft.banner.gradient.purple", + "item.banner.gradient.cyan": "block.minecraft.banner.gradient.cyan", + "item.banner.gradient.silver": "block.minecraft.banner.gradient.light_gray", + "item.banner.gradient.gray": "block.minecraft.banner.gradient.gray", + "item.banner.gradient.pink": "block.minecraft.banner.gradient.pink", + "item.banner.gradient.lime": "block.minecraft.banner.gradient.lime", + "item.banner.gradient.yellow": "block.minecraft.banner.gradient.yellow", + "item.banner.gradient.lightBlue": "block.minecraft.banner.gradient.light_blue", + "item.banner.gradient.magenta": "block.minecraft.banner.gradient.magenta", + "item.banner.gradient.orange": "block.minecraft.banner.gradient.orange", + "item.banner.gradient.white": "block.minecraft.banner.gradient.white", + "item.banner.gradient_up.black": "block.minecraft.banner.gradient_up.black", + "item.banner.gradient_up.red": "block.minecraft.banner.gradient_up.red", + "item.banner.gradient_up.green": "block.minecraft.banner.gradient_up.green", + "item.banner.gradient_up.brown": "block.minecraft.banner.gradient_up.brown", + "item.banner.gradient_up.blue": "block.minecraft.banner.gradient_up.blue", + "item.banner.gradient_up.purple": "block.minecraft.banner.gradient_up.purple", + "item.banner.gradient_up.cyan": "block.minecraft.banner.gradient_up.cyan", + "item.banner.gradient_up.silver": "block.minecraft.banner.gradient_up.light_gray", + "item.banner.gradient_up.gray": "block.minecraft.banner.gradient_up.gray", + "item.banner.gradient_up.pink": "block.minecraft.banner.gradient_up.pink", + "item.banner.gradient_up.lime": "block.minecraft.banner.gradient_up.lime", + "item.banner.gradient_up.yellow": "block.minecraft.banner.gradient_up.yellow", + "item.banner.gradient_up.lightBlue": "block.minecraft.banner.gradient_up.light_blue", + "item.banner.gradient_up.magenta": "block.minecraft.banner.gradient_up.magenta", + "item.banner.gradient_up.orange": "block.minecraft.banner.gradient_up.orange", + "item.banner.gradient_up.white": "block.minecraft.banner.gradient_up.white", + "item.banner.skull.black": "block.minecraft.banner.skull.black", + "item.banner.skull.red": "block.minecraft.banner.skull.red", + "item.banner.skull.green": "block.minecraft.banner.skull.green", + "item.banner.skull.brown": "block.minecraft.banner.skull.brown", + "item.banner.skull.blue": "block.minecraft.banner.skull.blue", + "item.banner.skull.purple": "block.minecraft.banner.skull.purple", + "item.banner.skull.cyan": "block.minecraft.banner.skull.cyan", + "item.banner.skull.silver": "block.minecraft.banner.skull.light_gray", + "item.banner.skull.gray": "block.minecraft.banner.skull.gray", + "item.banner.skull.pink": "block.minecraft.banner.skull.pink", + "item.banner.skull.lime": "block.minecraft.banner.skull.lime", + "item.banner.skull.yellow": "block.minecraft.banner.skull.yellow", + "item.banner.skull.lightBlue": "block.minecraft.banner.skull.light_blue", + "item.banner.skull.magenta": "block.minecraft.banner.skull.magenta", + "item.banner.skull.orange": "block.minecraft.banner.skull.orange", + "item.banner.skull.white": "block.minecraft.banner.skull.white", + "item.banner.flower.black": "block.minecraft.banner.flower.black", + "item.banner.flower.red": "block.minecraft.banner.flower.red", + "item.banner.flower.green": "block.minecraft.banner.flower.green", + "item.banner.flower.brown": "block.minecraft.banner.flower.brown", + "item.banner.flower.blue": "block.minecraft.banner.flower.blue", + "item.banner.flower.purple": "block.minecraft.banner.flower.purple", + "item.banner.flower.cyan": "block.minecraft.banner.flower.cyan", + "item.banner.flower.silver": "block.minecraft.banner.flower.light_gray", + "item.banner.flower.gray": "block.minecraft.banner.flower.gray", + "item.banner.flower.pink": "block.minecraft.banner.flower.pink", + "item.banner.flower.lime": "block.minecraft.banner.flower.lime", + "item.banner.flower.yellow": "block.minecraft.banner.flower.yellow", + "item.banner.flower.lightBlue": "block.minecraft.banner.flower.light_blue", + "item.banner.flower.magenta": "block.minecraft.banner.flower.magenta", + "item.banner.flower.orange": "block.minecraft.banner.flower.orange", + "item.banner.flower.white": "block.minecraft.banner.flower.white", + "item.banner.border.black": "block.minecraft.banner.border.black", + "item.banner.border.red": "block.minecraft.banner.border.red", + "item.banner.border.green": "block.minecraft.banner.border.green", + "item.banner.border.brown": "block.minecraft.banner.border.brown", + "item.banner.border.blue": "block.minecraft.banner.border.blue", + "item.banner.border.purple": "block.minecraft.banner.border.purple", + "item.banner.border.cyan": "block.minecraft.banner.border.cyan", + "item.banner.border.silver": "block.minecraft.banner.border.light_gray", + "item.banner.border.gray": "block.minecraft.banner.border.gray", + "item.banner.border.pink": "block.minecraft.banner.border.pink", + "item.banner.border.lime": "block.minecraft.banner.border.lime", + "item.banner.border.yellow": "block.minecraft.banner.border.yellow", + "item.banner.border.lightBlue": "block.minecraft.banner.border.light_blue", + "item.banner.border.magenta": "block.minecraft.banner.border.magenta", + "item.banner.border.orange": "block.minecraft.banner.border.orange", + "item.banner.border.white": "block.minecraft.banner.border.white", + "item.banner.curly_border.black": "block.minecraft.banner.curly_border.black", + "item.banner.curly_border.red": "block.minecraft.banner.curly_border.red", + "item.banner.curly_border.green": "block.minecraft.banner.curly_border.green", + "item.banner.curly_border.brown": "block.minecraft.banner.curly_border.brown", + "item.banner.curly_border.blue": "block.minecraft.banner.curly_border.blue", + "item.banner.curly_border.purple": "block.minecraft.banner.curly_border.purple", + "item.banner.curly_border.cyan": "block.minecraft.banner.curly_border.cyan", + "item.banner.curly_border.silver": "block.minecraft.banner.curly_border.light_gray", + "item.banner.curly_border.gray": "block.minecraft.banner.curly_border.gray", + "item.banner.curly_border.pink": "block.minecraft.banner.curly_border.pink", + "item.banner.curly_border.lime": "block.minecraft.banner.curly_border.lime", + "item.banner.curly_border.yellow": "block.minecraft.banner.curly_border.yellow", + "item.banner.curly_border.lightBlue": "block.minecraft.banner.curly_border.light_blue", + "item.banner.curly_border.magenta": "block.minecraft.banner.curly_border.magenta", + "item.banner.curly_border.orange": "block.minecraft.banner.curly_border.orange", + "item.banner.curly_border.white": "block.minecraft.banner.curly_border.white", + "item.banner.mojang.black": "block.minecraft.banner.mojang.black", + "item.banner.mojang.red": "block.minecraft.banner.mojang.red", + "item.banner.mojang.green": "block.minecraft.banner.mojang.green", + "item.banner.mojang.brown": "block.minecraft.banner.mojang.brown", + "item.banner.mojang.blue": "block.minecraft.banner.mojang.blue", + "item.banner.mojang.purple": "block.minecraft.banner.mojang.purple", + "item.banner.mojang.cyan": "block.minecraft.banner.mojang.cyan", + "item.banner.mojang.silver": "block.minecraft.banner.mojang.light_gray", + "item.banner.mojang.gray": "block.minecraft.banner.mojang.gray", + "item.banner.mojang.pink": "block.minecraft.banner.mojang.pink", + "item.banner.mojang.lime": "block.minecraft.banner.mojang.lime", + "item.banner.mojang.yellow": "block.minecraft.banner.mojang.yellow", + "item.banner.mojang.lightBlue": "block.minecraft.banner.mojang.light_blue", + "item.banner.mojang.magenta": "block.minecraft.banner.mojang.magenta", + "item.banner.mojang.orange": "block.minecraft.banner.mojang.orange", + "item.banner.mojang.white": "block.minecraft.banner.mojang.white", + "item.banner.straight_cross.black": "block.minecraft.banner.straight_cross.black", + "item.banner.straight_cross.red": "block.minecraft.banner.straight_cross.red", + "item.banner.straight_cross.green": "block.minecraft.banner.straight_cross.green", + "item.banner.straight_cross.brown": "block.minecraft.banner.straight_cross.brown", + "item.banner.straight_cross.blue": "block.minecraft.banner.straight_cross.blue", + "item.banner.straight_cross.purple": "block.minecraft.banner.straight_cross.purple", + "item.banner.straight_cross.cyan": "block.minecraft.banner.straight_cross.cyan", + "item.banner.straight_cross.silver": "block.minecraft.banner.straight_cross.light_gray", + "item.banner.straight_cross.gray": "block.minecraft.banner.straight_cross.gray", + "item.banner.straight_cross.pink": "block.minecraft.banner.straight_cross.pink", + "item.banner.straight_cross.lime": "block.minecraft.banner.straight_cross.lime", + "item.banner.straight_cross.yellow": "block.minecraft.banner.straight_cross.yellow", + "item.banner.straight_cross.lightBlue": "block.minecraft.banner.straight_cross.light_blue", + "item.banner.straight_cross.magenta": "block.minecraft.banner.straight_cross.magenta", + "item.banner.straight_cross.orange": "block.minecraft.banner.straight_cross.orange", + "item.banner.straight_cross.white": "block.minecraft.banner.straight_cross.white", + "subtitles.ambient.cave": null, + "subtitles.block.anvil.destroy": null, + "subtitles.block.anvil.land": null, + "subtitles.block.anvil.use": null, + "subtitles.block.brewing_stand.brew": null, + "subtitles.block.button.click": null, + "subtitles.block.chest.close": null, + "subtitles.block.chest.locked": null, + "subtitles.block.chest.open": null, + "subtitles.block.chorus_flower.death": null, + "subtitles.block.chorus_flower.grow": null, + "subtitles.block.comparator.click": null, + "subtitles.block.dispenser.dispense": null, + "subtitles.block.dispenser.fail": null, + "subtitles.block.door.toggle": null, + "subtitles.block.fence_gate.toggle": null, + "subtitles.block.fire.ambient": null, + "subtitles.block.fire.extinguish": null, + "subtitles.block.furnace.fire_crackle": null, + "subtitles.block.generic.break": null, + "subtitles.block.generic.footsteps": null, + "subtitles.block.generic.hit": null, + "subtitles.block.generic.place": null, + "subtitles.block.iron_trapdoor.close": null, + "subtitles.block.iron_trapdoor.open": null, + "subtitles.block.lava.ambient": null, + "subtitles.block.lava.extinguish": null, + "subtitles.block.lever.click": null, + "subtitles.block.note.note": "subtitles.block.note_block.note", + "subtitles.block.piston.move": null, + "subtitles.block.portal.ambient": null, + "subtitles.block.pressure_plate.click": null, + "subtitles.block.redstone_torch.burnout": null, + "subtitles.block.shulker_box.close": null, + "subtitles.block.shulker_box.open": null, + "subtitles.block.trapdoor.toggle": null, + "subtitles.block.tripwire.attach": null, + "subtitles.block.tripwire.click": null, + "subtitles.block.tripwire.detach": null, + "subtitles.block.water.ambient": null, + "subtitles.enchant.thorns.hit": null, + "subtitles.entity.armorstand.fall": "subtitles.entity.armor_stand.fall", + "subtitles.entity.arrow.hit": null, + "subtitles.entity.arrow.hit_player": null, + "subtitles.entity.arrow.shoot": null, + "subtitles.entity.bat.ambient": null, + "subtitles.entity.bat.death": null, + "subtitles.entity.bat.hurt": null, + "subtitles.entity.bat.takeoff": null, + "subtitles.entity.blaze.ambient": null, + "subtitles.entity.blaze.burn": null, + "subtitles.entity.blaze.death": null, + "subtitles.entity.blaze.hurt": null, + "subtitles.entity.blaze.shoot": null, + "subtitles.entity.bobber.throw": "subtitles.entity.fishing_bobber.throw", + "subtitles.entity.cat.ambient": null, + "subtitles.entity.cat.death": null, + "subtitles.entity.cat.hurt": null, + "subtitles.entity.chicken.ambient": null, + "subtitles.entity.chicken.death": null, + "subtitles.entity.chicken.egg": null, + "subtitles.entity.chicken.hurt": null, + "subtitles.entity.parrot.ambient": null, + "subtitles.entity.parrot.death": null, + "subtitles.entity.parrot.eats": null, + "subtitles.entity.parrot.hurts": null, + "subtitles.entity.parrot.imitate.blaze": null, + "subtitles.entity.parrot.imitate.cave_spider": "subtitles.entity.parrot.imitate.creeper", + "subtitles.entity.parrot.imitate.creeper": null, + "subtitles.entity.parrot.imitate.elder_guardian": null, + "subtitles.entity.parrot.imitate.enderdragon": "subtitles.entity.parrot.imitate.ender_dragon", + "subtitles.entity.parrot.imitate.enderman": null, + "subtitles.entity.parrot.imitate.endermite": null, + "subtitles.entity.parrot.imitate.evocation_illager": "subtitles.entity.parrot.imitate.evoker", + "subtitles.entity.parrot.imitate.ghast": null, + "subtitles.entity.parrot.imitate.husk": null, + "subtitles.entity.parrot.imitate.illusion_illager": "subtitles.entity.parrot.imitate.evoker", + "subtitles.entity.parrot.imitate.magmacube": "subtitles.entity.parrot.imitate.magma_cube", + "subtitles.entity.parrot.imitate.polar_bear": "subtitles.entity.parrot.imitate.husk", + "subtitles.entity.parrot.imitate.shulker": null, + "subtitles.entity.parrot.imitate.silverfish": "subtitles.entity.parrot.imitate.creeper", + "subtitles.entity.parrot.imitate.skeleton": null, + "subtitles.entity.parrot.imitate.slime": "subtitles.entity.parrot.imitate.magma_cube", + "subtitles.entity.parrot.imitate.spider": "subtitles.entity.parrot.imitate.creeper", + "subtitles.entity.parrot.imitate.stray": "subtitles.entity.parrot.imitate.skeleton", + "subtitles.entity.parrot.imitate.vex": null, + "subtitles.entity.parrot.imitate.vindication_illager": "subtitles.entity.parrot.imitate.vindicator", + "subtitles.entity.parrot.imitate.witch": null, + "subtitles.entity.parrot.imitate.wither": null, + "subtitles.entity.parrot.imitate.wither_skeleton": "subtitles.entity.parrot.imitate.skeleton", + "subtitles.entity.parrot.imitate.wolf": null, + "subtitles.entity.parrot.imitate.zombie": "subtitles.entity.parrot.imitate.husk", + "subtitles.entity.parrot.imitate.zombie_pigman": null, + "subtitles.entity.parrot.imitate.zombie_villager": "subtitles.entity.parrot.imitate.husk", + "subtitles.entity.cow.ambient": null, + "subtitles.entity.cow.death": null, + "subtitles.entity.cow.hurt": null, + "subtitles.entity.cow.milk": null, + "subtitles.entity.creeper.death": null, + "subtitles.entity.creeper.hurt": null, + "subtitles.entity.creeper.primed": null, + "subtitles.entity.donkey.ambient": null, + "subtitles.entity.donkey.angry": null, + "subtitles.entity.donkey.chest": null, + "subtitles.entity.donkey.death": null, + "subtitles.entity.donkey.hurt": null, + "subtitles.entity.egg.throw": null, + "subtitles.entity.elder_guardian.ambient.land": "subtitles.entity.elder_guardian.ambient_land", + "subtitles.entity.elder_guardian.ambient": null, + "subtitles.entity.elder_guardian.curse": null, + "subtitles.entity.elder_guardian.death": null, + "subtitles.entity.elder_guardian.flop": null, + "subtitles.entity.elder_guardian.hurt": null, + "subtitles.entity.enderdragon.ambient": "subtitles.entity.ender_dragon.ambient", + "subtitles.entity.enderdragon.death": "subtitles.entity.ender_dragon.death", + "subtitles.entity.enderdragon.flap": "subtitles.entity.ender_dragon.flap", + "subtitles.entity.enderdragon.growl": "subtitles.entity.ender_dragon.growl", + "subtitles.entity.enderdragon.hurt": "subtitles.entity.ender_dragon.hurt", + "subtitles.entity.enderdragon.shoot": "subtitles.entity.ender_dragon.shoot", + "subtitles.entity.endereye.launch": "subtitles.entity.ender_eye.launch", + "subtitles.entity.enderman.ambient": null, + "subtitles.entity.enderman.death": null, + "subtitles.entity.enderman.hurt": null, + "subtitles.entity.enderman.stare": null, + "subtitles.entity.enderman.teleport": null, + "subtitles.entity.endermite.ambient": null, + "subtitles.entity.endermite.death": null, + "subtitles.entity.endermite.hurt": null, + "subtitles.entity.enderpearl.throw": "subtitles.entity.ender_pearl.throw", + "subtitles.entity.evocation_fangs.attack": "subtitles.entity.evoker_fangs.attack", + "subtitles.entity.evocation_illager.ambient": "subtitles.entity.evoker.ambient", + "subtitles.entity.evocation_illager.cast_spell": "subtitles.entity.evoker.cast_spell", + "subtitles.entity.evocation_illager.death": "subtitles.entity.evoker.death", + "subtitles.entity.evocation_illager.hurt": "subtitles.entity.evoker.hurt", + "subtitles.entity.evocation_illager.prepare_attack": "subtitles.entity.evoker.prepare_attack", + "subtitles.entity.evocation_illager.prepare_summon": "subtitles.entity.evoker.prepare_summon", + "subtitles.entity.evocation_illager.prepare_wololo": "subtitles.entity.evoker.prepare_wololo", + "subtitles.entity.experience_orb.pickup": null, + "subtitles.entity.firework.blast": "subtitles.entity.firework_rocket.blast", + "subtitles.entity.firework.launch": "subtitles.entity.firework_rocket.launch", + "subtitles.entity.firework.twinkle": "subtitles.entity.firework_rocket.twinkle", + "subtitles.entity.generic.big_fall": "subtitles.entity.armor_stand.fall", + "subtitles.entity.generic.burn": null, + "subtitles.entity.generic.death": null, + "subtitles.entity.generic.drink": null, + "subtitles.entity.generic.eat": null, + "subtitles.entity.generic.explode": null, + "subtitles.entity.generic.extinguish_fire": null, + "subtitles.entity.generic.hurt": null, + "subtitles.entity.generic.splash": null, + "subtitles.entity.generic.swim": null, + "subtitles.entity.ghast.ambient": null, + "subtitles.entity.ghast.death": null, + "subtitles.entity.ghast.hurt": null, + "subtitles.entity.ghast.shoot": null, + "subtitles.entity.guardian.ambient.land": "subtitles.entity.guardian.ambient_land", + "subtitles.entity.guardian.ambient": null, + "subtitles.entity.guardian.attack": null, + "subtitles.entity.guardian.death": null, + "subtitles.entity.guardian.flop": null, + "subtitles.entity.guardian.hurt": null, + "subtitles.entity.horse.ambient": null, + "subtitles.entity.horse.angry": "subtitles.entity.horse.ambient", + "subtitles.entity.horse.armor": null, + "subtitles.entity.horse.breathe": null, + "subtitles.entity.horse.death": null, + "subtitles.entity.horse.eat": null, + "subtitles.entity.horse.gallop": null, + "subtitles.entity.horse.hurt": null, + "subtitles.entity.horse.jump": null, + "subtitles.entity.horse.saddle": null, + "subtitles.entity.husk.ambient": null, + "subtitles.entity.husk.death": null, + "subtitles.entity.husk.hurt": null, + "subtitles.entity.illusion_illager.ambient": "subtitles.entity.illusioner.ambient", + "subtitles.entity.illusion_illager.cast_spell": "subtitles.entity.illusioner.cast_spell", + "subtitles.entity.illusion_illager.death": "subtitles.entity.illusioner.death", + "subtitles.entity.illusion_illager.hurt": "subtitles.entity.illusioner.hurt", + "subtitles.entity.illusion_illager.mirror_move": "subtitles.entity.illusioner.mirror_move", + "subtitles.entity.illusion_illager.prepare_blindness": "subtitles.entity.illusioner.prepare_blindness", + "subtitles.entity.illusion_illager.prepare_mirror": "subtitles.entity.illusioner.prepare_mirror", + "subtitles.entity.iron_golem.attack": null, + "subtitles.entity.iron_golem.death": null, + "subtitles.entity.iron_golem.hurt": null, + "subtitles.entity.item.break": null, + "subtitles.entity.item.pickup": null, + "subtitles.entity.itemframe.add_item": "subtitles.entity.item_frame.add_item", + "subtitles.entity.itemframe.break": "subtitles.entity.item_frame.break", + "subtitles.entity.itemframe.place": "subtitles.entity.item_frame.place", + "subtitles.entity.itemframe.remove_item": "subtitles.entity.item_frame.remove_item", + "subtitles.entity.itemframe.rotate_item": "subtitles.entity.item_frame.rotate_item", + "subtitles.entity.leashknot.break": "subtitles.entity.leash_knot.break", + "subtitles.entity.leashknot.place": "subtitles.entity.leash_knot.place", + "subtitles.entity.lightning.impact": "subtitles.entity.lightning_bolt.impact", + "subtitles.entity.lightning.thunder": "subtitles.entity.lightning_bolt.thunder", + "subtitles.entity.llama.ambient": null, + "subtitles.entity.llama.chest": null, + "subtitles.entity.llama.death": null, + "subtitles.entity.llama.eat": null, + "subtitles.entity.llama.hurt": null, + "subtitles.entity.llama.spit": null, + "subtitles.entity.llama.step": null, + "subtitles.entity.llama.swag": null, + "subtitles.entity.magmacube.death": "subtitles.entity.magma_cube.death", + "subtitles.entity.magmacube.hurt": "subtitles.entity.magma_cube.hurt", + "subtitles.entity.magmacube.squish": "subtitles.entity.magma_cube.squish", + "subtitles.entity.minecart.riding": null, + "subtitles.entity.mule.ambient": null, + "subtitles.entity.mule.chest": null, + "subtitles.entity.mule.death": null, + "subtitles.entity.mule.hurt": null, + "subtitles.entity.painting.break": null, + "subtitles.entity.painting.place": null, + "subtitles.entity.pig.ambient": null, + "subtitles.entity.pig.death": null, + "subtitles.entity.pig.hurt": null, + "subtitles.entity.pig.saddle": "subtitles.entity.horse.saddle", + "subtitles.entity.player.burp": null, + "subtitles.entity.player.death": null, + "subtitles.entity.player.hurt": null, + "subtitles.entity.player.levelup": null, + "subtitles.entity.polar_bear.ambient": null, + "subtitles.entity.polar_bear.baby_ambient": "subtitles.entity.polar_bear.ambient_baby", + "subtitles.entity.polar_bear.death": null, + "subtitles.entity.polar_bear.hurt": null, + "subtitles.entity.polar_bear.warning": null, + "subtitles.entity.potion.splash": null, + "subtitles.entity.potion.throw": null, + "subtitles.entity.rabbit.ambient": null, + "subtitles.entity.rabbit.attack": null, + "subtitles.entity.rabbit.death": null, + "subtitles.entity.rabbit.hurt": null, + "subtitles.entity.rabbit.jump": null, + "subtitles.entity.sheep.ambient": null, + "subtitles.entity.sheep.death": null, + "subtitles.entity.sheep.hurt": null, + "subtitles.entity.shulker.ambient": null, + "subtitles.entity.shulker.close": "subtitles.block.shulker_box.close", + "subtitles.entity.shulker.death": null, + "subtitles.entity.shulker.hurt": null, + "subtitles.entity.shulker.open": "subtitles.block.shulker_box.open", + "subtitles.entity.shulker.shoot": null, + "subtitles.entity.shulker.teleport": null, + "subtitles.entity.shulker_bullet.hit": null, + "subtitles.entity.shulker_bullet.hurt": null, + "subtitles.entity.silverfish.ambient": null, + "subtitles.entity.silverfish.death": null, + "subtitles.entity.silverfish.hurt": null, + "subtitles.entity.skeleton.ambient": null, + "subtitles.entity.skeleton.death": null, + "subtitles.entity.skeleton.hurt": null, + "subtitles.entity.skeleton.shoot": null, + "subtitles.entity.skeleton_horse.ambient": null, + "subtitles.entity.skeleton_horse.death": null, + "subtitles.entity.skeleton_horse.hurt": null, + "subtitles.entity.slime.attack": null, + "subtitles.entity.slime.death": null, + "subtitles.entity.slime.hurt": null, + "subtitles.entity.slime.squish": null, + "subtitles.entity.snowball.throw": null, + "subtitles.entity.snowman.death": "subtitles.entity.snow_golem.death", + "subtitles.entity.snowman.hurt": "subtitles.entity.snow_golem.hurt", + "subtitles.entity.spider.ambient": null, + "subtitles.entity.spider.death": null, + "subtitles.entity.spider.hurt": null, + "subtitles.entity.squid.ambient": null, + "subtitles.entity.squid.death": null, + "subtitles.entity.squid.hurt": null, + "subtitles.entity.stray.ambient": null, + "subtitles.entity.stray.death": null, + "subtitles.entity.stray.hurt": null, + "subtitles.entity.tnt.primed": null, + "subtitles.entity.vex.ambient": null, + "subtitles.entity.vex.charge": null, + "subtitles.entity.vex.death": null, + "subtitles.entity.vex.hurt": null, + "subtitles.entity.villager.ambient": null, + "subtitles.entity.villager.death": null, + "subtitles.entity.villager.hurt": null, + "subtitles.entity.villager.no": null, + "subtitles.entity.villager.trading": "subtitles.entity.villager.trade", + "subtitles.entity.villager.yes": null, + "subtitles.entity.vindication_illager.ambient": "subtitles.entity.vindicator.ambient", + "subtitles.entity.vindication_illager.death": "subtitles.entity.vindicator.death", + "subtitles.entity.vindication_illager.hurt": "subtitles.entity.vindicator.hurt", + "subtitles.entity.witch.ambient": null, + "subtitles.entity.witch.death": null, + "subtitles.entity.witch.drink": null, + "subtitles.entity.witch.hurt": null, + "subtitles.entity.witch.throw": null, + "subtitles.entity.wither.ambient": null, + "subtitles.entity.wither.death": null, + "subtitles.entity.wither.hurt": null, + "subtitles.entity.wither.shoot": null, + "subtitles.entity.wither.spawn": null, + "subtitles.entity.wither_skeleton.ambient": null, + "subtitles.entity.wither_skeleton.death": null, + "subtitles.entity.wither_skeleton.hurt": null, + "subtitles.entity.wolf.ambient": null, + "subtitles.entity.wolf.death": null, + "subtitles.entity.wolf.growl": null, + "subtitles.entity.wolf.hurt": null, + "subtitles.entity.wolf.shake": null, + "subtitles.entity.zombie.ambient": null, + "subtitles.entity.zombie.death": null, + "subtitles.entity.zombie.hurt": null, + "subtitles.entity.zombie.infect": null, + "subtitles.entity.zombie_horse.ambient": null, + "subtitles.entity.zombie_horse.death": null, + "subtitles.entity.zombie_horse.hurt": null, + "subtitles.entity.zombie_pigman.ambient": null, + "subtitles.entity.zombie_pigman.angry": null, + "subtitles.entity.zombie_pigman.death": null, + "subtitles.entity.zombie_pigman.hurt": null, + "subtitles.entity.zombie_villager.ambient": null, + "subtitles.entity.zombie_villager.converted": null, + "subtitles.entity.zombie_villager.cure": null, + "subtitles.entity.zombie_villager.death": null, + "subtitles.entity.zombie_villager.hurt": null, + "subtitles.item.armor.equip_chain": null, + "subtitles.item.armor.equip_diamond": null, + "subtitles.item.armor.equip_gold": null, + "subtitles.item.armor.equip_iron": null, + "subtitles.item.armor.equip_leather": null, + "subtitles.item.bottle.fill": null, + "subtitles.item.bucket.empty": null, + "subtitles.item.bucket.fill": null, + "subtitles.item.chorus_fruit.teleport": null, + "subtitles.item.firecharge.use": null, + "subtitles.item.flintandsteel.use": null, + "subtitles.item.hoe.till": null, + "subtitles.item.shear": "subtitles.item.shears.shear", + "subtitles.item.shield.block": null, + "subtitles.item.shovel.flatten": null, + "subtitles.item.totem.use": null, + "subtitles.weather.rain": null, + "debug.prefix": null, + "debug.reload_chunks.message": null, + "debug.show_hitboxes.on": null, + "debug.show_hitboxes.off": null, + "debug.cycle_renderdistance.message": null, + "debug.chunk_boundaries.on": null, + "debug.chunk_boundaries.off": null, + "debug.advanced_tooltips.on": null, + "debug.advanced_tooltips.off": null, + "debug.creative_spectator.error": null, + "debug.pause_focus.on": null, + "debug.pause_focus.off": null, + "debug.help.message": null, + "debug.reload_resourcepacks.message": null, + "resourcepack.downloading": null, + "resourcepack.requesting": null, + "resourcepack.progress": null, + "tutorial.move.title": null, + "tutorial.move.description": null, + "tutorial.look.title": null, + "tutorial.look.description": null, + "tutorial.find_tree.title": null, + "tutorial.find_tree.description": null, + "tutorial.punch_tree.title": null, + "tutorial.punch_tree.description": null, + "tutorial.open_inventory.title": null, + "tutorial.open_inventory.description": null, + "tutorial.craft_planks.title": null, + "tutorial.craft_planks.description": null, + "advancements.adventure.adventuring_time.title": null, + "advancements.adventure.adventuring_time.description": null, + "advancements.adventure.kill_all_mobs.title": null, + "advancements.adventure.kill_all_mobs.description": null, + "advancements.adventure.kill_a_mob.title": null, + "advancements.adventure.kill_a_mob.description": null, + "advancements.adventure.root.title": "selectWorld.gameMode.adventure", + "advancements.adventure.root.description": null, + "advancements.adventure.shoot_arrow.title": null, + "advancements.adventure.shoot_arrow.description": null, + "advancements.adventure.sleep_in_bed.description": null, + "advancements.adventure.trade.title": null, + "advancements.adventure.trade.description": null, + "advancements.adventure.summon_iron_golem.title": null, + "advancements.adventure.summon_iron_golem.description": null, + "advancements.adventure.totem_of_undying.title": null, + "advancements.adventure.totem_of_undying.description": null, + "advancements.husbandry.root.title": null, + "advancements.husbandry.root.description": null, + "advancements.husbandry.breed_an_animal.title": null, + "advancements.husbandry.breed_an_animal.description": null, + "advancements.husbandry.breed_all_animals.title": null, + "advancements.husbandry.breed_all_animals.description": null, + "advancements.husbandry.tame_an_animal.title": null, + "advancements.husbandry.tame_an_animal.description": null, + "advancements.husbandry.plant_seed.title": null, + "advancements.husbandry.plant_seed.description": null, + "advancements.husbandry.break_diamond_hoe.title": null, + "advancements.husbandry.break_diamond_hoe.description": null, + "advancements.husbandry.balanced_diet.title": null, + "advancements.husbandry.balanced_diet.description": null, + "advancements.end.dragon_breath.title": null, + "advancements.end.dragon_breath.description": null, + "advancements.end.dragon_egg.title": null, + "advancements.end.dragon_egg.description": null, + "advancements.end.elytra.title": null, + "advancements.end.enter_end_gateway.title": null, + "advancements.end.enter_end_gateway.description": null, + "advancements.end.find_end_city.title": null, + "advancements.end.find_end_city.description": null, + "advancements.end.kill_dragon.title": null, + "advancements.end.kill_dragon.description": null, + "advancements.end.levitate.title": null, + "advancements.end.levitate.description": null, + "advancements.end.respawn_dragon.title": null, + "advancements.end.root.title": null, + "advancements.end.root.description": null, + "advancements.nether.brew_potion.title": null, + "advancements.nether.brew_potion.description": null, + "advancements.nether.all_potions.title": null, + "advancements.nether.all_potions.description": null, + "advancements.nether.all_effects.title": null, + "advancements.nether.all_effects.description": null, + "advancements.nether.create_beacon.title": null, + "advancements.nether.create_beacon.description": null, + "advancements.nether.create_full_beacon.title": null, + "advancements.nether.create_full_beacon.description": null, + "advancements.nether.find_fortress.title": null, + "advancements.nether.find_fortress.description": null, + "advancements.nether.get_wither_skull.title": null, + "advancements.nether.obtain_blaze_rod.title": null, + "advancements.nether.obtain_blaze_rod.description": null, + "advancements.nether.return_to_sender.title": null, + "advancements.nether.return_to_sender.description": null, + "advancements.nether.root.title": null, + "advancements.nether.root.description": null, + "advancements.nether.summon_wither.title": null, + "advancements.nether.summon_wither.description": null, + "advancements.nether.fast_travel.title": null, + "advancements.nether.uneasy_alliance.title": null, + "advancements.story.cure_zombie_villager.title": null, + "advancements.story.deflect_arrow.title": null, + "advancements.story.deflect_arrow.description": null, + "advancements.story.enchant_item.title": null, + "advancements.story.enchant_item.description": null, + "advancements.story.enter_the_end.title": null, + "advancements.story.enter_the_end.description": null, + "advancements.story.enter_the_nether.title": null, + "advancements.story.enter_the_nether.description": null, + "advancements.story.follow_ender_eye.title": null, + "advancements.story.form_obsidian.title": null, + "advancements.story.form_obsidian.description": null, + "advancements.story.iron_tools.title": null, + "advancements.story.iron_tools.description": null, + "advancements.story.lava_bucket.title": null, + "advancements.story.lava_bucket.description": null, + "advancements.story.mine_diamond.title": null, + "advancements.story.mine_diamond.description": null, + "advancements.story.mine_stone.title": null, + "advancements.story.mine_stone.description": null, + "advancements.story.obtain_armor.title": null, + "advancements.story.obtain_armor.description": null, + "advancements.story.root.title": null, + "advancements.story.root.description": null, + "advancements.story.shiny_gear.title": null, + "advancements.story.shiny_gear.description": null, + "advancements.story.smelt_iron.title": null, + "advancements.story.smelt_iron.description": null, + "advancements.story.upgrade_tools.title": null, + "advancements.story.upgrade_tools.description": null +} \ No newline at end of file diff --git a/jar/pom.xml b/jar/pom.xml index b75beca40..e909e3599 100644 --- a/jar/pom.xml +++ b/jar/pom.xml @@ -5,7 +5,7 @@ viaversion-parent us.myles - 1.6.1-18w46a + 2.0.0-18w46a 4.0.0 viaversion-jar @@ -57,6 +57,10 @@ org.javassist us.myles.viaversion.libs.javassist + + org.yaml.snakeyaml + us.myles.viaversion.libs.snakeyaml + @@ -92,6 +96,11 @@ viaversion-sponge ${project.parent.version} + + us.myles + viaversion-velocity + ${project.parent.version} + \ No newline at end of file diff --git a/pom.xml b/pom.xml index d6fed204c..61ef6cb72 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ us.myles viaversion-parent - 1.6.1-18w46a + 2.0.0-18w46a pom viaversion-parent @@ -21,6 +21,7 @@ bungee sponge sponge-legacy + velocity jar diff --git a/sponge-legacy/pom.xml b/sponge-legacy/pom.xml index 84497bb7f..53dbd74ad 100644 --- a/sponge-legacy/pom.xml +++ b/sponge-legacy/pom.xml @@ -5,7 +5,7 @@ viaversion-parent us.myles - 1.6.1-18w46a + 2.0.0-18w46a 4.0.0 diff --git a/sponge/pom.xml b/sponge/pom.xml index 7d2b5533f..23dd0e1b5 100644 --- a/sponge/pom.xml +++ b/sponge/pom.xml @@ -5,7 +5,7 @@ viaversion-parent us.myles - 1.6.1-18w46a + 2.0.0-18w46a 4.0.0 diff --git a/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java b/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java index a5d1f76ce..670dd56ae 100644 --- a/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java +++ b/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java @@ -55,7 +55,7 @@ public class SpongePlugin implements ViaPlatform { @Getter private SpongeViaAPI api = new SpongeViaAPI(); @Getter - private SpongeConfigAPI conf; + private SpongeViaConfig conf; @Getter private Logger logger; @@ -65,7 +65,7 @@ public class SpongePlugin implements ViaPlatform { // Setup Logger logger = new LoggerWrapper(container.getLogger()); // Setup Plugin - conf = new SpongeConfigAPI(container, defaultConfig.getParentFile()); + conf = new SpongeViaConfig(container, defaultConfig.getParentFile()); SpongeCommandHandler commandHandler = new SpongeCommandHandler(); game.getCommandManager().register(this, commandHandler, "viaversion", "viaver", "vvsponge"); getLogger().info("ViaVersion " + getPluginVersion() + " is now loaded!"); diff --git a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeConfigAPI.java b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaConfig.java similarity index 95% rename from sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeConfigAPI.java rename to sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaConfig.java index d5ec668db..180018458 100644 --- a/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeConfigAPI.java +++ b/sponge/src/main/java/us/myles/ViaVersion/sponge/platform/SpongeViaConfig.java @@ -12,11 +12,11 @@ import java.util.List; import java.util.Map; import java.util.Optional; -public class SpongeConfigAPI extends Config implements ViaVersionConfig { - private static List UNSUPPORTED = Arrays.asList("anti-xray-patch", "bungee-ping-interval", "bungee-ping-save", "bungee-servers", "quick-move-action-fix"); +public class SpongeViaConfig extends Config implements ViaVersionConfig { + private static List UNSUPPORTED = Arrays.asList("anti-xray-patch", "bungee-ping-interval", "bungee-ping-save", "bungee-servers", "velocity-ping-interval", "velocity-ping-save", "velocity-servers", "quick-move-action-fix"); private final PluginContainer pluginContainer; - public SpongeConfigAPI(PluginContainer pluginContainer, File configFile) { + public SpongeViaConfig(PluginContainer pluginContainer, File configFile) { super(new File(configFile, "config.yml")); this.pluginContainer = pluginContainer; // Load config diff --git a/velocity/pom.xml b/velocity/pom.xml new file mode 100644 index 000000000..2cdddfbef --- /dev/null +++ b/velocity/pom.xml @@ -0,0 +1,62 @@ + + + + viaversion-parent + us.myles + 2.0.0-18w46a + + 4.0.0 + + viaversion-velocity + + + 1.8 + 1.8 + + + + + velocity + https://repo.velocitypowered.com/snapshots + + + + + + + org.codehaus.mojo + templating-maven-plugin + 1.0.0 + + + filter-src + + filter-sources + + + + + + + + + + + us.myles + viaversion-common + ${project.parent.version} + provided + + + + + com.velocitypowered + velocity-api + 1.0-SNAPSHOT + provided + + + + \ No newline at end of file diff --git a/velocity/src/main/java-templates/us/myles/ViaVersion/velocity/VersionInfo.java b/velocity/src/main/java-templates/us/myles/ViaVersion/velocity/VersionInfo.java new file mode 100644 index 000000000..4b189c863 --- /dev/null +++ b/velocity/src/main/java-templates/us/myles/ViaVersion/velocity/VersionInfo.java @@ -0,0 +1,5 @@ +package us.myles.ViaVersion.velocity; + +public class VersionInfo { + public static final String VERSION = "${project.version}"; +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/VelocityPlugin.java b/velocity/src/main/java/us/myles/ViaVersion/VelocityPlugin.java new file mode 100644 index 000000000..94b131740 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/VelocityPlugin.java @@ -0,0 +1,206 @@ +package us.myles.ViaVersion; + +import com.google.gson.JsonObject; +import com.google.inject.Inject; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.DisconnectEvent; +import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; +import com.velocitypowered.api.plugin.Plugin; +import com.velocitypowered.api.plugin.PluginContainer; +import com.velocitypowered.api.plugin.annotation.DataDirectory; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ProxyServer; +import lombok.Getter; +import net.kyori.text.serializer.ComponentSerializers; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.chat.ComponentSerializer; +import org.slf4j.Logger; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; +import us.myles.ViaVersion.api.configuration.ConfigurationProvider; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.platform.TaskId; +import us.myles.ViaVersion.api.platform.ViaPlatform; +import us.myles.ViaVersion.dump.PluginInfo; +import us.myles.ViaVersion.util.GsonUtil; +import us.myles.ViaVersion.velocity.VersionInfo; +import us.myles.ViaVersion.velocity.command.VelocityCommandHandler; +import us.myles.ViaVersion.velocity.command.VelocityCommandSender; +import us.myles.ViaVersion.velocity.platform.*; +import us.myles.ViaVersion.velocity.service.ProtocolDetectorService; +import us.myles.ViaVersion.velocity.util.LoggerWrapper; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +@Plugin( + id = "viaversion", + name = "ViaVersion", + version = VersionInfo.VERSION, + authors = {"_MylesC", "Matsv"}, + description = "Allow newer Minecraft versions to connect to an older server version.", + url = "https://viaversion.com" +) +@Getter +public class VelocityPlugin implements ViaPlatform { + @Inject + private ProxyServer proxy; + @Inject + public static ProxyServer PROXY; + @Inject + private Logger loggerslf4j; + private java.util.logging.Logger logger; + @Inject + @DataDirectory + private Path configDir; + private VelocityViaAPI api; + private VelocityViaConfig conf; + + @Subscribe + public void onProxyInit(ProxyInitializeEvent e) { + PROXY = proxy; + VelocityCommandHandler commandHandler = new VelocityCommandHandler(); + PROXY.getCommandManager().register(commandHandler, "viaver", "vvvelocity", "viaversion"); + api = new VelocityViaAPI(); + conf = new VelocityViaConfig(configDir.toFile()); + logger = new LoggerWrapper(loggerslf4j); + Via.init(ViaManager.builder() + .platform(this) + .commandHandler(commandHandler) + .loader(new VelocityViaLoader()) + .injector(new VelocityViaInjector()).build()); + Via.getManager().init(); + } + + @Subscribe + public void onQuit(DisconnectEvent e) { + UserConnection userConnection = Via.getManager().getPortedPlayers().get(e.getPlayer().getUniqueId()); + if (userConnection != null) { + // Only remove if the connection is disconnected (eg. relogin) + if (userConnection.getChannel() == null || !userConnection.getChannel().isOpen()) { + Via.getManager().removePortedClient(e.getPlayer().getUniqueId()); + } + } + } + + @Override + public String getPlatformName() { + String proxyImpl = ProxyServer.class.getPackage().getImplementationTitle(); + return (proxyImpl != null) ? proxyImpl : "Velocity"; + } + + @Override + public String getPlatformVersion() { + String version = ProxyServer.class.getPackage().getImplementationVersion(); + return (version != null) ? version : "Unknown"; + } + + @Override + public String getPluginVersion() { + return VersionInfo.VERSION; + } + + @Override + public TaskId runAsync(Runnable runnable) { + return runSync(runnable); + } + + @Override + public TaskId runSync(Runnable runnable) { + return runSync(runnable, 0L); + } + + @Override + public TaskId runSync(Runnable runnable, Long ticks) { + return new VelocityTaskId( + PROXY.getScheduler() + .buildTask(this, runnable) + .delay(ticks * 50, TimeUnit.MILLISECONDS).schedule() + ); + } + + @Override + public TaskId runRepeatingSync(Runnable runnable, Long ticks) { + return new VelocityTaskId( + PROXY.getScheduler() + .buildTask(this, runnable) + .repeat(ticks * 50, TimeUnit.MILLISECONDS).schedule() + ); + } + + @Override + public void cancelTask(TaskId taskId) { + if (taskId instanceof VelocityTaskId) { + ((VelocityTaskId) taskId).getObject().cancel(); + } + } + + @Override + public ViaCommandSender[] getOnlinePlayers() { + return PROXY.getAllPlayers().stream() + .map(VelocityCommandSender::new) + .toArray(ViaCommandSender[]::new); + } + + @Override + public void sendMessage(UUID uuid, String message) { + PROXY.getPlayer(uuid).ifPresent(it -> it.sendMessage( + ComponentSerializers.JSON.deserialize( + ComponentSerializer.toString(TextComponent.fromLegacyText(message)) // Fixes links + ) + )); + } + + @Override + public boolean kickPlayer(UUID uuid, String message) { + return PROXY.getPlayer(uuid).map(it -> { + it.disconnect( + ComponentSerializers.JSON.deserialize( + ComponentSerializer.toString(TextComponent.fromLegacyText(message)) // ComponentSerializers.LEGACY is deprecated + ) + ); + return true; + }).orElse(false); + } + + @Override + public boolean isPluginEnabled() { + return true; + } + + @Override + public ConfigurationProvider getConfigurationProvider() { + return conf; + } + + @Override + public void onReload() { + + } + + @Override + public JsonObject getDump() { + JsonObject extra = new JsonObject(); + List plugins = new ArrayList<>(); + for (PluginContainer p : PROXY.getPluginManager().getPlugins()) { + plugins.add(new PluginInfo( + true, + p.getDescription().getName().orElse(p.getDescription().getId()), + p.getDescription().getVersion().orElse("Unknown Version"), + p.getInstance().isPresent() ? p.getInstance().get().getClass().getCanonicalName() : "Unknown", + p.getDescription().getAuthors() + )); + } + extra.add("plugins", GsonUtil.getGson().toJsonTree(plugins)); + extra.add("servers", GsonUtil.getGson().toJsonTree(ProtocolDetectorService.getDetectedIds())); + return extra; + } + + @Override + public boolean isOldClientsAllowed() { + return true; + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/command/VelocityCommandHandler.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/command/VelocityCommandHandler.java new file mode 100644 index 000000000..9c23a01e5 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/command/VelocityCommandHandler.java @@ -0,0 +1,29 @@ +package us.myles.ViaVersion.velocity.command; + +import com.velocitypowered.api.command.Command; +import com.velocitypowered.api.command.CommandSource; +import org.checkerframework.checker.nullness.qual.NonNull; +import us.myles.ViaVersion.commands.ViaCommandHandler; +import us.myles.ViaVersion.velocity.command.subs.ProbeSubCmd; + +import java.util.List; + +public class VelocityCommandHandler extends ViaCommandHandler implements Command { + public VelocityCommandHandler() { + try { + registerSubCommand(new ProbeSubCmd()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void execute(@NonNull CommandSource source, String[] args) { + onCommand(new VelocityCommandSender(source), args); + } + + @Override + public List suggest(@NonNull CommandSource source, String[] currentArgs) { + return onTabComplete(new VelocityCommandSender(source), currentArgs); + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/command/VelocityCommandSender.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/command/VelocityCommandSender.java new file mode 100644 index 000000000..1a61f8b5c --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/command/VelocityCommandSender.java @@ -0,0 +1,46 @@ +package us.myles.ViaVersion.velocity.command; + +import com.velocitypowered.api.command.CommandSource; +import com.velocitypowered.api.proxy.Player; +import lombok.AllArgsConstructor; +import net.kyori.text.serializer.ComponentSerializers; +import net.md_5.bungee.api.chat.TextComponent; +import net.md_5.bungee.chat.ComponentSerializer; +import us.myles.ViaVersion.api.command.ViaCommandSender; + +import java.util.UUID; + +@AllArgsConstructor +public class VelocityCommandSender implements ViaCommandSender { + private CommandSource source; + + @Override + public boolean hasPermission(String permission) { + return source.hasPermission(permission); + } + + @Override + public void sendMessage(String msg) { + source.sendMessage( + ComponentSerializers.JSON.deserialize( + ComponentSerializer.toString(TextComponent.fromLegacyText(msg)) // Fixes links + ) + ); + } + + @Override + public UUID getUUID() { + if (source instanceof Player) { + return ((Player) source).getUniqueId(); + } + return UUID.fromString(getName()); + } + + @Override + public String getName() { + if (source instanceof Player) { + return ((Player) source).getUsername(); + } + return "?"; // :( + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/command/subs/ProbeSubCmd.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/command/subs/ProbeSubCmd.java new file mode 100644 index 000000000..1470f49f1 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/command/subs/ProbeSubCmd.java @@ -0,0 +1,28 @@ +package us.myles.ViaVersion.velocity.command.subs; + +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.command.ViaCommandSender; +import us.myles.ViaVersion.api.command.ViaSubCommand; +import us.myles.ViaVersion.velocity.platform.VelocityViaConfig; +import us.myles.ViaVersion.velocity.service.ProtocolDetectorService; + +public class ProbeSubCmd extends ViaSubCommand { + @Override + public String name() { + return "probe"; + } + + @Override + public String description() { + return "Forces ViaVersion to scan server protocol versions " + + (((VelocityViaConfig) Via.getConfig()).getVelocityPingInterval() == -1 ? + "" : "(Also happens at an interval)"); + } + + @Override + public boolean execute(ViaCommandSender sender, String[] args) { + ProtocolDetectorService.getInstance().run(); + sendMessage(sender, "&6Started searching for protocol versions"); + return true; + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityChannelInitializer.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityChannelInitializer.java new file mode 100644 index 000000000..306bcf667 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityChannelInitializer.java @@ -0,0 +1,38 @@ +package us.myles.ViaVersion.velocity.handlers; + +import io.netty.channel.Channel; +import io.netty.channel.ChannelInitializer; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.ProtocolPipeline; + +import java.lang.reflect.Method; + +@RequiredArgsConstructor +public class VelocityChannelInitializer extends ChannelInitializer { + @NonNull + private ChannelInitializer original; + private Method initChannel; + + { + try { + initChannel = ChannelInitializer.class.getDeclaredMethod("initChannel", Channel.class); + initChannel.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + + @Override + protected void initChannel(Channel channel) throws Exception { + initChannel.invoke(original, channel); + + UserConnection user = new UserConnection(channel); + new ProtocolPipeline(user); + + // We need to add a separated handler because Velocity uses pipeline().get(MINECRAFT_DECODER) + channel.pipeline().addBefore("minecraft-encoder", "via-encoder", new VelocityEncodeHandler(user)); + channel.pipeline().addBefore("minecraft-decoder", "via-decoder", new VelocityDecodeHandler(user)); + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityDecodeHandler.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityDecodeHandler.java new file mode 100644 index 000000000..23dbd77fd --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityDecodeHandler.java @@ -0,0 +1,78 @@ +package us.myles.ViaVersion.velocity.handlers; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageDecoder; +import lombok.AllArgsConstructor; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.exception.CancelException; +import us.myles.ViaVersion.packets.Direction; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.util.PipelineUtil; + +import java.util.List; + +@ChannelHandler.Sharable +@AllArgsConstructor +public class VelocityDecodeHandler extends MessageToMessageDecoder { + private final UserConnection info; + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List out) throws Exception { + // use transformers + if (bytebuf.readableBytes() > 0) { + // Ignore if pending disconnect + if (info.isPendingDisconnect()) { + return; + } + // Increment received + boolean second = info.incrementReceived(); + // Check PPS + if (second) { + if (info.handlePPS()) + return; + } + info.getVelocityLock().readLock().lock(); + if (info.isActive()) { + // Handle ID + int id = Type.VAR_INT.read(bytebuf); + // Transform + ByteBuf newPacket = ctx.alloc().buffer(); + try { + if (id == PacketWrapper.PASSTHROUGH_ID) { + newPacket.writeBytes(bytebuf); + } else { + PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info); + ProtocolInfo protInfo = info.get(ProtocolInfo.class); + protInfo.getPipeline().transform(Direction.INCOMING, protInfo.getState(), wrapper); + wrapper.writeToBuffer(newPacket); + } + + bytebuf.clear(); + bytebuf = newPacket; + } catch (Exception e) { + // Clear Buffer + bytebuf.clear(); + // Release Packet, be free! + newPacket.release(); + info.getVelocityLock().readLock().unlock(); + throw e; + } + } else { + bytebuf.retain(); + } + info.getVelocityLock().readLock().unlock(); + + out.add(bytebuf); + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (PipelineUtil.containsCause(cause, CancelException.class)) return; + super.exceptionCaught(ctx, cause); + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityEncodeHandler.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityEncodeHandler.java new file mode 100644 index 000000000..1a929c2e8 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityEncodeHandler.java @@ -0,0 +1,90 @@ +package us.myles.ViaVersion.velocity.handlers; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; +import io.netty.handler.codec.MessageToMessageDecoder; +import io.netty.handler.codec.MessageToMessageEncoder; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.exception.CancelException; +import us.myles.ViaVersion.packets.Direction; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.util.PipelineUtil; + +import java.util.List; + +@ChannelHandler.Sharable +@RequiredArgsConstructor +public class VelocityEncodeHandler extends MessageToMessageEncoder { + @NonNull + private final UserConnection info; + private boolean handledCompression = false; + + @Override + protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List out) throws Exception { + if (bytebuf.readableBytes() == 0) { + throw new CancelException(); + } + boolean needsCompress = false; + if (!handledCompression + && ctx.pipeline().names().indexOf("compression-encoder") > ctx.pipeline().names().indexOf("via-encoder")) { + // Need to decompress this packet due to bad order + bytebuf = (ByteBuf) PipelineUtil.callDecode((MessageToMessageDecoder) ctx.pipeline().get("compression-decoder"), ctx, bytebuf).get(0); + ChannelHandler encoder = ctx.pipeline().get("via-encoder"); + ChannelHandler decoder = ctx.pipeline().get("via-decoder"); + ctx.pipeline().remove(encoder); + ctx.pipeline().remove(decoder); + ctx.pipeline().addAfter("compression-encoder", "via-encoder", encoder); + ctx.pipeline().addAfter("compression-decoder", "via-decoder", decoder); + needsCompress = true; + handledCompression = true; + } else { + bytebuf.retain(); + } + // Increment sent + info.incrementSent(); + + + if (info.isActive()) { + // Handle ID + int id = Type.VAR_INT.read(bytebuf); + // Transform + ByteBuf newPacket = bytebuf.alloc().buffer(); + try { + PacketWrapper wrapper = new PacketWrapper(id, bytebuf, info); + ProtocolInfo protInfo = info.get(ProtocolInfo.class); + protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper); + + wrapper.writeToBuffer(newPacket); + + bytebuf.clear(); + bytebuf.release(); + bytebuf = newPacket; + } catch (Exception e) { + bytebuf.clear(); + bytebuf.release(); + newPacket.release(); + throw e; + } + } + + if (needsCompress) { + ByteBuf old = bytebuf; + bytebuf = ctx.alloc().buffer(); + PipelineUtil.callEncode((MessageToByteEncoder) ctx.pipeline().get("compression-encoder"), ctx, old, bytebuf); + old.release(); + } + out.add(bytebuf); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (PipelineUtil.containsCause(cause, CancelException.class)) return; + super.exceptionCaught(ctx, cause); + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityServerHandler.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityServerHandler.java new file mode 100644 index 000000000..51bb600d1 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityServerHandler.java @@ -0,0 +1,138 @@ +package us.myles.ViaVersion.velocity.handlers; + +import com.velocitypowered.api.event.PostOrder; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.player.ServerConnectedEvent; +import com.velocitypowered.api.event.player.ServerPreConnectEvent; +import us.myles.ViaVersion.api.Pair; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.boss.BossBar; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.Protocol; +import us.myles.ViaVersion.api.protocol.ProtocolPipeline; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; +import us.myles.ViaVersion.util.ReflectionUtil; +import us.myles.ViaVersion.velocity.service.ProtocolDetectorService; +import us.myles.ViaVersion.velocity.storage.VelocityStorage; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; +import java.util.concurrent.Semaphore; + +public class VelocityServerHandler { + private static Method setProtocolVersion; + private static Method setNextProtocolVersion; + + static { + try { + setProtocolVersion = Class.forName("com.velocitypowered.proxy.connection.MinecraftConnection").getDeclaredMethod("setProtocolVersion", int.class); + setNextProtocolVersion = Class.forName("com.velocitypowered.proxy.connection.MinecraftConnection").getDeclaredMethod("setNextProtocolVersion", int.class); + } catch (NoSuchMethodException | ClassNotFoundException e) { + e.printStackTrace(); + } + } + + @Subscribe + public void preServerConnect(ServerPreConnectEvent e) { + try { + UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId()); + if (user == null) return; + if (!user.has(VelocityStorage.class)) { + user.put(new VelocityStorage(user, e.getPlayer())); + } + + int protocolId = ProtocolDetectorService.getProtocolId(e.getOriginalServer().getServerInfo().getName()); + List> protocols = ProtocolRegistry.getProtocolPath(user.get(ProtocolInfo.class).getProtocolVersion(), protocolId); + + // Check if ViaVersion can support that version + Object connection = ReflectionUtil.invoke(e.getPlayer(), "getConnection"); + setNextProtocolVersion.invoke(connection, protocols == null ? user.get(ProtocolInfo.class).getProtocolVersion() : protocolId); + + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e1) { + e1.printStackTrace(); + } + } + + @Subscribe(order = PostOrder.LATE) + public void connectedEvent(ServerConnectedEvent e) { + UserConnection user = Via.getManager().getConnection(e.getPlayer().getUniqueId()); + try { + checkServerChange(e, Via.getManager().getConnection(e.getPlayer().getUniqueId())); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + + public void checkServerChange(ServerConnectedEvent e, UserConnection user) throws Exception { + if (user == null) return; + // Manually hide ViaVersion-created BossBars if the childserver was version 1.8.x (#666) + if (user.has(EntityTracker.class)) { + EntityTracker tracker = user.get(EntityTracker.class); + + if (tracker.getBossBarMap() != null) + for (BossBar bar : tracker.getBossBarMap().values()) + bar.hide(); + } + // Handle server/version change + if (user.has(VelocityStorage.class)) { + // Wait all the scheduled packets be sent + Semaphore semaphore = new Semaphore(1); + semaphore.acquireUninterruptibly(); + user.getChannel().eventLoop().submit((Runnable) semaphore::release); + semaphore.acquireUninterruptibly(); + semaphore.release(); + + user.getVelocityLock().writeLock().lock(); + + VelocityStorage storage = user.get(VelocityStorage.class); + + if (e.getServer() != null) { + if (!e.getServer().getServerInfo().getName().equals(storage.getCurrentServer())) { + String serverName = e.getServer().getServerInfo().getName(); + + storage.setCurrentServer(serverName); + + int protocolId = ProtocolDetectorService.getProtocolId(serverName); + + ProtocolInfo info = user.get(ProtocolInfo.class); + + // Refresh the pipes + List> protocols = ProtocolRegistry.getProtocolPath(info.getProtocolVersion(), protocolId); + ProtocolPipeline pipeline = user.get(ProtocolInfo.class).getPipeline(); + user.clearStoredObjects(); + pipeline.cleanPipes(); + if (protocols == null) { + // TODO Check Bungee Supported Protocols? *shrugs* + protocolId = info.getProtocolVersion(); + } else { + for (Pair prot : protocols) { + pipeline.add(prot.getValue()); + } + } + + info.setServerProtocolVersion(protocolId); + // Add version-specific base Protocol + pipeline.add(ProtocolRegistry.getBaseProtocol(protocolId)); + + user.put(info); + user.put(storage); + + user.setActive(protocols != null); + + // Init all protocols TODO check if this can get moved up to the previous for loop, and doesn't require the pipeline to already exist. + for (Protocol protocol : pipeline.pipes()) { + protocol.init(user); + } + + Object connection = ReflectionUtil.invoke(e.getPlayer(), "getConnection"); + int version = (int) ReflectionUtil.invoke(connection,"getNextProtocolVersion"); + setProtocolVersion.invoke(ReflectionUtil.invoke(e.getPlayer(), "getConnection"), version); + } + } + user.getVelocityLock().writeLock().unlock(); + } + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/listeners/ElytraPatch.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/listeners/ElytraPatch.java new file mode 100644 index 000000000..9e9a93ba0 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/listeners/ElytraPatch.java @@ -0,0 +1,44 @@ +package us.myles.ViaVersion.velocity.listeners; + +import com.velocitypowered.api.event.PostOrder; +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.player.ServerConnectedEvent; +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.minecraft.metadata.Metadata; +import us.myles.ViaVersion.api.minecraft.metadata.types.MetaType1_9; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.api.type.types.version.Types1_9; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; + +import java.util.Collections; + +/* + * This patches https://github.com/MylesIsCool/ViaVersion/issues/555 + */ +public class ElytraPatch { + + @Subscribe(order = PostOrder.LAST) + public void onServerConnected(ServerConnectedEvent event) { + UserConnection user = Via.getManager().getConnection(event.getPlayer().getUniqueId()); + if (user == null) return; + + try { + if (user.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) { + int entityId = user.get(EntityTracker.class).getProvidedEntityId(); + + PacketWrapper wrapper = new PacketWrapper(0x39, null, user); + + wrapper.write(Type.VAR_INT, entityId); + wrapper.write(Types1_9.METADATA_LIST, Collections.singletonList(new Metadata(0, MetaType1_9.Byte, (byte) 0))); + + wrapper.send(Protocol1_9TO1_8.class); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/listeners/MainHandPatch.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/listeners/MainHandPatch.java new file mode 100644 index 000000000..eae7f08c3 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/listeners/MainHandPatch.java @@ -0,0 +1,49 @@ +package us.myles.ViaVersion.velocity.listeners; + +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.player.ServerConnectedEvent; +import com.velocitypowered.api.proxy.player.PlayerSettings; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.EntityTracker; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.lang.reflect.Method; + +/* + This solves the wrong mainhand issue when you join with BungeeCord on a 1.8 server, and switch to a 1.9 or higher. + */ +public class MainHandPatch { + private static Method setSettings; + + static { + try { + Class clientSettings = Class.forName("com.velocitypowered.proxy.protocol.packet.ClientSettings"); + setSettings = Class.forName("com.velocitypowered.proxy.connection.client.ConnectedPlayer").getDeclaredMethod("setPlayerSettings", clientSettings); + setSettings.setAccessible(true); + } catch (ClassNotFoundException | NoSuchMethodException e) { + e.printStackTrace(); + } + } + + @Subscribe + public void onServerConnect(ServerConnectedEvent event) { + UserConnection user = Via.getManager().getConnection(event.getPlayer().getUniqueId()); + if (user == null || setSettings == null) return; + + try { + if (user.get(ProtocolInfo.class).getPipeline().contains(Protocol1_9TO1_8.class)) { + PlayerSettings settings = event.getPlayer().getPlayerSettings(); + if (user.has(EntityTracker.class)) { + Object clientSettings = ReflectionUtil.get(settings, "settings", Object.class); + ReflectionUtil.set(clientSettings, "mainHand", user.get(EntityTracker.class).getMainHand()); + setSettings.invoke(event.getPlayer(), clientSettings); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/listeners/UpdateListener.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/listeners/UpdateListener.java new file mode 100644 index 000000000..d12069810 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/listeners/UpdateListener.java @@ -0,0 +1,16 @@ +package us.myles.ViaVersion.velocity.listeners; + +import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.PostLoginEvent; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.update.UpdateUtil; + +public class UpdateListener { + @Subscribe + public void onJoin(PostLoginEvent e) { + if (e.getPlayer().hasPermission("viaversion.update") + && Via.getConfig().isCheckForUpdates()) { + UpdateUtil.sendUpdateMessage(e.getPlayer().getUniqueId()); + } + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityBossBar.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityBossBar.java new file mode 100644 index 000000000..46a767c6a --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityBossBar.java @@ -0,0 +1,13 @@ +package us.myles.ViaVersion.velocity.platform; + +import com.velocitypowered.api.proxy.Player; +import us.myles.ViaVersion.api.boss.BossBar; +import us.myles.ViaVersion.api.boss.BossColor; +import us.myles.ViaVersion.api.boss.BossStyle; +import us.myles.ViaVersion.boss.CommonBoss; + +public class VelocityBossBar extends CommonBoss { + public VelocityBossBar(String title, float health, BossColor color, BossStyle style) { + super(title, health, color, style); + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityTaskId.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityTaskId.java new file mode 100644 index 000000000..9d7edbb56 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityTaskId.java @@ -0,0 +1,12 @@ +package us.myles.ViaVersion.velocity.platform; + +import com.velocitypowered.api.scheduler.ScheduledTask; +import lombok.AllArgsConstructor; +import lombok.Getter; +import us.myles.ViaVersion.api.platform.TaskId; + +@Getter +@AllArgsConstructor +public class VelocityTaskId implements TaskId { + private ScheduledTask object; +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaAPI.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaAPI.java new file mode 100644 index 000000000..aca7fe39a --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaAPI.java @@ -0,0 +1,78 @@ +package us.myles.ViaVersion.velocity.platform; + +import com.velocitypowered.api.proxy.Player; +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.ViaAPI; +import us.myles.ViaVersion.api.boss.BossBar; +import us.myles.ViaVersion.api.boss.BossColor; +import us.myles.ViaVersion.api.boss.BossStyle; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.ProtocolRegistry; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; + +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.UUID; + +public class VelocityViaAPI implements ViaAPI { + @Override + public int getPlayerVersion(@NonNull Player player) { + if (!isPorted(player.getUniqueId())) + return ProtocolRegistry.SERVER_PROTOCOL; + return getPortedPlayers().get(player.getUniqueId()).get(ProtocolInfo.class).getProtocolVersion(); + } + + @Override + public int getPlayerVersion(@NonNull UUID uuid) { + if (!isPorted(uuid)) + return ProtocolRegistry.SERVER_PROTOCOL; + return getPortedPlayers().get(uuid).get(ProtocolInfo.class).getProtocolVersion(); + } + + @Override + public boolean isPorted(UUID playerUUID) { + return getPortedPlayers().containsKey(playerUUID); + } + + @Override + public String getVersion() { + return Via.getPlatform().getPluginVersion(); + } + + @Override + public void sendRawPacket(UUID uuid, ByteBuf packet) throws IllegalArgumentException { + if (!isPorted(uuid)) throw new IllegalArgumentException("This player is not controlled by ViaVersion!"); + UserConnection ci = getPortedPlayers().get(uuid); + ci.sendRawPacket(packet); + } + + @Override + public void sendRawPacket(Player player, ByteBuf packet) throws IllegalArgumentException { + sendRawPacket(player.getUniqueId(), packet); + } + + @Override + public BossBar createBossBar(String title, BossColor color, BossStyle style) { + return new VelocityBossBar(title, 1F, color, style); + } + + @Override + public BossBar createBossBar(String title, float health, BossColor color, BossStyle style) { + return new VelocityBossBar(title, health, color, style); + } + + @Override + public SortedSet getSupportedVersions() { + SortedSet outputSet = new TreeSet<>(ProtocolRegistry.getSupportedVersions()); + outputSet.removeAll(Via.getPlatform().getConf().getBlockedProtocols()); + + return outputSet; + } + + public Map getPortedPlayers() { + return Via.getManager().getPortedPlayers(); + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaConfig.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaConfig.java new file mode 100644 index 000000000..9d8da33f0 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaConfig.java @@ -0,0 +1,280 @@ +package us.myles.ViaVersion.velocity.platform; + +import us.myles.ViaVersion.api.ViaVersionConfig; +import us.myles.ViaVersion.api.protocol.ProtocolVersion; +import us.myles.ViaVersion.util.Config; + +import java.io.File; +import java.net.URL; +import java.util.*; + +public class VelocityViaConfig extends Config implements ViaVersionConfig { + private static List UNSUPPORTED = Arrays.asList("nms-player-ticking", "item-cache", "anti-xray-patch", "quick-move-action-fix", "bungee-ping-interval", "bungee-ping-save", "bungee-servers"); + + public VelocityViaConfig(File configFile) { + super(new File(configFile, "config.yml")); + // Load config + reloadConfig(); + } + + @Override + public URL getDefaultConfigURL() { + return getClass().getClassLoader().getResource("assets/viaversion/config.yml"); + } + + @Override + protected void handleConfig(Map config) { + // Parse servers + Map servers; + if (!(config.get("velocity-servers") instanceof Map)) { + servers = new HashMap<>(); + } else { + servers = (Map) config.get("velocity-servers"); + } + // Convert any bad Protocol Ids + for (Map.Entry entry : new HashSet<>(servers.entrySet())) { + if (!(entry.getValue() instanceof Integer)) { + if (entry.getValue() instanceof String) { + ProtocolVersion found = ProtocolVersion.getClosest((String) entry.getValue()); + if (found != null) { + servers.put(entry.getKey(), found.getId()); + } else { + servers.remove(entry.getKey()); // Remove! + } + } else { + servers.remove(entry.getKey()); // Remove! + } + } + } + // Ensure default exists + if (!servers.containsKey("default")) { + // Side note: This doesn't use ProtocolRegistry as it doesn't know the protocol version at boot. + try { + servers.put("default", VelocityViaInjector.getLowestSupportedProtocolVersion()); + } catch (Exception e) { + // Something went very wrong + e.printStackTrace(); + } + } + // Put back + config.put("velocity-servers", servers); + } + + @Override + public List getUnsupportedOptions() { + return UNSUPPORTED; + } + + public boolean isCheckForUpdates() { + return getBoolean("checkforupdates", true); + } + + @Override + public boolean isPreventCollision() { + return getBoolean("prevent-collision", true); + } + + @Override + public boolean isNewEffectIndicator() { + return getBoolean("use-new-effect-indicator", true); + } + + @Override + public boolean isShowNewDeathMessages() { + return getBoolean("use-new-deathmessages", true); + } + + @Override + public boolean isSuppressMetadataErrors() { + return getBoolean("suppress-metadata-errors", false); + } + + @Override + public boolean isShieldBlocking() { + return getBoolean("shield-blocking", true); + } + + @Override + public boolean isHologramPatch() { + return getBoolean("hologram-patch", false); + } + + @Override + public boolean isPistonAnimationPatch() { + return getBoolean("piston-animation-patch", false); + } + + @Override + public boolean isBossbarPatch() { + return getBoolean("bossbar-patch", true); + } + + @Override + public boolean isBossbarAntiflicker() { + return getBoolean("bossbar-anti-flicker", false); + } + + @Override + public boolean isUnknownEntitiesSuppressed() { + return false; + } + + @Override + public double getHologramYOffset() { + return getDouble("hologram-y", -0.96D); + } + + @Override + public boolean isBlockBreakPatch() { + return false; + } + + @Override + public int getMaxPPS() { + return getInt("max-pps", 800); + } + + @Override + public String getMaxPPSKickMessage() { + return getString("max-pps-kick-msg", "Sending packets too fast? lag?"); + } + + @Override + public int getTrackingPeriod() { + return getInt("tracking-period", 6); + } + + @Override + public int getWarningPPS() { + return getInt("tracking-warning-pps", 120); + } + + @Override + public int getMaxWarnings() { + return getInt("tracking-max-warnings", 3); + } + + @Override + public String getMaxWarningsKickMessage() { + return getString("tracking-max-kick-msg", "You are sending too many packets, :("); + } + + @Override + public boolean isAntiXRay() { + return false; + } + + @Override + public boolean isSendSupportedVersions() { + return getBoolean("send-supported-versions", false); + } + + @Override + public boolean isStimulatePlayerTick() { + return getBoolean("simulate-pt", true); + } + + @Override + public boolean isItemCache() { + return false; + } + + @Override + public boolean isNMSPlayerTicking() { + return false; + } + + @Override + public boolean isReplacePistons() { + return getBoolean("replace-pistons", false); + } + + @Override + public int getPistonReplacementId() { + return getInt("replacement-piston-id", 0); + } + + public boolean isAutoTeam() { + // Collision has to be enabled first + return isPreventCollision() && getBoolean("auto-team", true); + } + + @Override + public boolean isForceJsonTransform() { + return getBoolean("force-json-transform", false); + } + + @Override + public boolean is1_12NBTArrayFix() { + return getBoolean("chat-nbt-fix", true); + } + + @Override + public boolean is1_12QuickMoveActionFix() { + return false; + } + + @Override + public List getBlockedProtocols() { + return getIntegerList("block-protocols"); + } + + @Override + public String getBlockedDisconnectMsg() { + return getString("block-disconnect-msg", "You are using an unsupported Minecraft version!"); + } + + @Override + public String getReloadDisconnectMsg() { + return getString("reload-disconnect-msg", "Server reload, please rejoin!"); + } + + @Override + public boolean isMinimizeCooldown() { + return getBoolean("minimize-cooldown", true); + } + + /** + * What is the interval for checking servers via ping + * -1 for disabled + * + * @return Ping interval in seconds + */ + public int getVelocityPingInterval() { + return getInt("velocity-ping-interval", 60); + } + + /** + * Should the velocity ping be saved to the config on change. + * + * @return True if it should save + */ + public boolean isVelocityPingSave() { + return getBoolean("velocity-ping-save", true); + } + + /** + * Get the listed server protocols in the config. + * default will be listed as default. + * + * @return Map of String, Integer + */ + public Map getVelocityServerProtocols() { + return get("velocity-servers", Map.class, new HashMap<>()); + } + + @Override + public boolean is1_13TeamColourFix() { + return getBoolean("team-colour-fix", true); + } + + @Override + public boolean isSuppress1_13ConversionErrors() { + return getBoolean("suppress-1_13-conversion-errors", false); + } + + @Override + public boolean isDisable1_13AutoComplete() { + return getBoolean("disable-1_13-auto-complete", false); + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaInjector.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaInjector.java new file mode 100644 index 000000000..4673d23c4 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaInjector.java @@ -0,0 +1,45 @@ +package us.myles.ViaVersion.velocity.platform; + +import io.netty.channel.ChannelInitializer; +import us.myles.ViaVersion.VelocityPlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.platform.ViaInjector; +import us.myles.ViaVersion.util.ReflectionUtil; +import us.myles.ViaVersion.velocity.handlers.VelocityChannelInitializer; + + +public class VelocityViaInjector implements ViaInjector { + @Override + public void inject() throws Exception { + Object connectionManager = ReflectionUtil.get(VelocityPlugin.PROXY, "cm", Object.class); + Object channelInitializerHolder = ReflectionUtil.invoke(connectionManager, "getServerChannelInitializer"); + ChannelInitializer originalIntializer = (ChannelInitializer) ReflectionUtil.invoke(channelInitializerHolder, "get"); + channelInitializerHolder.getClass().getMethod("set", ChannelInitializer.class) + .invoke(channelInitializerHolder, new VelocityChannelInitializer(originalIntializer)); + } + + @Override + public void uninject() { + Via.getPlatform().getLogger().severe("ViaVersion cannot remove itself from Velocity without a reboot!"); + } + + + @Override + public int getServerProtocolVersion() throws Exception { + return getLowestSupportedProtocolVersion(); + } + + public static int getLowestSupportedProtocolVersion() throws Exception { + return ReflectionUtil.getStatic(Class.forName("com.velocitypowered.proxy.protocol.ProtocolConstants"), "MINIMUM_GENERIC_VERSION", int.class); + } + + @Override + public String getEncoderName() { + return "via-encoder"; + } + + @Override + public String getDecoderName() { + return "via-decoder"; + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaLoader.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaLoader.java new file mode 100644 index 000000000..f81447437 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/platform/VelocityViaLoader.java @@ -0,0 +1,47 @@ +package us.myles.ViaVersion.velocity.platform; + +import com.velocitypowered.api.plugin.PluginContainer; +import us.myles.ViaVersion.VelocityPlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.platform.ViaPlatformLoader; +import us.myles.ViaVersion.protocols.base.VersionProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BossBarProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; +import us.myles.ViaVersion.velocity.handlers.VelocityServerHandler; +import us.myles.ViaVersion.velocity.listeners.ElytraPatch; +import us.myles.ViaVersion.velocity.listeners.MainHandPatch; +import us.myles.ViaVersion.velocity.listeners.UpdateListener; +import us.myles.ViaVersion.velocity.providers.VelocityBossBarProvider; +import us.myles.ViaVersion.velocity.providers.VelocityMovementTransmitter; +import us.myles.ViaVersion.velocity.providers.VelocityVersionProvider; +import us.myles.ViaVersion.velocity.service.ProtocolDetectorService; + +public class VelocityViaLoader implements ViaPlatformLoader { + @Override + public void load() { + Object plugin = VelocityPlugin.PROXY.getPluginManager() + .getPlugin("viaversion").flatMap(PluginContainer::getInstance).get(); + + Via.getManager().getProviders().use(MovementTransmitterProvider.class, new VelocityMovementTransmitter()); + Via.getManager().getProviders().use(BossBarProvider.class, new VelocityBossBarProvider()); + Via.getManager().getProviders().use(VersionProvider.class, new VelocityVersionProvider()); + // We probably don't need a EntityIdProvider because velocity sends a Join packet on server change + + VelocityPlugin.PROXY.getEventManager().register(plugin, new UpdateListener()); + VelocityPlugin.PROXY.getEventManager().register(plugin, new VelocityServerHandler()); + VelocityPlugin.PROXY.getEventManager().register(plugin, new MainHandPatch()); + VelocityPlugin.PROXY.getEventManager().register(plugin, new ElytraPatch()); + + int pingInterval = ((VelocityViaConfig) Via.getPlatform().getConf()).getVelocityPingInterval(); + if (pingInterval > 0) { + Via.getPlatform().runRepeatingSync( + new ProtocolDetectorService(), + pingInterval * 20L); + } + } + + @Override + public void unload() { + // Probably not useful, there's no ProxyReloadEvent + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityBossBarProvider.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityBossBarProvider.java new file mode 100644 index 000000000..276d4b931 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityBossBarProvider.java @@ -0,0 +1,30 @@ +package us.myles.ViaVersion.velocity.providers; + +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BossBarProvider; +import us.myles.ViaVersion.velocity.storage.VelocityStorage; + +import java.util.UUID; + +public class VelocityBossBarProvider extends BossBarProvider { + @Override + public void handleAdd(UserConnection user, UUID barUUID) { + if (user.has(VelocityStorage.class)) { + VelocityStorage storage = user.get(VelocityStorage.class); + // Check if bossbars are supported by bungee, static maybe + if (storage.getBossbar() != null) { + storage.getBossbar().add(barUUID); + } + } + } + + @Override + public void handleRemove(UserConnection user, UUID barUUID) { + if (user.has(VelocityStorage.class)) { + VelocityStorage storage = user.get(VelocityStorage.class); + if (storage.getBossbar() != null) { + storage.getBossbar().remove(barUUID); + } + } + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityMovementTransmitter.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityMovementTransmitter.java new file mode 100644 index 000000000..473633790 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityMovementTransmitter.java @@ -0,0 +1,35 @@ +package us.myles.ViaVersion.velocity.providers; + +import us.myles.ViaVersion.api.PacketWrapper; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.type.Type; +import us.myles.ViaVersion.packets.State; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.Protocol1_9TO1_8; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.MovementTracker; + +public class VelocityMovementTransmitter extends MovementTransmitterProvider { + @Override + public Object getFlyingPacket() { + return null; + } + + @Override + public Object getGroundPacket() { + return null; + } + + public void sendPlayer(UserConnection userConnection) { + if (userConnection.get(ProtocolInfo.class).getState() == State.PLAY) { + PacketWrapper wrapper = new PacketWrapper(0x03, null, userConnection); + wrapper.write(Type.BOOLEAN, userConnection.get(MovementTracker.class).isGround()); + try { + wrapper.sendToServer(Protocol1_9TO1_8.class); + } catch (Exception e) { + e.printStackTrace(); + } + // PlayerPackets will increment idle + } + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityVersionProvider.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityVersionProvider.java new file mode 100644 index 000000000..30fd4add9 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityVersionProvider.java @@ -0,0 +1,73 @@ +package us.myles.ViaVersion.velocity.providers; + +import com.google.common.collect.Lists; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.api.protocol.ProtocolVersion; +import us.myles.ViaVersion.protocols.base.ProtocolInfo; +import us.myles.ViaVersion.protocols.base.VersionProvider; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class VelocityVersionProvider extends VersionProvider { + private static Class ref ; + + static { + try { + ref = Class.forName("com.velocitypowered.proxy.protocol.ProtocolConstants"); + } catch (Exception e) { + Via.getPlatform().getLogger().severe("Could not detect the ProtocolConstants class"); + e.printStackTrace(); + } + } + + @Override + public int getServerProtocol(UserConnection user) throws Exception { + if (ref == null) + return super.getServerProtocol(user); + // TODO Have one constant list forever until restart? (Might limit plugins if they change this) + Object list = ReflectionUtil.getStatic(ref, "SUPPORTED_VERSIONS", Object.class); + List sorted = new ArrayList((List) ReflectionUtil.invoke(list, "asList")); + Collections.sort(sorted); + + ProtocolInfo info = user.get(ProtocolInfo.class); + + // Bungee supports it + if (sorted.contains(info.getProtocolVersion())) + return info.getProtocolVersion(); + + // Older than bungee supports, get the lowest version + if (info.getProtocolVersion() < sorted.get(0)) { + return getLowestSupportedVersion(); + } + + // Loop through all protocols to get the closest protocol id that bungee supports (and that viaversion does too) + + // TODO: This needs a better fix, i.e checking ProtocolRegistry to see if it would work. + // This is more of a workaround for snapshot support by bungee. + for (Integer protocol : Lists.reverse(sorted)) { + if (info.getProtocolVersion() > protocol && ProtocolVersion.isRegistered(protocol)) + return protocol; + } + + Via.getPlatform().getLogger().severe("Panic, no protocol id found for " + info.getProtocolVersion()); + return info.getProtocolVersion(); + } + + public static int getLowestSupportedVersion() { + List list; + try { + return ReflectionUtil.getStatic( + Class.forName("com.velocitypowered.proxy.protocol.ProtocolConstants"), + "MINIMUM_GENERIC_VERSION", + int.class); + } catch (NoSuchFieldException | IllegalAccessException | ClassNotFoundException e) { + e.printStackTrace(); + } + // Fallback + return -1; + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/service/ProtocolDetectorService.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/service/ProtocolDetectorService.java new file mode 100644 index 000000000..8abe51927 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/service/ProtocolDetectorService.java @@ -0,0 +1,82 @@ +package us.myles.ViaVersion.velocity.service; + +import com.velocitypowered.api.proxy.server.RegisteredServer; +import lombok.Getter; +import us.myles.ViaVersion.VelocityPlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.api.protocol.ProtocolVersion; +import us.myles.ViaVersion.velocity.platform.VelocityViaConfig; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ProtocolDetectorService implements Runnable { + private static final Map detectedProtocolIds = new ConcurrentHashMap<>(); + @Getter + private static ProtocolDetectorService instance; + + public ProtocolDetectorService() { + instance = this; + } + + public static Integer getProtocolId(String serverName) { + // Step 1. Check Config + Map servers = ((VelocityViaConfig) Via.getConfig()).getVelocityServerProtocols(); + Integer protocol = servers.get(serverName); + if (protocol != null) { + return protocol; + } + // Step 2. Check Detected + Integer detectedProtocol = detectedProtocolIds.get(serverName); + if (detectedProtocol != null) { + return detectedProtocol; + } + // Step 3. Use Default + Integer defaultProtocol = servers.get("default"); + if (defaultProtocol != null) { + return defaultProtocol; + } + // Step 4: Use bungee lowest supported... *cries* + try { + return Via.getManager().getInjector().getServerProtocolVersion(); + } catch (Exception e) { + e.printStackTrace(); + return ProtocolVersion.v1_8.getId(); + } + } + + @Override + public void run() { + for (final RegisteredServer serv : VelocityPlugin.PROXY.getAllServers()) { + probeServer(serv); + } + } + + public static void probeServer(final RegisteredServer serverInfo) { + final String key = serverInfo.getServerInfo().getName(); + serverInfo.ping().thenAccept((serverPing) -> { + if (serverPing != null && serverPing.getVersion() != null) { + detectedProtocolIds.put(key, serverPing.getVersion().getProtocol()); + if (((VelocityViaConfig) Via.getConfig()).isVelocityPingSave()) { + Map servers = ((VelocityViaConfig) Via.getConfig()).getVelocityServerProtocols(); + Integer protocol = servers.get(key); + if (protocol != null && protocol == serverPing.getVersion().getProtocol()) { + return; + } + // Ensure we're the only ones writing to the config + synchronized (Via.getPlatform().getConfigurationProvider()) { + servers.put(key, serverPing.getVersion().getProtocol()); + } + // Save + Via.getPlatform().getConfigurationProvider().saveConfig(); + } + } + }); + } + + public static Map getDetectedIds() { + return new HashMap<>(detectedProtocolIds); + } + +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/storage/VelocityStorage.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/storage/VelocityStorage.java new file mode 100644 index 000000000..353430070 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/storage/VelocityStorage.java @@ -0,0 +1,38 @@ +package us.myles.ViaVersion.velocity.storage; + +import com.velocitypowered.api.proxy.Player; +import lombok.Data; +import lombok.EqualsAndHashCode; +import us.myles.ViaVersion.api.data.StoredObject; +import us.myles.ViaVersion.api.data.UserConnection; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.lang.reflect.InvocationTargetException; +import java.util.Set; +import java.util.UUID; + +@Data +@EqualsAndHashCode(callSuper = true) +public class VelocityStorage extends StoredObject { + private Player player; + private String currentServer; + private Set bossbar; + + public VelocityStorage(UserConnection user, Player player) { + super(user); + this.player = player; + this.currentServer = ""; + + // Get bossbar list if it's supported + try { + Object connection = ReflectionUtil.invoke(player, "getConnection"); + Object sessionHandler = ReflectionUtil.invoke(connection, "getSessionHandler"); + if (sessionHandler.getClass().getSimpleName().contains("Play")) { + bossbar = (Set) ReflectionUtil.invoke(sessionHandler, "getServerBossBars"); + // TODO make this work + } + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + } + } +} diff --git a/velocity/src/main/java/us/myles/ViaVersion/velocity/util/LoggerWrapper.java b/velocity/src/main/java/us/myles/ViaVersion/velocity/util/LoggerWrapper.java new file mode 100644 index 000000000..60300e8c7 --- /dev/null +++ b/velocity/src/main/java/us/myles/ViaVersion/velocity/util/LoggerWrapper.java @@ -0,0 +1,69 @@ +package us.myles.ViaVersion.velocity.util; + +import org.slf4j.Logger; + +import java.text.MessageFormat; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +public class LoggerWrapper extends java.util.logging.Logger { + private final Logger base; + + public LoggerWrapper(Logger logger) { + super("logger", null); + this.base = logger; + } + + @Override + public void log(LogRecord record) { + log(record.getLevel(), record.getMessage()); + } + + @Override + public void log(Level level, String msg) { + if (level == Level.FINE) + base.debug(msg); + else if (level == Level.WARNING) + base.warn(msg); + else if (level == Level.SEVERE) + base.error(msg); + else if (level == Level.INFO) + base.info(msg); + else + base.trace(msg); + } + + @Override + public void log(Level level, String msg, Object param1) { + if (level == Level.FINE) + base.debug(msg, param1); + else if (level == Level.WARNING) + base.warn(msg, param1); + else if (level == Level.SEVERE) + base.error(msg, param1); + else if (level == Level.INFO) + base.info(msg, param1); + else + base.trace(msg, param1); + } + + @Override + public void log(Level level, String msg, Object[] params) { + log(level, MessageFormat.format(msg, params)); // workaround not formatting correctly + } + + @Override + public void log(Level level, String msg, Throwable params) { + if (level == Level.FINE) + base.debug(msg, params); + else if (level == Level.WARNING) + base.warn(msg, params); + else if (level == Level.SEVERE) + base.error(msg, params); + else if (level == Level.INFO) + base.info(msg, params); + else + base.trace(msg, params); + } + +}