From 1f5b3c02de75ee719cdd5257fa51734d35b284ac Mon Sep 17 00:00:00 2001 From: msdigital Date: Mon, 23 Feb 2026 17:48:24 +0100 Subject: [PATCH] Fix server-version manifest matching and extracted asset-pack manifest warnings --- build.gradle.kts | 9 +- src/main/java/com/bumenfeld/clock/Clock.java | 4 + .../ExtractedAssetPackManifestEnsurer.java | 86 +++++++++++++++++++ 3 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/bumenfeld/clock/ExtractedAssetPackManifestEnsurer.java diff --git a/build.gradle.kts b/build.gradle.kts index 1335058..382b599 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -113,14 +113,7 @@ fun formatManifestServerVersion(value: String?): String? { if (trimmed == "*") { return "*" } - if (trimmed.startsWithAny(listOf("<", ">", "=", "~", "^", "[", "(", "x", "X")) || trimmed.contains(" ")) { - return trimmed - } - return ">=$trimmed" -} - -fun String.startsWithAny(prefixes: List): Boolean { - return prefixes.any { this.startsWith(it) } + return trimmed } dependencies { diff --git a/src/main/java/com/bumenfeld/clock/Clock.java b/src/main/java/com/bumenfeld/clock/Clock.java index 2aaafd7..1a5d421 100644 --- a/src/main/java/com/bumenfeld/clock/Clock.java +++ b/src/main/java/com/bumenfeld/clock/Clock.java @@ -5,6 +5,8 @@ import com.bumenfeld.clock.PlayerClockSettings; import com.bumenfeld.clock.ClockTickSystem; import com.hypixel.hytale.component.ComponentType; +import com.hypixel.hytale.event.EventPriority; +import com.hypixel.hytale.server.core.event.events.BootEvent; import com.hypixel.hytale.server.core.plugin.JavaPlugin; import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.util.Config; @@ -22,6 +24,8 @@ public Clock(JavaPluginInit init) { @Override public void setup() { + ExtractedAssetPackManifestEnsurer.ensure(this); + getEventRegistry().register(EventPriority.LAST, BootEvent.class, event -> ExtractedAssetPackManifestEnsurer.ensure(this)); config.save(); playerSettingsComponent = getEntityStoreRegistry() .registerComponent(PlayerClockSettings.class, "BumenfeldClockSettings", PlayerClockSettings.CODEC); diff --git a/src/main/java/com/bumenfeld/clock/ExtractedAssetPackManifestEnsurer.java b/src/main/java/com/bumenfeld/clock/ExtractedAssetPackManifestEnsurer.java new file mode 100644 index 0000000..cc3656c --- /dev/null +++ b/src/main/java/com/bumenfeld/clock/ExtractedAssetPackManifestEnsurer.java @@ -0,0 +1,86 @@ +package com.bumenfeld.clock; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.hypixel.hytale.server.core.plugin.JavaPlugin; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + +final class ExtractedAssetPackManifestEnsurer { + private static final ObjectMapper MAPPER = new ObjectMapper(); + + private ExtractedAssetPackManifestEnsurer() { + } + + static void ensure(JavaPlugin plugin) { + try { + var pluginManifest = plugin.getManifest(); + if (pluginManifest == null || !pluginManifest.includesAssetPack()) { + return; + } + + Path dataDirectory = plugin.getDataDirectory(); + if (dataDirectory == null) { + return; + } + + Files.createDirectories(dataDirectory); + Path extractedManifest = dataDirectory.resolve("manifest.json"); + String extractedPackName = extractedPackName(pluginManifest.getName()); + if (!shouldWriteExtractedManifest(extractedManifest, pluginManifest.getGroup(), pluginManifest.getName(), extractedPackName)) { + return; + } + + try (InputStream stream = plugin.getClass().getClassLoader().getResourceAsStream("manifest.json")) { + if (stream == null) { + return; + } + JsonNode root = MAPPER.readTree(stream); + if (!(root instanceof ObjectNode rootObject)) { + return; + } + + rootObject.put("Name", extractedPackName); + rootObject.put("IncludesAssetPack", false); + MAPPER.writerWithDefaultPrettyPrinter().writeValue(extractedManifest.toFile(), rootObject); + } + } catch (IOException ignored) { + // Best-effort compatibility fix for hosters that create extracted mod folders without a root manifest. + } catch (RuntimeException ignored) { + // Best-effort compatibility fix for hosters that create extracted mod folders without a root manifest. + } + } + + private static boolean shouldWriteExtractedManifest(Path path, String pluginGroup, String pluginName, String extractedPackName) { + if (!Files.exists(path)) { + return true; + } + + try { + JsonNode root = MAPPER.readTree(path.toFile()); + String group = root.path("Group").asText(""); + String name = root.path("Name").asText(""); + + if (group.equals(pluginGroup) && name.equals(extractedPackName)) { + return false; + } + if (group.equals(pluginGroup) && name.equals(pluginName)) { + return true; + } + return false; + } catch (IOException ignored) { + return true; + } + } + + private static String extractedPackName(String pluginName) { + if (pluginName == null || pluginName.isBlank()) { + return "Config_Plugin"; + } + return "Config_" + pluginName; + } +}