From 5ad62a03ede6b8197899e0fab8d237bf3b1d38f1 Mon Sep 17 00:00:00 2001 From: KennyTV <28825609+KennyTV@users.noreply.github.com> Date: Sun, 5 Jan 2020 21:21:58 +0100 Subject: [PATCH 1/3] Make plugin channel mappings modifiable --- .../api/data/MappingDataLoader.java | 39 +++++++++++++--- .../ViaVersion/api/platform/ViaPlatform.java | 8 ++++ .../data/MappingData.java | 32 +++++++++++++ .../packets/InventoryPackets.java | 46 ++++--------------- .../viaversion/data/channelmappings-1.13.json | 7 +++ .../us/myles/ViaVersion/SpongePlugin.java | 5 ++ .../us/myles/ViaVersion/VelocityPlugin.java | 6 +++ 7 files changed, 100 insertions(+), 43 deletions(-) create mode 100644 common/src/main/resources/assets/viaversion/data/channelmappings-1.13.json diff --git a/common/src/main/java/us/myles/ViaVersion/api/data/MappingDataLoader.java b/common/src/main/java/us/myles/ViaVersion/api/data/MappingDataLoader.java index dcc4f25cc..0963e137e 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/data/MappingDataLoader.java +++ b/common/src/main/java/us/myles/ViaVersion/api/data/MappingDataLoader.java @@ -1,20 +1,41 @@ package us.myles.ViaVersion.api.data; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; +import com.google.gson.*; 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.*; +import java.nio.file.Files; import java.util.Map; public class MappingDataLoader { + public static JsonObject loadFromDataDir(String name) { + File file = new File(Via.getPlatform().getDataFolder(), name); + if (!file.exists()) { + try (InputStream in = getResource(name)) { + Files.copy(in, file.toPath()); + } catch (IOException e) { + Via.getPlatform().getLogger().warning("Error loading " + name + " from the config directory!"); + e.printStackTrace(); + return null; + } + } + + try (FileReader reader = new FileReader(file)) { + return GsonUtil.getGson().fromJson(reader, JsonObject.class); + } catch (IOException e) { + e.printStackTrace(); + return null; + } catch (JsonSyntaxException | JsonIOException e) { + Via.getPlatform().getLogger().warning(name + " is badly formatted!"); + e.printStackTrace(); + return null; + } + } + public static JsonObject loadData(String name) { - InputStream stream = MappingDataLoader.class.getClassLoader().getResourceAsStream("assets/viaversion/data/" + name); + InputStream stream = getResource(name); InputStreamReader reader = new InputStreamReader(stream); try { return GsonUtil.getGson().fromJson(reader, JsonObject.class); @@ -107,4 +128,8 @@ public class MappingDataLoader { } return null; } + + private static InputStream getResource(String name) { + return MappingDataLoader.class.getClassLoader().getResourceAsStream("assets/viaversion/data/" + name); + } } diff --git a/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java b/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java index 796910a52..b04bb75c7 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java +++ b/common/src/main/java/us/myles/ViaVersion/api/platform/ViaPlatform.java @@ -6,6 +6,7 @@ import us.myles.ViaVersion.api.ViaVersionConfig; import us.myles.ViaVersion.api.command.ViaCommandSender; import us.myles.ViaVersion.api.configuration.ConfigurationProvider; +import java.io.File; import java.util.UUID; import java.util.logging.Logger; @@ -139,6 +140,13 @@ public interface ViaPlatform { */ ConfigurationProvider getConfigurationProvider(); + /** + * Get ViaVersions's data folder. + * + * @return data folder + */ + File getDataFolder(); + /** * Called when a reload happens */ 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 e3ea1e6e8..b949e9982 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 @@ -27,6 +27,7 @@ public class MappingData { public static final BiMap oldEnchantmentsIds = HashBiMap.create(); public static final Map translateMapping = new HashMap<>(); public static final Map mojangTranslation = new HashMap<>(); + public static final BiMap channelMappings = HashBiMap.create(); // 1.12->1.13 public static Mappings enchantmentMappings; public static Mappings soundMappings; public static Mappings blockMappings; @@ -48,6 +49,21 @@ public class MappingData { enchantmentMappings = new Mappings(72, mapping1_12.getAsJsonObject("enchantments"), mapping1_13.getAsJsonObject("enchantments")); Via.getPlatform().getLogger().info("Loading 1.12.2 -> 1.13 sound mapping..."); soundMappings = new Mappings(662, mapping1_12.getAsJsonArray("sounds"), mapping1_13.getAsJsonArray("sounds")); + Via.getPlatform().getLogger().info("Loading 1.12.2 -> 1.13 plugin channel mappings..."); + + JsonObject object = MappingDataLoader.loadFromDataDir("channelmappings-1.13.json"); + if (object != null) { + for (Map.Entry entry : object.entrySet()) { + String oldChannel = entry.getKey(); + String newChannel = entry.getValue().getAsString(); + if (!isValid1_13Channel(newChannel)) { + Via.getPlatform().getLogger().warning("Channel '" + newChannel + "' is not a valid 1.13 plugin channel, please check your configuration!"); + continue; + } + channelMappings.put(oldChannel, newChannel); + } + } + Via.getPlatform().getLogger().info("Loading translation mappping"); Map translateData = GsonUtil.getGson().fromJson( new InputStreamReader(MappingData.class.getClassLoader().getResourceAsStream("assets/viaversion/data/mapping-lang-1.12-1.13.json")), @@ -79,6 +95,22 @@ public class MappingData { } } + public static String validateNewChannel(String newId) { + if (!isValid1_13Channel(newId)) { + return null; // Not valid + } + int separatorIndex = newId.indexOf(':'); + // Vanilla parses ``:`` and ```` as ``minecraft:`` (also ensure there's enough space) + if ((separatorIndex == -1 || separatorIndex == 0) && newId.length() <= 10) { + newId = "minecraft:" + newId; + } + return newId; + } + + public static boolean isValid1_13Channel(String channelId) { + return channelId.matches("([0-9a-z_.-]+):([0-9a-z_/.-]+)"); + } + private static void loadTags(Map output, JsonObject newTags) { for (Map.Entry entry : newTags.entrySet()) { JsonArray ids = entry.getValue().getAsJsonArray(); 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 42fcac91f..1db3bc618 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 @@ -443,6 +443,7 @@ public class InventoryPackets { } public static String getNewPluginChannelId(String old) { + // Default channels that should not be modifiable switch (old) { case "MC|TrList": return "minecraft:trader_list"; @@ -460,21 +461,12 @@ public class InventoryPackets { return "minecraft:unregister"; case "BungeeCord": return "bungeecord:main"; - case "WDL|INIT": - return "wdl:init"; - case "WDL|CONTROL": - return "wdl:control"; - case "WDL|REQUEST": - return "wdl:request"; case "bungeecord:main": return null; - case "FML|MP": - return "fml:mp"; - case "FML|HS": - return "fml:hs"; default: - return old.matches("([0-9a-z_.-]+):([0-9a-z_/.-]+)") // Identifier regex - ? old : null; + String mappedChannel = MappingData.channelMappings.get(old); + if (mappedChannel != null) return mappedChannel; + return MappingData.isValid1_13Channel(old) ? old : null; } } @@ -682,31 +674,11 @@ public class InventoryPackets { } public static String getOldPluginChannelId(String newId) { - if (!newId.matches("([0-9a-z_.-]+):([0-9a-z_/.-]+)")) { - return null; // Not valid - } - int separatorIndex = newId.indexOf(':'); - // Vanilla parses ``:`` and ```` as ``minecraft:`` (also ensure there's enough space) - if ((separatorIndex == -1 || separatorIndex == 0) && newId.length() <= 10) { - newId = "minecraft:" + newId; - } + newId = MappingData.validateNewChannel(newId); + if (newId == null) return null; + + // Default channels that should not be modifiable switch (newId) { - case "minecraft:trader_list": - return "MC|TrList"; - case "minecraft:book_open": - return "MC|BOpen"; - case "minecraft:debug/paths": - return "MC|DebugPath"; - case "minecraft:debug/neighbors_update": - return "MC|DebugNeighborsUpdate"; - case "minecraft:register": - return "REGISTER"; - case "minecraft:unregister": - return "UNREGISTER"; - case "minecraft:brand": - return "MC|Brand"; - case "bungeecord:main": - return "BungeeCord"; case "wdl:init": return "WDL|INIT"; case "wdl:control": @@ -718,6 +690,8 @@ public class InventoryPackets { case "fml:mp": return "FML:MP"; default: + String mappedChannel = MappingData.channelMappings.inverse().get(newId); + if (mappedChannel != null) return mappedChannel; return newId.length() > 20 ? newId.substring(0, 20) : newId; } } diff --git a/common/src/main/resources/assets/viaversion/data/channelmappings-1.13.json b/common/src/main/resources/assets/viaversion/data/channelmappings-1.13.json new file mode 100644 index 000000000..3e1b36593 --- /dev/null +++ b/common/src/main/resources/assets/viaversion/data/channelmappings-1.13.json @@ -0,0 +1,7 @@ +{ + "WDL|INIT": "wdl:init", + "WDL|CONTROL": "wdl:control", + "WDL|REQUEST": "wdl:request", + "FML|MP": "fml:mp", + "FML|HS": "fml:hs" +} \ No newline at end of file diff --git a/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java b/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java index 670dd56ae..3b5285920 100644 --- a/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java +++ b/sponge/src/main/java/us/myles/ViaVersion/SpongePlugin.java @@ -195,6 +195,11 @@ public class SpongePlugin implements ViaPlatform { return conf; } + @Override + public File getDataFolder() { + return defaultConfig.getParentFile(); + } + @Override public void onReload() { getLogger().severe("ViaVersion is already loaded, this should work fine. If you get any console errors, try rebooting."); diff --git a/velocity/src/main/java/us/myles/ViaVersion/VelocityPlugin.java b/velocity/src/main/java/us/myles/ViaVersion/VelocityPlugin.java index 44c7ca459..59e0e9980 100644 --- a/velocity/src/main/java/us/myles/ViaVersion/VelocityPlugin.java +++ b/velocity/src/main/java/us/myles/ViaVersion/VelocityPlugin.java @@ -30,6 +30,7 @@ import us.myles.ViaVersion.velocity.platform.*; import us.myles.ViaVersion.velocity.service.ProtocolDetectorService; import us.myles.ViaVersion.velocity.util.LoggerWrapper; +import java.io.File; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -176,6 +177,11 @@ public class VelocityPlugin implements ViaPlatform { return conf; } + @Override + public File getDataFolder() { + return configDir.toFile(); + } + @Override public void onReload() { From 4bdb566fb5fb1ee7e3aa883bee1575e592980e1c Mon Sep 17 00:00:00 2001 From: KennyTV <28825609+KennyTV@users.noreply.github.com> Date: Sun, 5 Jan 2020 21:23:40 +0100 Subject: [PATCH 2/3] Kept the wrong defaults --- .../packets/InventoryPackets.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) 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 1db3bc618..9c5643c53 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 @@ -679,16 +679,22 @@ public class InventoryPackets { // Default channels that should not be modifiable switch (newId) { - case "wdl:init": - return "WDL|INIT"; - case "wdl:control": - return "WDL|CONTROL"; - case "wdl:request": - return "WDL|REQUEST"; - case "fml:hs": - return "FML|HS"; - case "fml:mp": - return "FML:MP"; + case "minecraft:trader_list": + return "MC|TrList"; + case "minecraft:book_open": + return "MC|BOpen"; + case "minecraft:debug/paths": + return "MC|DebugPath"; + case "minecraft:debug/neighbors_update": + return "MC|DebugNeighborsUpdate"; + case "minecraft:register": + return "REGISTER"; + case "minecraft:unregister": + return "UNREGISTER"; + case "minecraft:brand": + return "MC|Brand"; + case "bungeecord:main": + return "BungeeCord"; default: String mappedChannel = MappingData.channelMappings.inverse().get(newId); if (mappedChannel != null) return mappedChannel; From 3384b6bc1756d14f0dbd592035006c45e284f4ec Mon Sep 17 00:00:00 2001 From: KennyTV Date: Mon, 6 Jan 2020 10:52:42 +0100 Subject: [PATCH 3/3] Only load mappings file from dir if manually copied --- .../api/data/MappingDataLoader.java | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/common/src/main/java/us/myles/ViaVersion/api/data/MappingDataLoader.java b/common/src/main/java/us/myles/ViaVersion/api/data/MappingDataLoader.java index 0963e137e..299cb166e 100644 --- a/common/src/main/java/us/myles/ViaVersion/api/data/MappingDataLoader.java +++ b/common/src/main/java/us/myles/ViaVersion/api/data/MappingDataLoader.java @@ -5,33 +5,25 @@ import us.myles.ViaVersion.api.Via; import us.myles.ViaVersion.util.GsonUtil; import java.io.*; -import java.nio.file.Files; import java.util.Map; public class MappingDataLoader { public static JsonObject loadFromDataDir(String name) { File file = new File(Via.getPlatform().getDataFolder(), name); - if (!file.exists()) { - try (InputStream in = getResource(name)) { - Files.copy(in, file.toPath()); - } catch (IOException e) { - Via.getPlatform().getLogger().warning("Error loading " + name + " from the config directory!"); - e.printStackTrace(); - return null; - } - } + if (!file.exists()) return loadData(name); + // Load the file from the platform's directory if present try (FileReader reader = new FileReader(file)) { return GsonUtil.getGson().fromJson(reader, JsonObject.class); - } catch (IOException e) { - e.printStackTrace(); - return null; - } catch (JsonSyntaxException | JsonIOException e) { + } catch (JsonSyntaxException e) { + // Users might mess up the format, so let's catch the syntax error Via.getPlatform().getLogger().warning(name + " is badly formatted!"); e.printStackTrace(); - return null; + } catch (IOException | JsonIOException e) { + e.printStackTrace(); } + return null; } public static JsonObject loadData(String name) {