From 7ce674b1f6b33e769d0b63624c02862659aa6bf7 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 28 Jan 2022 16:28:42 +0100 Subject: [PATCH] Improved Version handling for mod info exchange --- src/main/java/ru/bclib/BCLib.java | 7 + .../handler/autosync/HelloClient.java | 37 ++--- .../ru/bclib/gui/screens/ModListScreen.java | 10 +- src/main/java/ru/bclib/util/ModUtil.java | 130 +++++++++++------- 4 files changed, 111 insertions(+), 73 deletions(-) diff --git a/src/main/java/ru/bclib/BCLib.java b/src/main/java/ru/bclib/BCLib.java index f80d8a0d..9428b1ee 100644 --- a/src/main/java/ru/bclib/BCLib.java +++ b/src/main/java/ru/bclib/BCLib.java @@ -17,6 +17,7 @@ import ru.bclib.recipes.CraftingRecipes; import ru.bclib.registry.BaseBlockEntities; import ru.bclib.registry.BaseRegistry; import ru.bclib.util.Logger; +import ru.bclib.util.ModUtil; import ru.bclib.world.generator.BCLibEndBiomeSource; import ru.bclib.world.generator.BCLibNetherBiomeSource; import ru.bclib.world.generator.GeneratorOptions; @@ -29,6 +30,12 @@ public class BCLib implements ModInitializer { @Override public void onInitialize() { + System.out.println(ModUtil.convertModVersion("1.2")); + System.out.println(ModUtil.convertModVersion("1.2.3")); + System.out.println(ModUtil.convertModVersion("1.2.3-4.5")); + + var mods = ModUtil.getMods(); + mods.entrySet().forEach(e->System.out.println(e.getKey() + ": " + ModUtil.getModVersion(e.getKey()) +" - " + ModUtil.convertModVersion(ModUtil.convertModVersion(e.getValue().getVersion())))); BaseRegistry.register(); GeneratorOptions.init(); BaseBlockEntities.register(); diff --git a/src/main/java/ru/bclib/api/dataexchange/handler/autosync/HelloClient.java b/src/main/java/ru/bclib/api/dataexchange/handler/autosync/HelloClient.java index 9c693c2d..3daad63d 100644 --- a/src/main/java/ru/bclib/api/dataexchange/handler/autosync/HelloClient.java +++ b/src/main/java/ru/bclib/api/dataexchange/handler/autosync/HelloClient.java @@ -177,8 +177,6 @@ public class HelloClient extends DataHandler.FromServer { protected void deserializeIncomingDataOnClient(FriendlyByteBuf buf, PacketSender responseSender) { //read BCLibVersion (=protocol version) bclibVersion = ModUtil.convertModVersion(buf.readInt()); - final boolean protocolVersion_0_4_1 = ModUtil.isLargerOrEqualVersion(bclibVersion, "0.4.1"); - //read Plugin Versions modVersion = new ServerModMap(); @@ -189,14 +187,8 @@ public class HelloClient extends DataHandler.FromServer { final int size; final boolean canDownload; //since v0.4.1 we also send the size of the mod-File - if (protocolVersion_0_4_1) { - size = buf.readInt(); - canDownload = buf.readBoolean(); - } - else { - size = 0; - canDownload = true; - } + size = buf.readInt(); + canDownload = buf.readBoolean(); modVersion.put(id, new OfferedModInfo(version, size, canDownload)); } @@ -213,15 +205,13 @@ public class HelloClient extends DataHandler.FromServer { autoSynFolders = new ArrayList<>(1); //since v0.4.1 we also send the sync folders - if (protocolVersion_0_4_1) { - final int folderCount = buf.readInt(); - for (int i = 0; i < folderCount; i++) { - SyncFolderDescriptor desc = SyncFolderDescriptor.deserialize(buf); - autoSynFolders.add(desc); - } - - serverPublishedModInfo = buf.readBoolean(); + final int folderCount = buf.readInt(); + for (int i = 0; i < folderCount; i++) { + SyncFolderDescriptor desc = SyncFolderDescriptor.deserialize(buf); + autoSynFolders.add(desc); } + + serverPublishedModInfo = buf.readBoolean(); } @Environment(EnvType.CLIENT) @@ -266,7 +256,7 @@ public class HelloClient extends DataHandler.FromServer { SubFile localSubFile = localDescriptor.getLocalSubFile(subFile.relPath); if (localSubFile != null) { //the file exists locally, check if the hashes match - if (!localSubFile.hash.equals(subFile.hash)) { + if (true || !localSubFile.hash.equals(subFile.hash)) { BCLib.LOGGER.info(" * " + subFile.relPath + " (changed)"); filesToRequest.add(new AutoSyncID.ForDirectFileRequest(desc.folderID, new File(subFile.relPath))); } @@ -333,11 +323,14 @@ public class HelloClient extends DataHandler.FromServer { @Environment(EnvType.CLIENT) private void processModFileSync(final List filesToRequest, final Set mismatchingMods) { for (Entry e : modVersion.entrySet()) { - final String localVersion = ModUtil.getModVersion(e.getKey()); + final String localVersion = ModUtil.convertModVersion(ModUtil.convertModVersion(ModUtil.getModVersion(e.getKey()))); final OfferedModInfo serverInfo = e.getValue(); - final boolean requestMod = !serverInfo.version.equals(localVersion) && serverInfo.size > 0 && serverInfo.canDownload; - BCLib.LOGGER.info(" - " + e.getKey() + " (client=" + localVersion + ", server=" + serverInfo.version + ", size=" + PathUtil.humanReadableFileSize(serverInfo.size) + (requestMod ? ", requesting" : "") + (serverInfo.canDownload ? "" :", not offered")+ ")"); + ModInfo nfo = ModUtil.getModInfo(e.getKey()); + final boolean clientOnly = nfo!=null && nfo.metadata.getEnvironment()==ModEnvironment.CLIENT; + final boolean requestMod = !clientOnly && !serverInfo.version.equals(localVersion) && serverInfo.size > 0 && serverInfo.canDownload; + + BCLib.LOGGER.info(" - " + e.getKey() + " (client=" + localVersion + ", server=" + serverInfo.version + ", size=" + PathUtil.humanReadableFileSize(serverInfo.size) + (requestMod ? ", requesting" : "") + (serverInfo.canDownload ? "" :", not offered") + (clientOnly?", client only":"")+ ")"); if (requestMod) { filesToRequest.add(new AutoSyncID.ForModFileRequest(e.getKey(), serverInfo.version)); } diff --git a/src/main/java/ru/bclib/gui/screens/ModListScreen.java b/src/main/java/ru/bclib/gui/screens/ModListScreen.java index 4a923aad..e4d06201 100644 --- a/src/main/java/ru/bclib/gui/screens/ModListScreen.java +++ b/src/main/java/ru/bclib/gui/screens/ModListScreen.java @@ -76,6 +76,7 @@ public class ModListScreen extends BCLibScreen { final int STATE_OK = 6; final int STATE_SERVER_MISSING_CLIENT_MOD = 5; final int STATE_MISSING_NOT_OFFERED = 4; + final int STATE_VERSION_CLIENT_ONLY = 7; final int STATE_VERSION_NOT_OFFERED = 3; final int STATE_VERSION = 2; final int STATE_SERVER_MISSING = 1; @@ -114,7 +115,10 @@ public class ModListScreen extends BCLibScreen { final String modVer = data.version(); final int size = data.size(); if (!modVer.equals(mod.getVersion())) { - state = data.canDownload()?STATE_VERSION:STATE_VERSION_NOT_OFFERED; + if (mod.metadata.getEnvironment() == ModEnvironment.CLIENT) + state = STATE_VERSION_CLIENT_ONLY; + else + state = data.canDownload()?STATE_VERSION:STATE_VERSION_NOT_OFFERED; serverVersion = modVer; serverSize = size; } @@ -150,10 +154,12 @@ public class ModListScreen extends BCLibScreen { int color = GridLayout.COLOR_RED; final String typeText; - if (state==STATE_VERSION || state==STATE_VERSION_NOT_OFFERED) { + if (state==STATE_VERSION || state==STATE_VERSION_NOT_OFFERED || state==STATE_VERSION_CLIENT_ONLY) { typeText = "[VERSION]"; if (state == STATE_VERSION_NOT_OFFERED) { color = GridLayout.COLOR_YELLOW; + } else if (state == STATE_VERSION_CLIENT_ONLY) { + color = GridLayout.COLOR_DARK_GREEN; } } else if (state==STATE_MISSING || state==STATE_MISSING_NOT_OFFERED) { typeText = "[MISSING]"; diff --git a/src/main/java/ru/bclib/util/ModUtil.java b/src/main/java/ru/bclib/util/ModUtil.java index 94ab1097..8145b7bf 100644 --- a/src/main/java/ru/bclib/util/ModUtil.java +++ b/src/main/java/ru/bclib/util/ModUtil.java @@ -62,53 +62,31 @@ public class ModUtil { mods = new HashMap<>(); org.apache.logging.log4j.Logger logger = LogManager.getFormatterLogger("BCLib|ModLoader"); - PathUtil.fileWalker(PathUtil.MOD_FOLDER.toFile(), false, (file -> { - try { - URI uri = URI.create("jar:" + file.toUri()); - FileSystem fs = FileSystems.getFileSystem(uri); - if (fs!=null) { - try { - Path modMetaFile = fs.getPath("fabric.mod.json"); - if (modMetaFile != null) { - try (InputStream is = Files.newInputStream(modMetaFile)) { - //ModMetadata mc = ModMetadataParser.parseMetadata(is, uri.toString(), new LinkedList()); - ModMetadata mc = readJSON(is, uri.toString()); - if (mc!=null){ - mods.put(mc.getId(), new ModInfo(mc, file)); - } - } - } - } catch (Exception e) { - BCLib.LOGGER.error(e.getMessage()); - } - } - } - catch (Exception e) { - BCLib.LOGGER.error(e.getMessage()); - } - })); + PathUtil.fileWalker(PathUtil.MOD_FOLDER.toFile(), false, (ModUtil::accept)); return mods; } private static ModMetadata readJSON(InputStream is, String sourceFile) throws IOException { try (com.google.gson.stream.JsonReader reader = new JsonReader(new InputStreamReader(is, StandardCharsets.UTF_8))) { - JsonObject data = new JsonParser().parse(reader).getAsJsonObject(); + JsonObject data = new JsonParser().parse(reader) + .getAsJsonObject(); Version ver; try { - ver = new SemanticVersionImpl(data.get("version").getAsString(), false); + ver = new SemanticVersionImpl(data.get("version") + .getAsString(), false); } catch (VersionParsingException e) { BCLib.LOGGER.error("Unable to parse Version in " + sourceFile); return null; } - if (data.get("id") == null){ + if (data.get("id") == null) { BCLib.LOGGER.error("Unable to read ID in " + sourceFile); return null; } - if (data.get("name") == null){ + if (data.get("name") == null) { BCLib.LOGGER.error("Unable to read name in " + sourceFile); return null; } @@ -118,6 +96,7 @@ public class ModUtil { public Version getVersion() { return ver; } + @Override public String getType() { return "fabric"; @@ -125,7 +104,8 @@ public class ModUtil { @Override public String getId() { - return data.get("id").getAsString(); + return data.get("id") + .getAsString(); } @Override @@ -136,35 +116,44 @@ public class ModUtil { @Override public ModEnvironment getEnvironment() { JsonElement env = data.get("environment"); - if (env==null) { + if (env == null) { BCLib.LOGGER.warning("No environment specified in " + sourceFile); //return ModEnvironment.UNIVERSAL; } - final String environment = env==null?"":env.getAsString().toLowerCase(Locale.ROOT); + final String environment = env == null ? "" : env.getAsString() + .toLowerCase(Locale.ROOT); - if (environment.isEmpty() || environment.equals("*") || environment.equals("common")) { + if (environment.isEmpty() || environment.equals("*") || environment.equals("\"*\"") || environment.equals("common")) { JsonElement entrypoints = data.get("entrypoints"); boolean hasClient = true; //check if there is an actual client entrypoint - if (entrypoints!=null && entrypoints.isJsonObject()){ - JsonElement client = entrypoints.getAsJsonObject().get("client"); - if (client!=null && client.isJsonArray()){ - hasClient = client.getAsJsonArray().size() > 0; - } else if (client==null || !client.isJsonPrimitive()){ + if (entrypoints != null && entrypoints.isJsonObject()) { + JsonElement client = entrypoints.getAsJsonObject() + .get("client"); + if (client != null && client.isJsonArray()) { + hasClient = client.getAsJsonArray() + .size() > 0; + } + else if (client == null || !client.isJsonPrimitive()) { hasClient = false; - } else if (!client.getAsJsonPrimitive().isString()){ + } + else if (!client.getAsJsonPrimitive() + .isString()) { hasClient = false; } } - if (hasClient == false) return ModEnvironment.SERVER; + //if (hasClient == false) return ModEnvironment.SERVER; return ModEnvironment.UNIVERSAL; - } else if (environment.equals("client")) { + } + else if (environment.equals("client")) { return ModEnvironment.CLIENT; - } else if (environment.equals("server")) { + } + else if (environment.equals("server")) { return ModEnvironment.SERVER; - } else { + } + else { BCLib.LOGGER.error("Unable to read environment in " + sourceFile); return ModEnvironment.UNIVERSAL; } @@ -201,7 +190,8 @@ public class ModUtil { @Override public String getName() { - return data.get("name").getAsString(); + return data.get("name") + .getAsString(); } @Override @@ -325,13 +315,16 @@ public class ModUtil { } try { int res = 0; - final String semanticVersionPattern = "(\\d+)\\.(\\d+)\\.(\\d+)\\D*"; + final String semanticVersionPattern = "(\\d+)\\.(\\d+)(\\.(\\d+))?\\D*"; final Matcher matcher = Pattern.compile(semanticVersionPattern) .matcher(version); if (matcher.find()) { - if (matcher.groupCount() > 0) res = (Integer.parseInt(matcher.group(1)) & 0xFF) << 22; - if (matcher.groupCount() > 1) res |= (Integer.parseInt(matcher.group(2)) & 0xFF) << 14; - if (matcher.groupCount() > 2) res |= Integer.parseInt(matcher.group(3)) & 0x3FFF; + if (matcher.groupCount() > 0) + res = matcher.group(1) == null ? 0 : ((Integer.parseInt(matcher.group(1)) & 0xFF) << 22); + if (matcher.groupCount() > 1) + res |= matcher.group(2) == null ? 0 : ((Integer.parseInt(matcher.group(2)) & 0xFF) << 14); + if (matcher.groupCount() > 3) + res |= matcher.group(4) == null ? 0 : Integer.parseInt(matcher.group(4)) & 0x3FFF; } return res; @@ -376,6 +369,43 @@ public class ModUtil { return convertModVersion(v1) >= convertModVersion(v2); } + private static void accept(Path file) { + try { + URI uri = URI.create("jar:" + file.toUri()); + System.out.println(uri); + + FileSystem fs; + try { + fs = FileSystems.getFileSystem(uri); + } + catch (Exception e) { + fs = FileSystems.newFileSystem(file); + } + if (fs != null) { + try { + Path modMetaFile = fs.getPath("fabric.mod.json"); + if (modMetaFile != null) { + try (InputStream is = Files.newInputStream(modMetaFile)) { + //ModMetadata mc = ModMetadataParser.parseMetadata(is, uri.toString(), new LinkedList()); + ModMetadata mc = readJSON(is, uri.toString()); + if (mc != null) { + mods.put(mc.getId(), new ModInfo(mc, file)); + } + } + } + } + catch (Exception e) { + BCLib.LOGGER.error("Error for " + uri + ": " + e.toString()); + } + fs.close(); + } + } + catch (Exception e) { + BCLib.LOGGER.error("Error for " + file.toUri() + ": " + e.toString()); + e.printStackTrace(); + } + } + public static class ModInfo { public final ModMetadata metadata; public final Path jarPath; @@ -416,7 +446,9 @@ public class ModUtil { } public String getVersion() { - if (metadata == null) return "0.0.0"; + if (metadata == null) { + return "0.0.0"; + } return versionToString(metadata.getVersion()); } }