From 3d4655c0018ed4fb024328780f98ab65fa1bb646 Mon Sep 17 00:00:00 2001 From: suerion <55131959+suerion@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:50:38 +0100 Subject: [PATCH 01/56] Trying to change UI to look how it work Added 2 Buttons and changed one highend lowend complete server pack --- .../skidam/automodpack/client/ui/DangerScreen.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java index cfc204cf9..e2a6eb86c 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java @@ -33,8 +33,16 @@ protected void init() { this.client.setScreen(parent); })); - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.confirm").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.highendconfirm").formatted(Formatting.BOLD), button -> { + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startHighUpdate); + })); + + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.lowendconfirm").formatted(Formatting.BOLD), button -> { + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startLowUpdate); + })); + + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.completeconfirm").formatted(Formatting.BOLD), button -> { + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); })); } From 7a18905191d4f61ab25f7af50265624aa6b39003 Mon Sep 17 00:00:00 2001 From: suerion <55131959+suerion@users.noreply.github.com> Date: Mon, 16 Dec 2024 22:58:43 +0100 Subject: [PATCH 02/56] change language file for UI Buttons --- src/main/resources/assets/automodpack/lang/en_us.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/resources/assets/automodpack/lang/en_us.json b/src/main/resources/assets/automodpack/lang/en_us.json index 1fb899fd6..0abf0072c 100644 --- a/src/main/resources/assets/automodpack/lang/en_us.json +++ b/src/main/resources/assets/automodpack/lang/en_us.json @@ -19,6 +19,9 @@ "automodpack.danger.description": "Do you want to download it?", "automodpack.danger.secDescription": "It might be risky! Do NOT download if don't trust the server owners!", "automodpack.danger.confirm": "Download", + "automodpack.danger.highendconfirm": "Download for High End PC's", + "automodpack.danger.lowendconfirm": "Download for Low End PC's", + "automodpack.danger.completeconfirm": "Download Full Server Pack", "automodpack.danger.cancel": "Don't download", "automodpack.changelog.view": "View changelogs", @@ -48,4 +51,4 @@ "automodpack.cancel": "Cancel", "automodpack.back": "Back", "automodpack.wait": "Please wait..." - } \ No newline at end of file + } From f3234ba78ab72f8656ab9a9f3b8640d9c7174891 Mon Sep 17 00:00:00 2001 From: suerion <55131959+suerion@users.noreply.github.com> Date: Mon, 16 Dec 2024 23:00:30 +0100 Subject: [PATCH 03/56] deutsch angepasst --- src/main/resources/assets/automodpack/lang/de_de.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/resources/assets/automodpack/lang/de_de.json b/src/main/resources/assets/automodpack/lang/de_de.json index 7ae6d5fcf..b7b07fcc7 100644 --- a/src/main/resources/assets/automodpack/lang/de_de.json +++ b/src/main/resources/assets/automodpack/lang/de_de.json @@ -17,6 +17,9 @@ "automodpack.danger.description": "Möchtest du es herunterladen?", "automodpack.danger.secDescription": "Es könnte riskant sein! Lade es NICHT herunter, wenn du den Server-Betreibern nicht vertraust!", "automodpack.danger.confirm": "Herunterladen", + "automodpack.danger.highendconfirm": "Lade das Pack für High End PC's", + "automodpack.danger.lowendconfirm": "Lade das Pack für High End PC's", + "automodpack.danger.completeconfirm": "Lade das komplette Server Pack", "automodpack.danger.cancel": "Nicht herunterladen", "automodpack.changelog.view": "Änderungen anzeigen", @@ -45,4 +48,4 @@ "automodpack.cancel": "Abbrechen", "automodpack.back": "Zurück", "automodpack.wait": "Bitte warten..." -} \ No newline at end of file +} From 0fcc519f77b28c0b68cfca818af5a5080223a312 Mon Sep 17 00:00:00 2001 From: Suerion Date: Fri, 20 Dec 2024 22:52:47 +0100 Subject: [PATCH 04/56] Update Modpack updater for new buttons --- .../automodpack_loader_core/client/ModpackUpdater.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index 68246467d..d0332b58e 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -86,6 +86,9 @@ public void prepareUpdate(Jsons.ModpackContentFields modpackContent, String link LOGGER.warn("Modpack update found"); startUpdate(); + startHighUpdate(); + startLowUpdate(); + startServerUpdate(); } catch (Exception e) { LOGGER.error("Error while initializing modpack updater", e); } @@ -146,6 +149,9 @@ public void CheckAndLoadModpack() throws Exception { } // TODO split it into different methods, its too long + public void startHighUpdate() {} + public void startLowUpdate() {} + public void startServerUpdate() {} public void startUpdate() { new ScreenManager().download(downloadManager, getModpackName()); From 74d24179901c785ed34b4f80883310d72647bbf7 Mon Sep 17 00:00:00 2001 From: Suerion Date: Fri, 20 Dec 2024 23:15:25 +0100 Subject: [PATCH 05/56] Update Modpack updater for new buttons --- .../skidam/automodpack_loader_core/client/ModpackUpdater.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index d0332b58e..0b7ee06e0 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -148,9 +148,13 @@ public void CheckAndLoadModpack() throws Exception { LOGGER.info("Modpack is already loaded"); } + // TODO split it into different methods, its too long + // Todo HighUpdate main folder rename in high end folder for Client (complete Folder from Automodpack folders (main)) public void startHighUpdate() {} + // Todo LowUpdate low folder adding and only Download low client folder public void startLowUpdate() {} + // TODO Download all files, also the files whats declared in automodpack-server and server sided files. public void startServerUpdate() {} public void startUpdate() { From 40e36143276bd0609b12fe999404630d480ee275 Mon Sep 17 00:00:00 2001 From: Suerion Date: Fri, 20 Dec 2024 23:51:03 +0100 Subject: [PATCH 06/56] Update Modpack updater for new buttons --- .../java/pl/skidam/automodpack/client/ui/DangerScreen.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java index e2a6eb86c..bd0697f82 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java @@ -37,11 +37,11 @@ protected void init() { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startHighUpdate); })); - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.lowendconfirm").formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 75, 120, 20, VersionedText.translatable("automodpack.danger.lowendconfirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startLowUpdate); })); - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.completeconfirm").formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 90, 120, 20, VersionedText.translatable("automodpack.danger.completeconfirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); })); } From e94bb7431055812a02e452a01de375ab5944cf2f Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 21 Dec 2024 00:05:37 +0100 Subject: [PATCH 07/56] update buttons on danger screen, hope look better now --- .../pl/skidam/automodpack/client/ui/DangerScreen.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java index bd0697f82..d5dc64b5e 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java @@ -33,15 +33,19 @@ protected void init() { this.client.setScreen(parent); })); - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.highendconfirm").formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.confirm").formatted(Formatting.BOLD), button -> { + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + })); + + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 75, 120, 20, VersionedText.translatable("automodpack.danger.highendconfirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startHighUpdate); })); - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 75, 120, 20, VersionedText.translatable("automodpack.danger.lowendconfirm").formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 100, 120, 20, VersionedText.translatable("automodpack.danger.lowendconfirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startLowUpdate); })); - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 90, 120, 20, VersionedText.translatable("automodpack.danger.completeconfirm").formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.danger.completeconfirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); })); } From 4003198b282549d650ccfa554350d14802c8802c Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 21 Dec 2024 23:10:28 +0100 Subject: [PATCH 08/56] update buttons on danger screen, hope look better now --- .../screen/ScreenManager.java | 5 ++ .../skidam/automodpack/client/ScreenImpl.java | 17 +++-- .../client/ui/DownloadSelectionScreen.java | 63 +++++++++++++++++++ .../assets/automodpack/lang/en_us.json | 10 +++ 4 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenManager.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenManager.java index 118ea9a31..06ee32def 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenManager.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenManager.java @@ -31,6 +31,11 @@ public void danger(Object... args) { INSTANCE.danger(args); } + @Override + public void downloadselection(Object... args) { + INSTANCE.downloadselection(args); + } + @Override public void error(String... args) { INSTANCE.error(args); diff --git a/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java b/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java index d0692fe49..29e1475e5 100644 --- a/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java +++ b/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java @@ -18,6 +18,11 @@ public class ScreenImpl implements ScreenService { + @Override + public void downloadselection(Object... args) { + Screens.downloadselection(args[0], args[1]); + } + @Override public void download(Object... args) { Screens.download(args[0], args[1]); @@ -79,6 +84,12 @@ public static void setScreen(Screen screen) { Util.getMainWorkerExecutor().execute(() -> MinecraftClient.getInstance().execute(() -> MinecraftClient.getInstance().setScreen(screen))); } + public static void danger(Object parent, Object modpackUpdaterInstance) { + Screens.setScreen(new DangerScreen((Screen) parent, (ModpackUpdater) modpackUpdaterInstance)); + } + public static void downloadselection(Object parent, Object modpackUpdaterInstance) { + Screens.setScreen(new DownloadSelectionScreen((Screen) parent, (ModpackUpdater) modpackUpdaterInstance)); + } public static void download(Object downloadManager, Object header) { Screens.setScreen(new DownloadScreen((DownloadManager) downloadManager, (String) header)); } @@ -88,15 +99,9 @@ public static void fetch(Object fetchManager) { public static void changelog(Object parent, Object modpackDir, Object changelog) { Screens.setScreen(new ChangelogScreen((Screen) parent, (Path) modpackDir, (Changelogs) changelog)); } - public static void restart(Object modpackDir, Object updateType, Object changelogs) { Screens.setScreen(new RestartScreen((Path) modpackDir, (UpdateType) updateType, (Changelogs) changelogs)); } - - public static void danger(Object parent, Object modpackUpdaterInstance) { - Screens.setScreen(new DangerScreen((Screen) parent, (ModpackUpdater) modpackUpdaterInstance)); - } - public static void error(String... error) { Screens.setScreen(new ErrorScreen(Arrays.toString(error))); } diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java new file mode 100644 index 000000000..c03c92296 --- /dev/null +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -0,0 +1,63 @@ +package pl.skidam.automodpack.client.ui; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.util.Formatting; +import net.minecraft.util.Util; +import pl.skidam.automodpack_loader_core.client.ModpackUpdater; +import pl.skidam.automodpack.client.audio.AudioManager; + +import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; +import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; +import pl.skidam.automodpack.client.ui.versioned.VersionedText; + +public class DownloadSelectionScreen extends VersionedScreen { + private final Screen parent; + private final ModpackUpdater modpackUpdaterInstance; + + public DownloadSelectionScreen(Screen parent, ModpackUpdater modpackUpdaterInstance) { + super(VersionedText.literal("DownloadSelectionScreen")); + this.parent = parent; + this.modpackUpdaterInstance = modpackUpdaterInstance; + + if (AudioManager.isMusicPlaying()) { + AudioManager.stopMusic(); + } + } + @Override + protected void init() { + super.init(); + assert this.client != null; + + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 150, 120, 20, VersionedText.translatable("automodpack.ds.cancel"), button -> { + this.client.setScreen(parent); + })); + + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.ds.standard").formatted(Formatting.BOLD), button -> { + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + })); + + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 75, 120, 20, VersionedText.translatable("automodpack.ds.highendconfirm").formatted(Formatting.BOLD), button -> { + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startHighUpdate); + })); + + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 100, 120, 20, VersionedText.translatable("automodpack.ds.lowendconfirm").formatted(Formatting.BOLD), button -> { + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startLowUpdate); + })); + + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); + })); + } + + @Override + public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { + drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds").formatted(Formatting.BOLD), this.width / 2, this.height / 2 - 60, 16777215); + drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.description"), this.width / 2, this.height / 2 - 35, 16777215); + drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.secDescription"), this.width / 2, this.height / 2 - 25, 16777215); + } + + @Override + public boolean shouldCloseOnEsc() { + return false; + } +} \ No newline at end of file diff --git a/src/main/resources/assets/automodpack/lang/en_us.json b/src/main/resources/assets/automodpack/lang/en_us.json index 0abf0072c..df797f1c3 100644 --- a/src/main/resources/assets/automodpack/lang/en_us.json +++ b/src/main/resources/assets/automodpack/lang/en_us.json @@ -24,6 +24,16 @@ "automodpack.danger.completeconfirm": "Download Full Server Pack", "automodpack.danger.cancel": "Don't download", + "automodpack.ds": "This server provides an external modpack!", + "automodpack.ds.description": "Do you want to download it?", + "automodpack.ds.secDescription": "It might be risky! Do NOT download if don't trust the server owners!", + "automodpack.ds.confirm": "Download", + "automodpack.ds.highendconfirm": "Download for High End PC's", + "automodpack.ds.lowendconfirm": "Download for Low End PC's", + "automodpack.ds.completeconfirm": "Download Full Server Pack", + "automodpack.ds.cancel": "Exit", + + "automodpack.changelog.view": "View changelogs", "automodpack.changelog.noChanges": "No changes found.", "automodpack.changelog.openPage": "Open project page", From 08091bdd47a2cd7f1d768237b9f44655e95583f8 Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 21 Dec 2024 23:13:58 +0100 Subject: [PATCH 09/56] added new screen for Download selection, added english language, changed back danger screen --- .../skidam/automodpack/client/ui/DangerScreen.java | 12 ------------ .../resources/assets/automodpack/lang/en_us.json | 5 +---- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java index d5dc64b5e..cfc204cf9 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java @@ -36,18 +36,6 @@ protected void init() { this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.confirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); - - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 75, 120, 20, VersionedText.translatable("automodpack.danger.highendconfirm").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startHighUpdate); - })); - - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 100, 120, 20, VersionedText.translatable("automodpack.danger.lowendconfirm").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startLowUpdate); - })); - - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.danger.completeconfirm").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); - })); } @Override diff --git a/src/main/resources/assets/automodpack/lang/en_us.json b/src/main/resources/assets/automodpack/lang/en_us.json index df797f1c3..7160cd095 100644 --- a/src/main/resources/assets/automodpack/lang/en_us.json +++ b/src/main/resources/assets/automodpack/lang/en_us.json @@ -18,10 +18,7 @@ "automodpack.danger": "This server provides an external modpack!", "automodpack.danger.description": "Do you want to download it?", "automodpack.danger.secDescription": "It might be risky! Do NOT download if don't trust the server owners!", - "automodpack.danger.confirm": "Download", - "automodpack.danger.highendconfirm": "Download for High End PC's", - "automodpack.danger.lowendconfirm": "Download for Low End PC's", - "automodpack.danger.completeconfirm": "Download Full Server Pack", + "automodpack.danger.confirm": "Download selection", "automodpack.danger.cancel": "Don't download", "automodpack.ds": "This server provides an external modpack!", From 2bed8d28d26f6a82be48e714bda2ef175347954b Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 21 Dec 2024 23:26:53 +0100 Subject: [PATCH 10/56] hopefull added new screen without linking --- .../screen/PreloadScreenImpl.java | 3 +++ .../automodpack_loader_core/screen/ScreenManager.java | 10 ++++------ .../automodpack_loader_core/screen/ScreenService.java | 1 + 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/PreloadScreenImpl.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/PreloadScreenImpl.java index 2991114b3..a0204e439 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/PreloadScreenImpl.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/PreloadScreenImpl.java @@ -5,6 +5,9 @@ public class PreloadScreenImpl implements ScreenService { // We leave this all empty + @Override + public void downloadselection(Object... args) { } + @Override public void download(Object... args) { } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenManager.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenManager.java index 06ee32def..233004501 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenManager.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenManager.java @@ -6,6 +6,10 @@ public class ScreenManager implements ScreenService { public static ScreenService INSTANCE = new PreloadScreenImpl(); + @Override + public void downloadselection(Object... args) { + INSTANCE.downloadselection(args); + } @Override public void download(Object... args) { INSTANCE.download(args); @@ -30,12 +34,6 @@ public void restart(Object... args) { public void danger(Object... args) { INSTANCE.danger(args); } - - @Override - public void downloadselection(Object... args) { - INSTANCE.downloadselection(args); - } - @Override public void error(String... args) { INSTANCE.error(args); diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenService.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenService.java index ee2079068..bab8e6da9 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenService.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/screen/ScreenService.java @@ -4,6 +4,7 @@ public interface ScreenService { + void downloadselection(Object... args); void download(Object... args); void fetch(Object... args); void changelog(Object... args); From a219ae5c2aad3f97080f70dc8785a5575ad8df71 Mon Sep 17 00:00:00 2001 From: Suerion Date: Sun, 22 Dec 2024 14:04:33 +0100 Subject: [PATCH 11/56] added selectionManager file for selection screen, need toDo. changed danger screen if selection manager has more folders found --- .../client/ModpackUpdater.java | 4 ++- .../utils/SelectionManager.java | 27 +++++++++++++++++++ .../automodpack/client/ui/DangerScreen.java | 13 ++++++++- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index 0b7ee06e0..7fee6b76a 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -21,6 +21,7 @@ public class ModpackUpdater { public Changelogs changelogs = new Changelogs(); + public SelectionManager selectionManager; public DownloadManager downloadManager; public FetchManager fetchManager; public long totalBytesToDownload = 0; @@ -35,11 +36,12 @@ public class ModpackUpdater { private Path modpackDir; private Path modpackContentFile; - public String getModpackName() { return serverModpackContent.modpackName; } + public void prepareSelection() {} + public void prepareUpdate(Jsons.ModpackContentFields modpackContent, String link, Path modpackPath) { serverModpackContent = modpackContent; modpackLink = link; diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java new file mode 100644 index 000000000..5691c0737 --- /dev/null +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java @@ -0,0 +1,27 @@ +package pl.skidam.automodpack_loader_core.utils; + +import pl.skidam.automodpack_core.utils.CustomFileUtils; +import pl.skidam.automodpack_core.utils.CustomThreadFactoryBuilder; + +import java.io.*; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Instant; +import java.util.*; +import java.util.concurrent.*; +import java.util.zip.GZIPInputStream; + +import static pl.skidam.automodpack_core.GlobalVariables.AM_VERSION; +import static pl.skidam.automodpack_core.GlobalVariables.LOGGER; + +public class SelectionManager { + public SelectionManager() { + } + + // TODO + + +} \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java index cfc204cf9..b1e1bbc1f 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java @@ -13,11 +13,13 @@ public class DangerScreen extends VersionedScreen { private final Screen parent; private final ModpackUpdater modpackUpdaterInstance; + private final SelectionManager selectionManagerInstance; - public DangerScreen(Screen parent, ModpackUpdater modpackUpdaterInstance) { + public DangerScreen(Screen parent, ModpackUpdater modpackUpdaterInstance, SelectionManager selectionManagerInstance) { super(VersionedText.literal("DangerScreen")); this.parent = parent; this.modpackUpdaterInstance = modpackUpdaterInstance; + this.selectionManagerInstance = selectionManagerInstance; if (AudioManager.isMusicPlaying()) { AudioManager.stopMusic(); @@ -33,9 +35,18 @@ protected void init() { this.client.setScreen(parent); })); + if (selectionManagerInstance != null) { + + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.selection").formatted(Formatting.BOLD), button -> { + Util.getMainWorkerExecutor().execute(selectionManagerInstance::startSelection); + })); + + } else { + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.confirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); + } } @Override From 30f5de551ed9345827c30f5af77b421e72775cb6 Mon Sep 17 00:00:00 2001 From: skidam Date: Sun, 22 Dec 2024 15:29:30 +0100 Subject: [PATCH 12/56] fix build --- .../client/ModpackUpdater.java | 2 +- .../pl/skidam/automodpack/client/ScreenImpl.java | 7 ++++--- .../automodpack/client/ui/DangerScreen.java | 16 +++++++--------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index 7fee6b76a..112bc187a 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -82,7 +82,7 @@ public void prepareUpdate(Jsons.ModpackContentFields modpackContent, String link } } else if (!preload) { fullDownload = true; - new ScreenManager().danger(new ScreenManager().getScreen().orElseThrow(), this); + new ScreenManager().danger(new ScreenManager().getScreen().orElseThrow(), this, null); return; } diff --git a/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java b/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java index 29e1475e5..342f3da52 100644 --- a/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java +++ b/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java @@ -10,6 +10,7 @@ import pl.skidam.automodpack_loader_core.screen.ScreenService; import pl.skidam.automodpack_loader_core.utils.DownloadManager; import pl.skidam.automodpack_loader_core.utils.FetchManager; +import pl.skidam.automodpack_loader_core.utils.SelectionManager; import pl.skidam.automodpack_loader_core.utils.UpdateType; import java.nio.file.Path; @@ -45,7 +46,7 @@ public void restart(Object... args) { @Override public void danger(Object... args) { - Screens.danger(args[0], args[1]); + Screens.danger(args[0], args[1], args[2]); } @Override @@ -84,8 +85,8 @@ public static void setScreen(Screen screen) { Util.getMainWorkerExecutor().execute(() -> MinecraftClient.getInstance().execute(() -> MinecraftClient.getInstance().setScreen(screen))); } - public static void danger(Object parent, Object modpackUpdaterInstance) { - Screens.setScreen(new DangerScreen((Screen) parent, (ModpackUpdater) modpackUpdaterInstance)); + public static void danger(Object parent, Object modpackUpdaterInstance, Object selectionManagerInstance) { + Screens.setScreen(new DangerScreen((Screen) parent, (ModpackUpdater) modpackUpdaterInstance, (SelectionManager) selectionManagerInstance)); } public static void downloadselection(Object parent, Object modpackUpdaterInstance) { Screens.setScreen(new DownloadSelectionScreen((Screen) parent, (ModpackUpdater) modpackUpdaterInstance)); diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java index b1e1bbc1f..40b210b42 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java @@ -9,6 +9,7 @@ import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; import pl.skidam.automodpack.client.ui.versioned.VersionedText; +import pl.skidam.automodpack_loader_core.utils.SelectionManager; public class DangerScreen extends VersionedScreen { private final Screen parent; @@ -36,16 +37,13 @@ protected void init() { })); if (selectionManagerInstance != null) { - - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.selection").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(selectionManagerInstance::startSelection); - })); - + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.selection").formatted(Formatting.BOLD), button -> { + this.client.setScreen(new DownloadSelectionScreen(parent, modpackUpdaterInstance)); + })); } else { - - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.confirm").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); - })); + this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.confirm").formatted(Formatting.BOLD), button -> { + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + })); } } From ba027f90526539f7d545a3a753b0aae42f1bba55 Mon Sep 17 00:00:00 2001 From: Suerion Date: Mon, 23 Dec 2024 23:07:12 +0100 Subject: [PATCH 13/56] updated english and german language file, next is Selection manager and checking all files for all files and folder creation with config comparing --- .../resources/assets/automodpack/lang/de_de.json | 13 ++++++++++--- .../resources/assets/automodpack/lang/en_us.json | 13 +++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main/resources/assets/automodpack/lang/de_de.json b/src/main/resources/assets/automodpack/lang/de_de.json index b7b07fcc7..52d2c12ae 100644 --- a/src/main/resources/assets/automodpack/lang/de_de.json +++ b/src/main/resources/assets/automodpack/lang/de_de.json @@ -1,6 +1,8 @@ { "automodpack.restart.full": "Das Modpack wurde heruntergeladen!", "automodpack.restart.update": "Es wurde ein Update für das Modpack heruntergeladen!", + "automodpack.restart.select": "Modpack required by server got selected!", + "automodpack.restart.automodpack": "Updated version of AutoModpack mod to the one required by server!", "automodpack.restart.description": "Um den Vorgang abzuschließen, musst du das Spiel neu starten.", "automodpack.restart.secDescription": "Möchtest du jetzt neu starten?", "automodpack.restart.confirm": "Ja, Spiel schließen", @@ -16,14 +18,19 @@ "automodpack.danger": "Dieser Server bietet ein externes Modpack an!", "automodpack.danger.description": "Möchtest du es herunterladen?", "automodpack.danger.secDescription": "Es könnte riskant sein! Lade es NICHT herunter, wenn du den Server-Betreibern nicht vertraust!", + "automodpack.danger.selection": "Version wählen", "automodpack.danger.confirm": "Herunterladen", - "automodpack.danger.highendconfirm": "Lade das Pack für High End PC's", - "automodpack.danger.lowendconfirm": "Lade das Pack für High End PC's", - "automodpack.danger.completeconfirm": "Lade das komplette Server Pack", "automodpack.danger.cancel": "Nicht herunterladen", + "automodpack.ds": "Dieser Server stellt verschiedene Versionen bereit!", + "automodpack.ds.description": "Du kannst für dich die benötigte Version auswählen. Welche benötigst du?", + "automodpack.ds.secDescription": "Verschiedenen Versionen benötigen andere PC Systeme!", + "automodpack.ds.confirm": "Download", + "automodpack.ds.cancel": "Abbrechen", + "automodpack.changelog.view": "Änderungen anzeigen", "automodpack.changelog.noChanges": "Keine Änderungen gefunden.", + "automodpack.changelog.openPage": "Open project page", "automodpack.download.calculating": "Berechnung läuft...", "automodpack.download.eta": "Verbleibende Zeit: %s", diff --git a/src/main/resources/assets/automodpack/lang/en_us.json b/src/main/resources/assets/automodpack/lang/en_us.json index 7160cd095..f5cf7a6e7 100644 --- a/src/main/resources/assets/automodpack/lang/en_us.json +++ b/src/main/resources/assets/automodpack/lang/en_us.json @@ -18,19 +18,16 @@ "automodpack.danger": "This server provides an external modpack!", "automodpack.danger.description": "Do you want to download it?", "automodpack.danger.secDescription": "It might be risky! Do NOT download if don't trust the server owners!", - "automodpack.danger.confirm": "Download selection", + "automodpack.danger.selection": "Chose Version", + "automodpack.danger.confirm": "Download", "automodpack.danger.cancel": "Don't download", - "automodpack.ds": "This server provides an external modpack!", - "automodpack.ds.description": "Do you want to download it?", - "automodpack.ds.secDescription": "It might be risky! Do NOT download if don't trust the server owners!", + "automodpack.ds": "The Server Admin provides different versions!", + "automodpack.ds.description": "You could chose, what version do you need? Chose the right one for you!", + "automodpack.ds.secDescription": "The difference of the versions are dependent on your PC System!", "automodpack.ds.confirm": "Download", - "automodpack.ds.highendconfirm": "Download for High End PC's", - "automodpack.ds.lowendconfirm": "Download for Low End PC's", - "automodpack.ds.completeconfirm": "Download Full Server Pack", "automodpack.ds.cancel": "Exit", - "automodpack.changelog.view": "View changelogs", "automodpack.changelog.noChanges": "No changes found.", "automodpack.changelog.openPage": "Open project page", From db9e255661ddcd6059c3e651360db1f07e60e390 Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 15 Mar 2025 17:33:04 +0100 Subject: [PATCH 14/56] trying to update the restart button --- .../skidam/automodpack/client/ui/RestartScreen.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java index a569654ef..d4e4216cb 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java @@ -32,6 +32,10 @@ public RestartScreen(Path modpackDir, UpdateType updateType, Changelogs changelo } } + private static void onPress(ButtonWidget button) { + System.exit(0); + } + @Override protected void init() { super.init(); @@ -42,6 +46,7 @@ protected void init() { this.addDrawableChild(restartButton); this.addDrawableChild(changelogsButton); + if (changelogs == null || changelogs.changesAddedList.isEmpty() && changelogs.changesDeletedList.isEmpty()) { changelogsButton.active = false; } @@ -53,14 +58,14 @@ public void initWidgets() { this.client.setScreen(null); }); - restartButton = buttonWidget(this.width / 2 + 5, this.height / 2 + 50, 150, 20, VersionedText.translatable("automodpack.restart.confirm").formatted(Formatting.BOLD), button -> { - System.exit(0); - }); + restartButton = buttonWidget(this.width / 2 + 5, this.height / 2 + 50, 150, 20, VersionedText.translatable("automodpack.restart.confirm").formatted(Formatting.BOLD), RestartScreen::onPress); changelogsButton = buttonWidget(this.width / 2 - 75, this.height / 2 + 75, 150, 20, VersionedText.translatable("automodpack.changelog.view"), button -> { new ScreenManager().changelog(this, modpackDir, changelogs); }); } + + @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { From d47157efe950077769b52f05a3a8c969ef4660fb Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 15 Mar 2025 19:07:33 +0100 Subject: [PATCH 15/56] Revert "trying to update the restart button" This reverts commit db9e255661ddcd6059c3e651360db1f07e60e390. --- .../skidam/automodpack/client/ui/RestartScreen.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java index d4e4216cb..a569654ef 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java @@ -32,10 +32,6 @@ public RestartScreen(Path modpackDir, UpdateType updateType, Changelogs changelo } } - private static void onPress(ButtonWidget button) { - System.exit(0); - } - @Override protected void init() { super.init(); @@ -46,7 +42,6 @@ protected void init() { this.addDrawableChild(restartButton); this.addDrawableChild(changelogsButton); - if (changelogs == null || changelogs.changesAddedList.isEmpty() && changelogs.changesDeletedList.isEmpty()) { changelogsButton.active = false; } @@ -58,14 +53,14 @@ public void initWidgets() { this.client.setScreen(null); }); - restartButton = buttonWidget(this.width / 2 + 5, this.height / 2 + 50, 150, 20, VersionedText.translatable("automodpack.restart.confirm").formatted(Formatting.BOLD), RestartScreen::onPress); + restartButton = buttonWidget(this.width / 2 + 5, this.height / 2 + 50, 150, 20, VersionedText.translatable("automodpack.restart.confirm").formatted(Formatting.BOLD), button -> { + System.exit(0); + }); changelogsButton = buttonWidget(this.width / 2 - 75, this.height / 2 + 75, 150, 20, VersionedText.translatable("automodpack.changelog.view"), button -> { new ScreenManager().changelog(this, modpackDir, changelogs); }); } - - @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { From 086247e48c71bd67859a9bd953d0a160ee9168dc Mon Sep 17 00:00:00 2001 From: Suerion Date: Thu, 20 Mar 2025 23:16:25 +0100 Subject: [PATCH 16/56] Changed SelectionManger to get folders from server, added dynamical buttons and changed the modpack updater to get the right folder... hope i had nothing forget yet --- .../client/ModpackUpdater.java | 6 +++- .../utils/SelectionManager.java | 32 +++++++++++++++++-- .../client/ui/DownloadSelectionScreen.java | 24 ++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index 01113f830..f0a31016f 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -152,7 +152,7 @@ public void CheckAndLoadModpack() throws Exception { LOGGER.info("Modpack is already loaded"); } - + /* Delete soon this one // TODO split it into different methods, its too long // Todo HighUpdate main folder rename in high end folder for Client (complete Folder from Automodpack folders (main)) public void startHighUpdate() {} @@ -160,7 +160,11 @@ public void startHighUpdate() {} public void startLowUpdate() {} // TODO Download all files, also the files whats declared in automodpack-server and server sided files. public void startServerUpdate() {} + */ public void startUpdate() { + //checkout for selected modpack + String checkoutpack = SelectionManager.getSelectedPack(); + File modpackFolder = new File(FabricLoader.getInstance().getGameDir().toFile(), "automodpack/host-modpack/" + checkoutpack); if (modpackSecret == null) { LOGGER.error("Cannot update modpack, secret is null"); diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java index 5691c0737..12a1cdc50 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java @@ -14,14 +14,42 @@ import java.util.concurrent.*; import java.util.zip.GZIPInputStream; +import net.fabricmc.loader.api.FabricLoader; + import static pl.skidam.automodpack_core.GlobalVariables.AM_VERSION; import static pl.skidam.automodpack_core.GlobalVariables.LOGGER; public class SelectionManager { - public SelectionManager() { + + //select folders from host-modpack for difference client packs + public static List getModpackFolders() { + List modpacks = new ArrayList<>(); + + File modpackfolders = new File(FabricLoader.getInstance().getGameDir().toFile(), "automodpack/host-modpack/"); + File[] folders = modpackfolders.listFiles(File::isDirectory); + + if (folders != null) { + for (File dir : folders) { + if (!dir.getName().equalsIgnoreCase("main")) { // "main" überspringen + modpacks.add(dir.getName()); + } + } + } + return modpacks; } - // TODO + //give only main Pack + private static String selectedPack ="main"; + //give modpack from selected modpack and save to config + public static void setSelectedPack(String modpack) { + selectedPack = modpack; + //TO DO Adding in Config... but how xD + } + + //fetch modpack from config + public static String getSelectedPack() { + return selectedPack; + } } \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index c03c92296..2d47e788a 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -1,6 +1,7 @@ package pl.skidam.automodpack.client.ui; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Util; import pl.skidam.automodpack_loader_core.client.ModpackUpdater; @@ -9,6 +10,7 @@ import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; import pl.skidam.automodpack.client.ui.versioned.VersionedText; +import pl.skidam.automodpack_loader_core.utils.SelectionManager; public class DownloadSelectionScreen extends VersionedScreen { private final Screen parent; @@ -32,6 +34,27 @@ protected void init() { this.client.setScreen(parent); })); + //buttons from Selectionmanager + + List modpacks = SelectionManager.getModpackFolders(); + + //dynamisch wieviele buttons vorhanden sind + int dynamicY = this.height / 2 - (modpacks.size() * 15); + int i=0; + + for (String modpack : modpacks) { + // abstand einfügen + int y = dynamicY + (i * 25); + + this.addDrawableChild(buttonWidget(this.width / 2, y, 140, 20, Text.literal(modpack).formatted(Formatting.BOLD), button -> { + //Auswählen und dann starten + SelectionManager.setSelectedPack(modpack); + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate()); + })); + i++; + } + + /* Old Buttons this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.ds.standard").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); @@ -47,6 +70,7 @@ protected void init() { this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); })); + */ } @Override From e959520c436c9f1206743ef6829853a7681a9161 Mon Sep 17 00:00:00 2001 From: Suerion Date: Mon, 24 Mar 2025 21:50:58 +0100 Subject: [PATCH 17/56] changed config tools, and jsons to exclude files with IP or BOT tokkens, added in download selections screen the full server button, added in jsons a helper method to exclude added utils for paths, modpackfolder, and clientpackage --- .../automodpack_core/config/ConfigTools.java | 31 ++++++++ .../skidam/automodpack_core/config/Jsons.java | 6 +- .../client/ModpackUpdater.java | 73 ++++++++++++++++++- .../client/ModpackUtils.java | 13 ++++ .../utils/SelectionManager.java | 4 +- .../client/ui/DownloadSelectionScreen.java | 10 ++- 6 files changed, 129 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java b/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java index 580b13de4..f04ca2cc4 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java @@ -4,11 +4,21 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonSyntaxException; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonParser; +import java.io.Reader; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; + import static pl.skidam.automodpack_core.GlobalVariables.*; public class ConfigTools { @@ -63,6 +73,7 @@ public static T load(Path configFile, Class configClass) { } } + public static T load(String json, Class configClass) { try { if (json != null) { @@ -119,4 +130,24 @@ public static void saveModpackContent(Path modpackContentFile, Jsons.ModpackCont e.printStackTrace(); } } + + public static Set loadFullServerPackExclude(Path serverConfigPath) { + Set excludedFiles = new HashSet<>(); + + if (!Files.exists(serverConfigPath)) return excludedFiles; + + try (Reader reader = Files.newBufferedReader(serverConfigPath)) { + JsonObject json = JsonParser.parseReader(reader).getAsJsonObject(); + JsonArray excluded = json.getAsJsonArray("ServerPackExcluded"); + if (excluded != null) { + for (JsonElement e : excluded) { + excludedFiles.add(e.getAsString()); + } + } + } catch (IOException | JsonParseException e) { + LOGGER.error("Error in automodpack-server.json with FullServerPack exclude", e); + } + + return excludedFiles; + } } diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java index 9d18aeb44..a4f6311c8 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java @@ -3,10 +3,7 @@ import pl.skidam.automodpack_core.auth.Secrets; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class Jsons { @@ -24,6 +21,7 @@ public static class ServerConfigFields { public boolean generateModpackOnStart = true; public List syncedFiles = List.of("/mods/*.jar", "!/mods/iDontWantThisModInModpack.jar", "!/config/andThisConfigToo.json", "!/mods/andAllTheseMods-*.jar", "!/mods/server-*.jar"); public List allowEditsInFiles = List.of("/options.txt", "/config/*", "!/config/excludeThisFile"); + public List ServerPackExcluded = List.of("!/config/bottokens.toml", "!/config/ipadresses.json"); public boolean autoExcludeUnnecessaryFiles = true; // public List forceLoad = List.of("/resourcepacks/someResourcePack.zip", "/shaderpacks/someShaderPack.zip"); // public List> forceLoad = new ArrayList<>(); diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index f0a31016f..55282a825 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -39,7 +39,12 @@ public class ModpackUpdater { private Path modpackDir; private Path modpackContentFile; + //if name is null... i hope it is right public String getModpackName() { + if (serverModpackContent == null) { + LOGGER.warn("name was initialized before server modpack content."); + return "unknown Modpack"; + } return serverModpackContent.modpackName; } @@ -95,9 +100,12 @@ public void prepareUpdate(Jsons.ModpackContentFields modpackContent, InetSocketA LOGGER.warn("Modpack update found"); startUpdate(); + /* should be cleaned after update startHighUpdate(); startLowUpdate(); startServerUpdate(); + + */ } catch (Exception e) { LOGGER.error("Error while initializing modpack updater", e); } @@ -164,7 +172,70 @@ public void startServerUpdate() {} public void startUpdate() { //checkout for selected modpack String checkoutpack = SelectionManager.getSelectedPack(); - File modpackFolder = new File(FabricLoader.getInstance().getGameDir().toFile(), "automodpack/host-modpack/" + checkoutpack); + + //should be path one or two? bruhhh, not know yet, trying both + Path modpackFolder = ModpackUtils.getModpackPathFolder(checkoutpack); + Path modpackPathFolder = ModpackUtils.getModpackPathFolder(SelectionManager.getSelectedPack()); + + if ("fullserver".equalsIgnoreCase(checkoutpack)) { + + // Sammle Pfade aus den Standardordnern + List includeDirs = List.of( + ModpackUtils.getMinecraftPath().resolve("mods"), + ModpackUtils.getMinecraftPath().resolve("config"), + ModpackUtils.getMinecraftPath().resolve("resourcepacks"), + ModpackUtils.getMinecraftPath().resolve("shaderpacks") + ); + + LOGGER.info("Full pack selected. Lade alle Dateien aus Standardordnern + wende ServerPackExcluded an"); + + // Pfad zur Server-Konfig + Path automodpackserverConfig = ModpackUtils.getMinecraftPath().resolve("mods/automodpack/automodpack-server.json"); + + // Lade Exclude-Liste aus JSON + Set excludedFiles = ConfigTools.loadFullServerPackExclude(automodpackserverConfig); + + // Liste, in die alle gültigen Dateien aufgenommen werden + List filesToInclude = new ArrayList<>(); + + // Durchlaufe alle Standardverzeichnisse + for (Path dir : includeDirs) { + if (!Files.exists(dir)) continue; + + try (Stream files = Files.walk(dir)) { + files.filter(Files::isRegularFile).forEach(path -> { + // Rechne relativen Pfad + String relative = ModpackUtils.getMinecraftPath().relativize(path).toString().replace("\\", "/"); + String formatted = "/" + relative; + + // Prüfe, ob excluded + boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { + if (rule.startsWith("!")) rule = rule.substring(1); + return rule.equalsIgnoreCase(formatted); + }); + + if (isExcluded) { + LOGGER.info("files excluded: {}", formatted); + return; + } + + LOGGER.info("files included: {}", formatted); + filesToInclude.add(path); + }); + } catch (IOException e) { + LOGGER.error("error on folder search {}", dir, e); + } + } + + // automodpack server config import + if (Files.exists(automodpackserverConfig)) { + LOGGER.info("automodpack server config import: {}", automodpackserverConfig); + filesToInclude.add(automodpackserverConfig); + } + + return; + } + if (modpackSecret == null) { LOGGER.error("Cannot update modpack, secret is null"); diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java index bb8eeabb3..240215a6e 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java @@ -294,6 +294,19 @@ public static Path renameModpackDir(Jsons.ModpackContentFields serverModpackCont return modpackDir; } + //get minecraft path.... + public static Path getMinecraftPath() { + return Path.of(System.getProperty("user.dir")); + } + + //try to get modpacks about minecraft path for utils + public static Path getModpackPathFolder(String modpackpackage) { + return getMinecraftPath().resolve("automodpack/host-modpack/").resolve(modpackpackage); + } + // get all client Packages and paths from host-modpack util test + public static Path getClientPackage() { + return getMinecraftPath().resolve("automodpack/host-modpack"); + } // Returns true if value changed public static boolean selectModpack(Path modpackDirToSelect, InetSocketAddress modpackAddressToSelect, Set newDownloadedFiles) { diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java index 12a1cdc50..6841fdd94 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java @@ -1,5 +1,6 @@ package pl.skidam.automodpack_loader_core.utils; +import pl.skidam.automodpack_loader_core.client.ModpackUtils; import pl.skidam.automodpack_core.utils.CustomFileUtils; import pl.skidam.automodpack_core.utils.CustomThreadFactoryBuilder; @@ -14,7 +15,6 @@ import java.util.concurrent.*; import java.util.zip.GZIPInputStream; -import net.fabricmc.loader.api.FabricLoader; import static pl.skidam.automodpack_core.GlobalVariables.AM_VERSION; import static pl.skidam.automodpack_core.GlobalVariables.LOGGER; @@ -25,7 +25,7 @@ public class SelectionManager { public static List getModpackFolders() { List modpacks = new ArrayList<>(); - File modpackfolders = new File(FabricLoader.getInstance().getGameDir().toFile(), "automodpack/host-modpack/"); + File modpackfolders = ModpackUtils.getClientPackage().toFile(); File[] folders = modpackfolders.listFiles(File::isDirectory); if (folders != null) { diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index 2d47e788a..30608e832 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -1,5 +1,7 @@ package pl.skidam.automodpack.client.ui; +import java.util.List; + import net.minecraft.client.gui.screen.Screen; import net.minecraft.text.Text; import net.minecraft.util.Formatting; @@ -49,11 +51,17 @@ protected void init() { this.addDrawableChild(buttonWidget(this.width / 2, y, 140, 20, Text.literal(modpack).formatted(Formatting.BOLD), button -> { //Auswählen und dann starten SelectionManager.setSelectedPack(modpack); - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate()); + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); i++; } + //Full Serverpack Button + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, Text.literal("Full Server Pack").formatted(Formatting.RED), button -> { + SelectionManager.setSelectedPack("fullserver"); + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + })); + /* Old Buttons this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.ds.standard").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); From 16819aa838120e1a04a3eb9935a5e52f17037db7 Mon Sep 17 00:00:00 2001 From: Suerion Date: Mon, 24 Mar 2025 22:58:02 +0100 Subject: [PATCH 18/56] create helper content build for full server and create on update excluding and default folders looked on other content file should create automodpack/host-modpack/fullserver/fullserverpack-content.json --- .../client/ModpackUpdater.java | 27 ++++++++--- .../client/ModpackUtils.java | 45 +++++++++++++++++++ 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index 55282a825..fc075c2d2 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -179,7 +179,7 @@ public void startUpdate() { if ("fullserver".equalsIgnoreCase(checkoutpack)) { - // Sammle Pfade aus den Standardordnern + // look for paths on default folders List includeDirs = List.of( ModpackUtils.getMinecraftPath().resolve("mods"), ModpackUtils.getMinecraftPath().resolve("config"), @@ -189,26 +189,26 @@ public void startUpdate() { LOGGER.info("Full pack selected. Lade alle Dateien aus Standardordnern + wende ServerPackExcluded an"); - // Pfad zur Server-Konfig + // path to automodpack config Path automodpackserverConfig = ModpackUtils.getMinecraftPath().resolve("mods/automodpack/automodpack-server.json"); - // Lade Exclude-Liste aus JSON + // load exclude files from config tools Set excludedFiles = ConfigTools.loadFullServerPackExclude(automodpackserverConfig); - // Liste, in die alle gültigen Dateien aufgenommen werden + // list all files to include List filesToInclude = new ArrayList<>(); - // Durchlaufe alle Standardverzeichnisse + // search default folders for (Path dir : includeDirs) { if (!Files.exists(dir)) continue; try (Stream files = Files.walk(dir)) { files.filter(Files::isRegularFile).forEach(path -> { - // Rechne relativen Pfad + // path for windows and linux String relative = ModpackUtils.getMinecraftPath().relativize(path).toString().replace("\\", "/"); String formatted = "/" + relative; - // Prüfe, ob excluded + // check if excluded boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { if (rule.startsWith("!")) rule = rule.substring(1); return rule.equalsIgnoreCase(formatted); @@ -233,6 +233,19 @@ public void startUpdate() { filesToInclude.add(automodpackserverConfig); } + try { + Jsons.ModpackContentFields fullServerContent = ModpackUtils.buildFullServerPackContent(filesToInclude); + + Path outputPath = ModpackUtils.getMinecraftPath() + .resolve("automodpack/host-modpack/fullserver/fullserverpack-content.json"); + + ConfigTools.saveModpackContent(outputPath, fullServerContent); + + LOGGER.info("servermodpack content file saved under: {}", outputPath); + } catch (Exception e) { + LOGGER.error("error on creation from fullserverpack-content-content.json", e); + } + return; } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java index 240215a6e..cd72d1da2 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java @@ -509,4 +509,49 @@ static Set getEditableFiles(Set filesToInclude) { + Jsons.ModpackContentFields content = new Jsons.ModpackContentFields(); + content.modpackName = "FullServerPack"; + content.list = new HashSet<>(); + + for (Path file : filesToInclude) { + try { + Jsons.ModpackContentFields.ModpackContentItem item = new Jsons.ModpackContentFields.ModpackContentItem(); + + // path for linux or windows + String formattedPath = "/" + ModpackUtils.getMinecraftPath().relativize(file).toString().replace("\\", "/"); + item.file = formattedPath; + + // hash for files like content + item.sha1 = CustomFileUtils.getHash(file); + + // file + item.size = String.valueOf(Files.size(file)); + + // Editable = false (später optional über JSON steuerbar) + item.editable = false; + + // Typ bestimmen + if (formattedPath.startsWith("/mods/")) { + item.type = "mod"; + } else if (formattedPath.startsWith("/shaderpacks/")) { + item.type = "shader"; + } else if (formattedPath.startsWith("/resourcepacks/")) { + item.type = "resourcepack"; + } else if (formattedPath.startsWith("/config/")) { + item.type = "config"; + } else { + item.type = "file"; + } + + content.list.add(item); + } catch (IOException e) { + LOGGER.error("there is an error on the full server content: {}", file, e); + } + } + + return content; + } } From d3955e9fbc3033285ad683c9632f1419395330f0 Mon Sep 17 00:00:00 2001 From: Suerion Date: Mon, 24 Mar 2025 23:38:06 +0100 Subject: [PATCH 19/56] should fixed murmur check --- .../client/ModpackUtils.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java index cd72d1da2..d5ee8cc53 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java @@ -18,6 +18,7 @@ import static pl.skidam.automodpack_core.GlobalVariables.*; + public class ModpackUtils { public static boolean isUpdate(Jsons.ModpackContentFields serverModpackContent, Path modpackDir) { @@ -518,33 +519,32 @@ public static Jsons.ModpackContentFields buildFullServerPackContent(List f for (Path file : filesToInclude) { try { - Jsons.ModpackContentFields.ModpackContentItem item = new Jsons.ModpackContentFields.ModpackContentItem(); + + String sha1 = CustomFileUtils.getHash(file); + String murmur = CustomFileUtils.getCurseforgeMurmurHash(file); + String size = String.valueOf(Files.size(file)); // path for linux or windows String formattedPath = "/" + ModpackUtils.getMinecraftPath().relativize(file).toString().replace("\\", "/"); - item.file = formattedPath; - - // hash for files like content - item.sha1 = CustomFileUtils.getHash(file); - - // file - item.size = String.valueOf(Files.size(file)); - - // Editable = false (später optional über JSON steuerbar) - item.editable = false; - // Typ bestimmen + // what type is folder + String type; if (formattedPath.startsWith("/mods/")) { - item.type = "mod"; + type = "mod"; } else if (formattedPath.startsWith("/shaderpacks/")) { - item.type = "shader"; + type = "shader"; } else if (formattedPath.startsWith("/resourcepacks/")) { - item.type = "resourcepack"; + type = "resourcepack"; } else if (formattedPath.startsWith("/config/")) { - item.type = "config"; + type = "config"; } else { - item.type = "file"; + type = "file"; } + // filling with content + Jsons.ModpackContentFields.ModpackContentItem item = + new Jsons.ModpackContentFields.ModpackContentItem( + formattedPath, sha1, murmur, false, size, type + ); content.list.add(item); } catch (IOException e) { From 93eb022a85586dee6ee7fff3fc2eeefd4724c2f9 Mon Sep 17 00:00:00 2001 From: suerion <55131959+suerion@users.noreply.github.com> Date: Mon, 24 Mar 2025 23:56:48 +0100 Subject: [PATCH 20/56] fixed error on screen impl deleted fu** } xD --- src/main/java/pl/skidam/automodpack/client/ScreenImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java b/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java index 48f5bd1f3..d6b42f980 100644 --- a/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java +++ b/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java @@ -82,7 +82,6 @@ private static Screen getScreen() { public static void setScreen(Screen screen) { // required for forge to handle it properly Util.getMainWorkerExecutor().execute(() -> MinecraftClient.getInstance().execute(() -> MinecraftClient.getInstance().setScreen(screen))); - } } public static void downloadselection(Object parent, Object modpackUpdaterInstance) { From 229ca1a2c238ed05204a55648e5f59d254944ecb Mon Sep 17 00:00:00 2001 From: Suerion Date: Tue, 25 Mar 2025 00:11:19 +0100 Subject: [PATCH 21/56] updated button to different versions --- .../skidam/automodpack/client/ui/DownloadSelectionScreen.java | 4 ++-- src/main/resources/assets/automodpack/lang/de_de.json | 1 + src/main/resources/assets/automodpack/lang/en_us.json | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index 30608e832..b6db043a5 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -48,7 +48,7 @@ protected void init() { // abstand einfügen int y = dynamicY + (i * 25); - this.addDrawableChild(buttonWidget(this.width / 2, y, 140, 20, Text.literal(modpack).formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidget(this.width / 2, y, 140, 20, VersionedText.literal(modpack).formatted(Formatting.BOLD), button -> { //Auswählen und dann starten SelectionManager.setSelectedPack(modpack); Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); @@ -57,7 +57,7 @@ protected void init() { } //Full Serverpack Button - this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, Text.literal("Full Server Pack").formatted(Formatting.RED), button -> { + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, VersionedText.translatable("automodpack.ds.fullserverpack").formatted(Formatting.RED), button -> { SelectionManager.setSelectedPack("fullserver"); Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); diff --git a/src/main/resources/assets/automodpack/lang/de_de.json b/src/main/resources/assets/automodpack/lang/de_de.json index 52d2c12ae..d8d5be27d 100644 --- a/src/main/resources/assets/automodpack/lang/de_de.json +++ b/src/main/resources/assets/automodpack/lang/de_de.json @@ -25,6 +25,7 @@ "automodpack.ds": "Dieser Server stellt verschiedene Versionen bereit!", "automodpack.ds.description": "Du kannst für dich die benötigte Version auswählen. Welche benötigst du?", "automodpack.ds.secDescription": "Verschiedenen Versionen benötigen andere PC Systeme!", + "automodpack.ds.fullserverpack": "Server Package", "automodpack.ds.confirm": "Download", "automodpack.ds.cancel": "Abbrechen", diff --git a/src/main/resources/assets/automodpack/lang/en_us.json b/src/main/resources/assets/automodpack/lang/en_us.json index f5cf7a6e7..2790ec10d 100644 --- a/src/main/resources/assets/automodpack/lang/en_us.json +++ b/src/main/resources/assets/automodpack/lang/en_us.json @@ -25,6 +25,7 @@ "automodpack.ds": "The Server Admin provides different versions!", "automodpack.ds.description": "You could chose, what version do you need? Chose the right one for you!", "automodpack.ds.secDescription": "The difference of the versions are dependent on your PC System!", + "automodpack.ds.fullserverpack": "Full Server Pack", "automodpack.ds.confirm": "Download", "automodpack.ds.cancel": "Exit", From 53e857f7b5b22f9f5e8d9f9b2d5e74462827fe42 Mon Sep 17 00:00:00 2001 From: Suerion Date: Tue, 25 Mar 2025 22:31:27 +0100 Subject: [PATCH 22/56] added full server pack button, and added an config line if server pack should be generated, new server pack content file created, only importings added, will next create the file, then sync --- .../skidam/automodpack_core/config/Jsons.java | 1 + .../modpack/FullServerPackContent.java | 20 +++++++++++++++++++ .../client/ModpackUpdater.java | 18 ++++++++++++++++- .../automodpack/client/ui/DangerScreen.java | 17 ++++++++++++++++ .../assets/automodpack/lang/de_de.json | 1 + .../assets/automodpack/lang/en_us.json | 1 + 6 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java index a4f6311c8..574034231 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java @@ -21,6 +21,7 @@ public static class ServerConfigFields { public boolean generateModpackOnStart = true; public List syncedFiles = List.of("/mods/*.jar", "!/mods/iDontWantThisModInModpack.jar", "!/config/andThisConfigToo.json", "!/mods/andAllTheseMods-*.jar", "!/mods/server-*.jar"); public List allowEditsInFiles = List.of("/options.txt", "/config/*", "!/config/excludeThisFile"); + public boolean enableFullServerPack = false; public List ServerPackExcluded = List.of("!/config/bottokens.toml", "!/config/ipadresses.json"); public boolean autoExcludeUnnecessaryFiles = true; // public List forceLoad = List.of("/resourcepacks/someResourcePack.zip", "/shaderpacks/someShaderPack.zip"); diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java new file mode 100644 index 000000000..ea9b12d93 --- /dev/null +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -0,0 +1,20 @@ +package pl.skidam.automodpack_core.modpack; + +import pl.skidam.automodpack_core.config.ConfigTools; +import pl.skidam.automodpack_core.config.Jsons; +import pl.skidam.automodpack_core.utils.CustomFileUtils; +import pl.skidam.automodpack_core.utils.ModpackContentTools; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; + +import static pl.skidam.automodpack_core.GlobalVariables.*; +import static pl.skidam.automodpack_core.GlobalVariables.LOGGER; + +public class FullServerPackContent { + + + + +} diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index fc075c2d2..3b5a46402 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -170,6 +170,22 @@ public void startLowUpdate() {} public void startServerUpdate() {} */ public void startUpdate() { + Path automodpackserverConfig = ModpackUtils.getMinecraftPath().resolve("mods/automodpack/automodpack-server.json"); + //if file is deleted from user, stop + if (!Files.exists(automodpackserverConfig)) { + LOGGER.info("automodpack-server.json is missing? did you delete the file?"); + return; + } + + //load config + Jsons.ServerConfigFields serverConfig = ConfigTools.load(automodpackserverConfig, Jsons.ServerConfigFields.class); + + //if config null or false, stop + if (serverConfig == null || !serverConfig.enableFullServerPack) { + LOGGER.info("Fullserverack creation on default disabled."); + return; + } + //checkout for selected modpack String checkoutpack = SelectionManager.getSelectedPack(); @@ -190,7 +206,7 @@ public void startUpdate() { LOGGER.info("Full pack selected. Lade alle Dateien aus Standardordnern + wende ServerPackExcluded an"); // path to automodpack config - Path automodpackserverConfig = ModpackUtils.getMinecraftPath().resolve("mods/automodpack/automodpack-server.json"); + automodpackserverConfig = ModpackUtils.getMinecraftPath().resolve("mods/automodpack/automodpack-server.json"); // load exclude files from config tools Set excludedFiles = ConfigTools.loadFullServerPackExclude(automodpackserverConfig); diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java index 40b210b42..6495ec7b0 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java @@ -5,10 +5,16 @@ import net.minecraft.util.Util; import pl.skidam.automodpack_loader_core.client.ModpackUpdater; import pl.skidam.automodpack.client.audio.AudioManager; +import java.nio.file.Files; +import java.nio.file.Path; +import pl.skidam.automodpack_core.config.ConfigTools; +import pl.skidam.automodpack_core.config.Jsons; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; import pl.skidam.automodpack.client.ui.versioned.VersionedText; +import pl.skidam.automodpack_loader_core.client.ModpackUtils; + import pl.skidam.automodpack_loader_core.utils.SelectionManager; public class DangerScreen extends VersionedScreen { @@ -45,6 +51,17 @@ protected void init() { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); } + Path serverConfigPath = ModpackUtils.getMinecraftPath().resolve("mods/automodpack/automodpack-server.json"); + if (Files.exists(serverConfigPath)) { + Jsons.ServerConfigFields serverConfig = ConfigTools.load(serverConfigPath, Jsons.ServerConfigFields.class); + + if (serverConfig != null && serverConfig.enableFullServerPack) { + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 100, 160, 20, VersionedText.literal("automodpack.danger.fullserverpack").formatted(Formatting.RED), button -> { + SelectionManager.setSelectedPack("fullserver"); + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + })); + } + } } @Override diff --git a/src/main/resources/assets/automodpack/lang/de_de.json b/src/main/resources/assets/automodpack/lang/de_de.json index d8d5be27d..74b2ebfb5 100644 --- a/src/main/resources/assets/automodpack/lang/de_de.json +++ b/src/main/resources/assets/automodpack/lang/de_de.json @@ -19,6 +19,7 @@ "automodpack.danger.description": "Möchtest du es herunterladen?", "automodpack.danger.secDescription": "Es könnte riskant sein! Lade es NICHT herunter, wenn du den Server-Betreibern nicht vertraust!", "automodpack.danger.selection": "Version wählen", + "automodpack.danger.fullserverpack": "Server Package", "automodpack.danger.confirm": "Herunterladen", "automodpack.danger.cancel": "Nicht herunterladen", diff --git a/src/main/resources/assets/automodpack/lang/en_us.json b/src/main/resources/assets/automodpack/lang/en_us.json index 2790ec10d..6fe94eb7a 100644 --- a/src/main/resources/assets/automodpack/lang/en_us.json +++ b/src/main/resources/assets/automodpack/lang/en_us.json @@ -19,6 +19,7 @@ "automodpack.danger.description": "Do you want to download it?", "automodpack.danger.secDescription": "It might be risky! Do NOT download if don't trust the server owners!", "automodpack.danger.selection": "Chose Version", + "automodpack.danger.fullserverpack": "Full Server Pack", "automodpack.danger.confirm": "Download", "automodpack.danger.cancel": "Don't download", From aeff7a16c64ef6b42fbc0ab1be0fc22f32aeb5a6 Mon Sep 17 00:00:00 2001 From: Suerion Date: Wed, 26 Mar 2025 21:25:24 +0100 Subject: [PATCH 23/56] created FullServerPackContent.java and deleted all content file creation form ModpackUpdater because client side and server side need to be cuted in config tools we added SaveFullServerPackContent to check if there is an error on creating added in ModpackContenttools the file content murmur and so on are not added yet... added in jsons the contentfileitems like ModpackContentFields not finished yet... need to be searching for sha and fileextensions --- .../automodpack_core/config/ConfigTools.java | 13 +++ .../skidam/automodpack_core/config/Jsons.java | 32 ++++++ .../modpack/FullServerPackContent.java | 101 +++++++++++++++++- .../utils/ModpackContentTools.java | 31 ++++++ .../client/ModpackUpdater.java | 88 --------------- 5 files changed, 173 insertions(+), 92 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java b/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java index f04ca2cc4..86d8a91b0 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java @@ -131,6 +131,19 @@ public static void saveModpackContent(Path modpackContentFile, Jsons.ModpackCont } } + public static void saveFullServerPackContent(Path modpackContentFile, Jsons.FullServerPackContentFields configObject) { + try { + if (!Files.isDirectory(modpackContentFile.getParent())) { + Files.createDirectories(modpackContentFile.getParent()); + } + + Files.writeString(modpackContentFile, GSON.toJson(configObject), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + } catch (Exception e) { + LOGGER.error("Couldn't save full server pack content! " + configObject.getClass()); + e.printStackTrace(); + } + } + public static Set loadFullServerPackExclude(Path serverConfigPath) { Set excludedFiles = new HashSet<>(); diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java index 574034231..8c1a78f06 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java @@ -102,4 +102,36 @@ public String toString() { } } } + public static class FullServerPackContentFields { + public Set list; + + public FullServerPackContentFields(Set list) { + this.list = list; + } + + public FullServerPackContentFields() { + this.list = Set.of(); + } + + public static class FullServerPackContentItem { + public String file; + public String size; + public String type; + public String sha1; + public String murmur; + + public FullServerPackContentItem(String file, String size, String type, String sha1, String murmur) { + this.file = file; + this.size = size; + this.type = type; + this.sha1 = sha1; + this.murmur = murmur; + } + + @Override + public String toString() { + return String.format("FullServerPackContentItem(file=%s, size=%s, type=%s, sha1=%s, murmur=%s)", file, size, type, sha1, murmur); + } + } + } } diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index ea9b12d93..46e253764 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -1,20 +1,113 @@ package pl.skidam.automodpack_core.modpack; -import pl.skidam.automodpack_core.config.ConfigTools; -import pl.skidam.automodpack_core.config.Jsons; +import pl.skidam.automodpack_core.config.*; import pl.skidam.automodpack_core.utils.CustomFileUtils; import pl.skidam.automodpack_core.utils.ModpackContentTools; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; +import java.util.stream.Stream; -import static pl.skidam.automodpack_core.GlobalVariables.*; import static pl.skidam.automodpack_core.GlobalVariables.LOGGER; public class FullServerPackContent { + public static void generate() { + LOGGER.info("start generating server pack content file"); + Path automodpackserverConfig = CustomFileUtils.getPathFromCWD("mods/automodpack/automodpack-server.json"); -} + //if file is deleted from user, stop + if (!Files.exists(automodpackserverConfig)) { + LOGGER.info("automodpack-server.json is missing? did you delete the file?"); + return; + } + + //load config + Jsons.ServerConfigFields serverConfig = ConfigTools.load(automodpackserverConfig, Jsons.ServerConfigFields.class); + //if config null or false, stop + if (serverConfig == null || !serverConfig.enableFullServerPack) { + LOGGER.info("Fullserverpack creation on default disabled."); + return; + } + Set excludedFiles = ConfigTools.loadFullServerPackExclude(automodpackserverConfig); + List filesToInclude = new ArrayList<>(); + + //check synced files + List syncedFilePaths = serverConfig.syncedFiles != null ? serverConfig.syncedFiles : new ArrayList<>(); + + for (String relativePath : syncedFilePaths) { + Path path = CustomFileUtils.getPathFromCWD(relativePath); + if (!Files.exists(path) || Files.isDirectory(path)) continue; + String formatted = "/" + relativePath.replace("\\", "/"); + + boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { + if (rule.startsWith("!")) rule = rule.substring(1); + return rule.equalsIgnoreCase(formatted); + }); + + if (isExcluded) { + LOGGER.info("excluded from syncedFiles: {}", formatted); + continue; + } + + LOGGER.info("included from syncedFiles: {}", formatted); + filesToInclude.add(path); + } + + // look for paths on default folders + List includeDefaultDirs = List.of( + CustomFileUtils.getPathFromCWD("mods"), + CustomFileUtils.getPathFromCWD("config"), + CustomFileUtils.getPathFromCWD("resourcepacks"), + CustomFileUtils.getPathFromCWD("shaderpacks") + //adding library or other folders like kubejs? + ); + //Check default folders if not in synced files declared + for (Path dir : includeDefaultDirs) { + if (!Files.exists(dir)) continue; + + try (Stream files = Files.walk(dir)) { + files.filter(Files::isRegularFile).forEach(path -> { + // check if already included + if (filesToInclude.contains(path)) return; + + String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); + String formatted = "/" + relative; + + boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { + if (rule.startsWith("!")) rule = rule.substring(1); + return rule.equalsIgnoreCase(formatted); + }); + + if (isExcluded) { + LOGGER.info("excluded from defaultDir: {}", formatted); + return; + } + LOGGER.info("included from defaultDir: {}", formatted); + filesToInclude.add(path); + }); + } catch (Exception e) { + LOGGER.error("Error while walking through folder: {}", dir, e); + } + } + // automodpack server config import + if (Files.exists(automodpackserverConfig)) { + LOGGER.info("automodpack server config import: {}", automodpackserverConfig); + filesToInclude.add(automodpackserverConfig); + } + + try { + Jsons.FullServerPackContentFields fullServerContent = ModpackContentTools.buildFullServerPackContent(filesToInclude); + + Path outputPath = CustomFileUtils.getPathFromCWD("mods/automodpack-host/fullserverpack-content.json"); + ConfigTools.saveFullServerPackContent(outputPath, fullServerContent); + + LOGGER.info("servermodpack content file saved under: {}", outputPath); + } catch (Exception e) { + LOGGER.error("error on creation from fullserverpack-content.json", e); + } + } +} \ No newline at end of file diff --git a/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java b/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java index bd24f32bc..c02f7b637 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java +++ b/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java @@ -5,10 +5,39 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Optional; +import java.util.List; +import java.util.Set; +import java.util.HashSet; import static pl.skidam.automodpack_core.GlobalVariables.*; public class ModpackContentTools { + //create Fullserverpack content with files + public static Jsons.FullServerPackContentFields buildFullServerPackContent(List files) { + Set contentList = new HashSet<>(); + + for (Path path : files) { + try { + String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); + String file = "/" + relative; + String size = String.valueOf(Files.size(path)); + String type = getFileExtension(path); + String sha1 = CustomFileUtils.sha1(path); + String murmur = ""; + + var item = new Jsons.FullServerPackContentFields.FullServerPackContentItem( + file, size, type, sha1, murmur + ); + + contentList.add(item); + } catch (Exception e) { + LOGGER.warn("Could not process file for FullServerPackContent: {}", path, e); + } + } + + return new Jsons.FullServerPackContentFields(contentList); + } + public static String getFileType(String file, Jsons.ModpackContentFields list) { for (Jsons.ModpackContentFields.ModpackContentItem item : list.list) { if (item.file.contains(file)) { // compare file absolute path if it contains item.file @@ -43,4 +72,6 @@ public static Optional getModpackContentFile(Path modpackDir) { return Optional.of(path); } + + } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index 3b5a46402..05acd4192 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -170,100 +170,12 @@ public void startLowUpdate() {} public void startServerUpdate() {} */ public void startUpdate() { - Path automodpackserverConfig = ModpackUtils.getMinecraftPath().resolve("mods/automodpack/automodpack-server.json"); - //if file is deleted from user, stop - if (!Files.exists(automodpackserverConfig)) { - LOGGER.info("automodpack-server.json is missing? did you delete the file?"); - return; - } - - //load config - Jsons.ServerConfigFields serverConfig = ConfigTools.load(automodpackserverConfig, Jsons.ServerConfigFields.class); - - //if config null or false, stop - if (serverConfig == null || !serverConfig.enableFullServerPack) { - LOGGER.info("Fullserverack creation on default disabled."); - return; - } - - //checkout for selected modpack String checkoutpack = SelectionManager.getSelectedPack(); //should be path one or two? bruhhh, not know yet, trying both Path modpackFolder = ModpackUtils.getModpackPathFolder(checkoutpack); Path modpackPathFolder = ModpackUtils.getModpackPathFolder(SelectionManager.getSelectedPack()); - if ("fullserver".equalsIgnoreCase(checkoutpack)) { - - // look for paths on default folders - List includeDirs = List.of( - ModpackUtils.getMinecraftPath().resolve("mods"), - ModpackUtils.getMinecraftPath().resolve("config"), - ModpackUtils.getMinecraftPath().resolve("resourcepacks"), - ModpackUtils.getMinecraftPath().resolve("shaderpacks") - ); - - LOGGER.info("Full pack selected. Lade alle Dateien aus Standardordnern + wende ServerPackExcluded an"); - - // path to automodpack config - automodpackserverConfig = ModpackUtils.getMinecraftPath().resolve("mods/automodpack/automodpack-server.json"); - - // load exclude files from config tools - Set excludedFiles = ConfigTools.loadFullServerPackExclude(automodpackserverConfig); - - // list all files to include - List filesToInclude = new ArrayList<>(); - - // search default folders - for (Path dir : includeDirs) { - if (!Files.exists(dir)) continue; - - try (Stream files = Files.walk(dir)) { - files.filter(Files::isRegularFile).forEach(path -> { - // path for windows and linux - String relative = ModpackUtils.getMinecraftPath().relativize(path).toString().replace("\\", "/"); - String formatted = "/" + relative; - - // check if excluded - boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { - if (rule.startsWith("!")) rule = rule.substring(1); - return rule.equalsIgnoreCase(formatted); - }); - - if (isExcluded) { - LOGGER.info("files excluded: {}", formatted); - return; - } - - LOGGER.info("files included: {}", formatted); - filesToInclude.add(path); - }); - } catch (IOException e) { - LOGGER.error("error on folder search {}", dir, e); - } - } - - // automodpack server config import - if (Files.exists(automodpackserverConfig)) { - LOGGER.info("automodpack server config import: {}", automodpackserverConfig); - filesToInclude.add(automodpackserverConfig); - } - - try { - Jsons.ModpackContentFields fullServerContent = ModpackUtils.buildFullServerPackContent(filesToInclude); - - Path outputPath = ModpackUtils.getMinecraftPath() - .resolve("automodpack/host-modpack/fullserver/fullserverpack-content.json"); - - ConfigTools.saveModpackContent(outputPath, fullServerContent); - - LOGGER.info("servermodpack content file saved under: {}", outputPath); - } catch (Exception e) { - LOGGER.error("error on creation from fullserverpack-content-content.json", e); - } - - return; - } if (modpackSecret == null) { From 8b7f0557a7922cec1db26885038ac012672db1c0 Mon Sep 17 00:00:00 2001 From: Suerion Date: Wed, 26 Mar 2025 22:30:47 +0100 Subject: [PATCH 24/56] changed deleted in ModpackContentTools the build from full server content and added it directly in FullServerPackContent --- .../modpack/FullServerPackContent.java | 121 +++++++++++++++--- .../utils/ModpackContentTools.java | 28 ---- 2 files changed, 104 insertions(+), 45 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index 46e253764..c848ab0db 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -2,19 +2,83 @@ import pl.skidam.automodpack_core.config.*; import pl.skidam.automodpack_core.utils.CustomFileUtils; -import pl.skidam.automodpack_core.utils.ModpackContentTools; +import pl.skidam.automodpack_core.utils.FileInspection; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; import java.util.stream.Stream; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; -import static pl.skidam.automodpack_core.GlobalVariables.LOGGER; +import static pl.skidam.automodpack_core.GlobalVariables.*; public class FullServerPackContent { - public static void generate() { + public static Jsons.FullServerPackContentFields buildFullServerPackContent(List files) { + Set contentList = Collections.synchronizedSet(new HashSet<>()); + ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(4); + List> futures = new ArrayList<>(); + for (int i = 0; i < files.size(); i += 6) { + List subList = files.subList(i, Math.min(files.size(), i + 6)); + futures.add(CompletableFuture.runAsync(() -> subList.forEach(file -> generate(file, contentList)), executor)); + } + + futures.forEach(CompletableFuture::join); + executor.shutdown(); + + return new Jsons.FullServerPackContentFields(contentList); + } + + private static void generate(Path file, Set contentList) { + try { + if (!Files.isRegularFile(file)) return; + + String formattedFile = CustomFileUtils.formatPath(file, CustomFileUtils.getPathFromCWD("")); + if (formattedFile.startsWith("/automodpack/")) return; + + String size = String.valueOf(Files.size(file)); + + //exclude invalid files + if (size.equals("0") || file.getFileName().toString().startsWith(".") || formattedFile.endsWith(".tmp") || formattedFile.endsWith(".bak") || formattedFile.endsWith(".disabled")) { + LOGGER.info("Skipping file {}, because they are invalid and not needed in fullserverModpack Content", formattedFile); + return; + } + + String type; + if (FileInspection.isMod(file)) { + type = "mod"; + if ((MOD_ID + "-bootstrap").equals(FileInspection.getModID(file))) { + return; + } + } else if (formattedFile.contains("/config/")) { + type = "config"; + } else if (formattedFile.contains("/shaderpacks/")) { + type = "shader"; + } else if (formattedFile.contains("/resourcepacks/")) { + type = "resourcepack"; + } else if (formattedFile.endsWith("/options.txt")) { + type = "mc_options"; + } else { + type = "other"; + } + + String sha1 = CustomFileUtils.getHash(file); + String murmur = null; + if (type.equals("mod") || type.equals("shader") || type.equals("resourcepack")) { + murmur = CustomFileUtils.getCurseforgeMurmurHash(file); + } + + var item = new Jsons.FullServerPackContentFields.FullServerPackContentItem("/" + formattedFile, size, type, sha1, murmur); + contentList.add(item); + + } catch (Exception e) { + LOGGER.warn("Could not add file for FullServerPackContent: {}", file, e); + } + } + public static void generateFromServerConfig() { LOGGER.info("start generating server pack content file"); Path automodpackserverConfig = CustomFileUtils.getPathFromCWD("mods/automodpack/automodpack-server.json"); @@ -71,21 +135,21 @@ public static void generate() { try (Stream files = Files.walk(dir)) { files.filter(Files::isRegularFile).forEach(path -> { - // check if already included - if (filesToInclude.contains(path)) return; + // check if already included + if (filesToInclude.contains(path)) return; - String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); - String formatted = "/" + relative; + String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); + String formatted = "/" + relative; - boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { - if (rule.startsWith("!")) rule = rule.substring(1); - return rule.equalsIgnoreCase(formatted); - }); + boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { + if (rule.startsWith("!")) rule = rule.substring(1); + return rule.equalsIgnoreCase(formatted); + }); - if (isExcluded) { - LOGGER.info("excluded from defaultDir: {}", formatted); - return; - } + if (isExcluded) { + LOGGER.info("excluded from defaultDir: {}", formatted); + return; + } LOGGER.info("included from defaultDir: {}", formatted); filesToInclude.add(path); }); @@ -99,8 +163,30 @@ public static void generate() { filesToInclude.add(automodpackserverConfig); } + // adding client mod folders from automodpack host + Path automodpackHostDir = CustomFileUtils.getPathFromCWD("mods/automodpack-host"); + if (Files.exists(automodpackHostDir) && Files.isDirectory(automodpackHostDir)) { + try (Stream files = Files.walk(automodpackHostDir)) { + files.filter(Files::isRegularFile).forEach(path -> { + String fileName = path.getFileName().toString().toLowerCase(); + if (fileName.equals("fullserverpack-content.json") || fileName.equals("automodpack-content.json")) { + LOGGER.info("skipped content files from automodpack-host: {}", fileName); + return; + } + + String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); + String formatted = "/" + relative; + + LOGGER.info("included from automodpack-host: {}", formatted); + filesToInclude.add(path); + }); + } catch (Exception e) { + LOGGER.error("Error while walking through automodpack-host folder: {}", automodpackHostDir, e); + } + } + try { - Jsons.FullServerPackContentFields fullServerContent = ModpackContentTools.buildFullServerPackContent(filesToInclude); + Jsons.FullServerPackContentFields fullServerContent = FullServerPackContent.buildFullServerPackContent(filesToInclude); Path outputPath = CustomFileUtils.getPathFromCWD("mods/automodpack-host/fullserverpack-content.json"); ConfigTools.saveFullServerPackContent(outputPath, fullServerContent); @@ -110,4 +196,5 @@ public static void generate() { LOGGER.error("error on creation from fullserverpack-content.json", e); } } -} \ No newline at end of file + +} diff --git a/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java b/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java index c02f7b637..a3b3665d4 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java +++ b/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java @@ -5,38 +5,10 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Optional; -import java.util.List; -import java.util.Set; -import java.util.HashSet; import static pl.skidam.automodpack_core.GlobalVariables.*; public class ModpackContentTools { - //create Fullserverpack content with files - public static Jsons.FullServerPackContentFields buildFullServerPackContent(List files) { - Set contentList = new HashSet<>(); - - for (Path path : files) { - try { - String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); - String file = "/" + relative; - String size = String.valueOf(Files.size(path)); - String type = getFileExtension(path); - String sha1 = CustomFileUtils.sha1(path); - String murmur = ""; - - var item = new Jsons.FullServerPackContentFields.FullServerPackContentItem( - file, size, type, sha1, murmur - ); - - contentList.add(item); - } catch (Exception e) { - LOGGER.warn("Could not process file for FullServerPackContent: {}", path, e); - } - } - - return new Jsons.FullServerPackContentFields(contentList); - } public static String getFileType(String file, Jsons.ModpackContentFields list) { for (Jsons.ModpackContentFields.ModpackContentItem item : list.list) { From 27d00918464e7a39ef8f413c1c50c3e49f90f22c Mon Sep 17 00:00:00 2001 From: Suerion Date: Wed, 26 Mar 2025 23:02:34 +0100 Subject: [PATCH 25/56] add Fullserverpackcontent generation on modpack generation, --- core/src/main/java/pl/skidam/automodpack_core/Server.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index 7b6e1707b..f82e2f35e 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -4,6 +4,7 @@ import pl.skidam.automodpack_core.config.Jsons; import pl.skidam.automodpack_core.modpack.Modpack; import pl.skidam.automodpack_core.modpack.ModpackContent; +import pl.skidam.automodpack_core.modpack.FullServerPackContent; import pl.skidam.automodpack_core.protocol.netty.NettyServer; import java.nio.file.Path; @@ -62,10 +63,11 @@ public static void main(String[] args) { Modpack modpack = new Modpack(); ModpackContent modpackContent = new ModpackContent(serverConfig.modpackName, null, mainModpackDir, serverConfig.syncedFiles, serverConfig.allowEditsInFiles, modpack.CREATION_EXECUTOR); - boolean generated = modpack.generateNew(modpackContent); + boolean modpackgenerated = modpack.generateNew(modpackContent); - if (generated) { + if (modpackgenerated) { LOGGER.info("Modpack generated!"); + FullServerPackContent.generateFromServerConfig(); } else { LOGGER.error("Failed to generate modpack!"); } From 1ae3eb05d4c371e1a533ce9b0cc38c3fdaf93b94 Mon Sep 17 00:00:00 2001 From: Suerion Date: Wed, 26 Mar 2025 23:25:08 +0100 Subject: [PATCH 26/56] correcting path to servermodpack config --- .../automodpack_core/modpack/FullServerPackContent.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index c848ab0db..e4935dac5 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -81,7 +81,7 @@ private static void generate(Path file, Set files = Files.walk(automodpackHostDir)) { files.filter(Files::isRegularFile).forEach(path -> { @@ -188,7 +188,7 @@ public static void generateFromServerConfig() { try { Jsons.FullServerPackContentFields fullServerContent = FullServerPackContent.buildFullServerPackContent(filesToInclude); - Path outputPath = CustomFileUtils.getPathFromCWD("mods/automodpack-host/fullserverpack-content.json"); + Path outputPath = CustomFileUtils.getPathFromCWD("automodpack/automodpack-host/fullserverpack-content.json"); ConfigTools.saveFullServerPackContent(outputPath, fullServerContent); LOGGER.info("servermodpack content file saved under: {}", outputPath); From 1eea4f78f9ee26ddc3160e584bf3f77b73b08761 Mon Sep 17 00:00:00 2001 From: Suerion Date: Wed, 26 Mar 2025 23:52:42 +0100 Subject: [PATCH 27/56] add debbuging log --- .../pl/skidam/automodpack_core/Server.java | 2 + .../modpack/FullServerPackContent.java | 199 +++++++++--------- 2 files changed, 103 insertions(+), 98 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index f82e2f35e..9ab9fa682 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -67,7 +67,9 @@ public static void main(String[] args) { if (modpackgenerated) { LOGGER.info("Modpack generated!"); + LOGGER.info("start generateFromServerConfig()..."); FullServerPackContent.generateFromServerConfig(); + LOGGER.info("log generateFromServerConfig() finished"); } else { LOGGER.error("Failed to generate modpack!"); } diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index e4935dac5..089e52f01 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -79,121 +79,124 @@ private static void generate(Path file, Set excludedFiles = ConfigTools.loadFullServerPackExclude(automodpackserverConfig); + List filesToInclude = new ArrayList<>(); - //load config - Jsons.ServerConfigFields serverConfig = ConfigTools.load(automodpackserverConfig, Jsons.ServerConfigFields.class); - //if config null or false, stop - if (serverConfig == null || !serverConfig.enableFullServerPack) { - LOGGER.info("Fullserverpack creation on default disabled."); - return; - } - Set excludedFiles = ConfigTools.loadFullServerPackExclude(automodpackserverConfig); - List filesToInclude = new ArrayList<>(); + //check synced files + List syncedFilePaths = serverConfig.syncedFiles != null ? serverConfig.syncedFiles : new ArrayList<>(); - //check synced files - List syncedFilePaths = serverConfig.syncedFiles != null ? serverConfig.syncedFiles : new ArrayList<>(); + for (String relativePath : syncedFilePaths) { + Path path = CustomFileUtils.getPathFromCWD(relativePath); + if (!Files.exists(path) || Files.isDirectory(path)) continue; + String formatted = "/" + relativePath.replace("\\", "/"); - for (String relativePath : syncedFilePaths) { - Path path = CustomFileUtils.getPathFromCWD(relativePath); - if (!Files.exists(path) || Files.isDirectory(path)) continue; - String formatted = "/" + relativePath.replace("\\", "/"); + boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { + if (rule.startsWith("!")) rule = rule.substring(1); + return rule.equalsIgnoreCase(formatted); + }); - boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { - if (rule.startsWith("!")) rule = rule.substring(1); - return rule.equalsIgnoreCase(formatted); - }); + if (isExcluded) { + LOGGER.info("excluded from syncedFiles: {}", formatted); + continue; + } - if (isExcluded) { - LOGGER.info("excluded from syncedFiles: {}", formatted); - continue; + LOGGER.info("included from syncedFiles: {}", formatted); + filesToInclude.add(path); } - LOGGER.info("included from syncedFiles: {}", formatted); - filesToInclude.add(path); - } - - // look for paths on default folders - List includeDefaultDirs = List.of( - CustomFileUtils.getPathFromCWD("mods"), - CustomFileUtils.getPathFromCWD("config"), - CustomFileUtils.getPathFromCWD("resourcepacks"), - CustomFileUtils.getPathFromCWD("shaderpacks") - //adding library or other folders like kubejs? - ); - //Check default folders if not in synced files declared - for (Path dir : includeDefaultDirs) { - if (!Files.exists(dir)) continue; - - try (Stream files = Files.walk(dir)) { - files.filter(Files::isRegularFile).forEach(path -> { - // check if already included - if (filesToInclude.contains(path)) return; - - String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); - String formatted = "/" + relative; - - boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { - if (rule.startsWith("!")) rule = rule.substring(1); - return rule.equalsIgnoreCase(formatted); + // look for paths on default folders + List includeDefaultDirs = List.of( + CustomFileUtils.getPathFromCWD("mods"), + CustomFileUtils.getPathFromCWD("config"), + CustomFileUtils.getPathFromCWD("resourcepacks"), + CustomFileUtils.getPathFromCWD("shaderpacks") + //adding library or other folders like kubejs? + ); + //Check default folders if not in synced files declared + for (Path dir : includeDefaultDirs) { + if (!Files.exists(dir)) continue; + + try (Stream files = Files.walk(dir)) { + files.filter(Files::isRegularFile).forEach(path -> { + // check if already included + if (filesToInclude.contains(path)) return; + + String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); + String formatted = "/" + relative; + + boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { + if (rule.startsWith("!")) rule = rule.substring(1); + return rule.equalsIgnoreCase(formatted); + }); + + if (isExcluded) { + LOGGER.info("excluded from defaultDir: {}", formatted); + return; + } + LOGGER.info("included from defaultDir: {}", formatted); + filesToInclude.add(path); }); - - if (isExcluded) { - LOGGER.info("excluded from defaultDir: {}", formatted); - return; - } - LOGGER.info("included from defaultDir: {}", formatted); - filesToInclude.add(path); - }); - } catch (Exception e) { - LOGGER.error("Error while walking through folder: {}", dir, e); + } catch (Exception e) { + LOGGER.error("Error while walking through folder: {}", dir, e); + } + } + // automodpack server config import + if (Files.exists(automodpackserverConfig)) { + LOGGER.info("automodpack server config import: {}", automodpackserverConfig); + filesToInclude.add(automodpackserverConfig); } - } - // automodpack server config import - if (Files.exists(automodpackserverConfig)) { - LOGGER.info("automodpack server config import: {}", automodpackserverConfig); - filesToInclude.add(automodpackserverConfig); - } - // adding client mod folders from automodpack host - Path automodpackHostDir = CustomFileUtils.getPathFromCWD("automodpack/automodpack-host"); - if (Files.exists(automodpackHostDir) && Files.isDirectory(automodpackHostDir)) { - try (Stream files = Files.walk(automodpackHostDir)) { - files.filter(Files::isRegularFile).forEach(path -> { - String fileName = path.getFileName().toString().toLowerCase(); - if (fileName.equals("fullserverpack-content.json") || fileName.equals("automodpack-content.json")) { - LOGGER.info("skipped content files from automodpack-host: {}", fileName); - return; - } - - String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); - String formatted = "/" + relative; - - LOGGER.info("included from automodpack-host: {}", formatted); - filesToInclude.add(path); - }); - } catch (Exception e) { - LOGGER.error("Error while walking through automodpack-host folder: {}", automodpackHostDir, e); + // adding client mod folders from automodpack host + Path automodpackHostDir = CustomFileUtils.getPathFromCWD("automodpack/automodpack-host"); + if (Files.exists(automodpackHostDir) && Files.isDirectory(automodpackHostDir)) { + try (Stream files = Files.walk(automodpackHostDir)) { + files.filter(Files::isRegularFile).forEach(path -> { + String fileName = path.getFileName().toString().toLowerCase(); + if (fileName.equals("fullserverpack-content.json") || fileName.equals("automodpack-content.json")) { + LOGGER.info("skipped content files from automodpack-host: {}", fileName); + return; + } + + String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); + String formatted = "/" + relative; + + LOGGER.info("included from automodpack-host: {}", formatted); + filesToInclude.add(path); + }); + } catch (Exception e) { + LOGGER.error("Error while walking through automodpack-host folder: {}", automodpackHostDir, e); + } } - } - try { - Jsons.FullServerPackContentFields fullServerContent = FullServerPackContent.buildFullServerPackContent(filesToInclude); + try { + Jsons.FullServerPackContentFields fullServerContent = FullServerPackContent.buildFullServerPackContent(filesToInclude); - Path outputPath = CustomFileUtils.getPathFromCWD("automodpack/automodpack-host/fullserverpack-content.json"); - ConfigTools.saveFullServerPackContent(outputPath, fullServerContent); + Path outputPath = CustomFileUtils.getPathFromCWD("automodpack/automodpack-host/fullserverpack-content.json"); + ConfigTools.saveFullServerPackContent(outputPath, fullServerContent); - LOGGER.info("servermodpack content file saved under: {}", outputPath); - } catch (Exception e) { + LOGGER.info("servermodpack content file saved under: {}", outputPath); + } catch (Exception e) { LOGGER.error("error on creation from fullserverpack-content.json", e); + } + } catch (Exception e) { + LOGGER.error("ERROR ON CREATION?", e); } } From f97e338cbe99c968946be704dc46771f4c253c9c Mon Sep 17 00:00:00 2001 From: Suerion Date: Fri, 28 Mar 2025 18:59:17 +0100 Subject: [PATCH 28/56] changed the FullServerPack creation in the new FullServerPack.java file with FullServerPackContent.java generating is now implemented like Modpack.java and ModpackContent.java should generating the FullServerPack in the right folders if config is enabled. also looked on all folders a lots of logging to test it right --- .../pl/skidam/automodpack_core/Server.java | 19 +- .../modpack/FullServerPack.java | 65 +++++++ .../modpack/FullServerPackContent.java | 178 +++++++++++++++--- 3 files changed, 229 insertions(+), 33 deletions(-) create mode 100644 core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index 9ab9fa682..33e920da4 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -2,6 +2,7 @@ import pl.skidam.automodpack_core.config.ConfigTools; import pl.skidam.automodpack_core.config.Jsons; +import pl.skidam.automodpack_core.modpack.FullServerPack; import pl.skidam.automodpack_core.modpack.Modpack; import pl.skidam.automodpack_core.modpack.ModpackContent; import pl.skidam.automodpack_core.modpack.FullServerPackContent; @@ -63,19 +64,25 @@ public static void main(String[] args) { Modpack modpack = new Modpack(); ModpackContent modpackContent = new ModpackContent(serverConfig.modpackName, null, mainModpackDir, serverConfig.syncedFiles, serverConfig.allowEditsInFiles, modpack.CREATION_EXECUTOR); - boolean modpackgenerated = modpack.generateNew(modpackContent); + boolean generated = modpack.generateNew(modpackContent); - if (modpackgenerated) { + if (generated) { LOGGER.info("Modpack generated!"); - LOGGER.info("start generateFromServerConfig()..."); - FullServerPackContent.generateFromServerConfig(); - LOGGER.info("log generateFromServerConfig() finished"); } else { LOGGER.error("Failed to generate modpack!"); } + FullServerPack fullserverpack = new FullServerPack(); + FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, mainModpackDir, fullserverpack.CREATION_EXECUTOR); + boolean fullpackgenerated = fullserverpack.generateNew(fullServerPackContent); - modpack.CREATION_EXECUTOR.shutdownNow(); + if (fullpackgenerated) { + LOGGER.info("FullServerPack generated!"); + } else { + LOGGER.error("Failed to generate serverpack!"); + } + modpack.shutdownExecutor(); + fullserverpack.shutdownExecutor(); LOGGER.info("Starting server on port {}", serverConfig.hostPort); server.start(); // wait for server to stop diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java new file mode 100644 index 000000000..aa5157048 --- /dev/null +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java @@ -0,0 +1,65 @@ +package pl.skidam.automodpack_core.modpack; + +import pl.skidam.automodpack_core.utils.CustomThreadFactoryBuilder; + +import java.io.IOException; +import java.nio.file.Files; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import static pl.skidam.automodpack_core.GlobalVariables.*; + +public class FullServerPack { + public final ThreadPoolExecutor CREATION_EXECUTOR = (ThreadPoolExecutor) Executors.newFixedThreadPool(Math.max(1, Runtime.getRuntime().availableProcessors() * 2), new CustomThreadFactoryBuilder().setNameFormat("AutoModpackCreation-%d").build()); + + private FullServerPackContent init() { + if (isGenerating()) { + LOGGER.error("Called generate() twice!"); + return null; + } + + try { + if (!Files.exists(hostContentModpackDir)) { + Files.createDirectories(hostContentModpackDir); + } + } catch (IOException e) { + LOGGER.error("Failed to create modpack directory", e); + e.printStackTrace(); + return null; + } + + return new FullServerPackContent(serverConfig.modpackName, hostContentModpackDir, CREATION_EXECUTOR); + } + + public boolean generateNew(FullServerPackContent content) { + if (content == null) return false; + return content.create(); + } + + public boolean generateNew() { + FullServerPackContent content = init(); + if (content == null) return false; + return content.create(); + } + + public boolean isGenerating() { + int activeCount = CREATION_EXECUTOR.getActiveCount(); + int queueSize = CREATION_EXECUTOR.getQueue().size(); + return activeCount > 0 || queueSize > 0; + } + + public void shutdownExecutor() { + CREATION_EXECUTOR.shutdown(); + try { + if (!CREATION_EXECUTOR.awaitTermination(5, TimeUnit.SECONDS)) { + CREATION_EXECUTOR.shutdownNow(); + if (!CREATION_EXECUTOR.awaitTermination(3, TimeUnit.SECONDS)) { + LOGGER.error("CREATION Executor did not terminate"); + } + } + } catch (InterruptedException e) { + CREATION_EXECUTOR.shutdownNow(); + } + } +} \ No newline at end of file diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index 089e52f01..8a664682e 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -7,6 +7,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; @@ -16,23 +17,162 @@ public class FullServerPackContent { - public static Jsons.FullServerPackContentFields buildFullServerPackContent(List files) { - Set contentList = Collections.synchronizedSet(new HashSet<>()); - ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(4); + public final Set list = Collections.synchronizedSet(new HashSet<>()); + private final String MODPACK_NAME; + private final Path MODPACK_DIR; + private final ThreadPoolExecutor CREATION_EXECUTOR; + private final Map sha1MurmurMapPreviousContent = new HashMap<>(); + + public FullServerPackContent(String modpackName, Path modpackDir, ThreadPoolExecutor executor) { + this.MODPACK_NAME = modpackName; + this.MODPACK_DIR = modpackDir; + this.CREATION_EXECUTOR = executor; + } + + public boolean create() { + try { + LOGGER.info("Creating Full Server Pack for: {}", MODPACK_NAME); + + Path serverConfigFile = CustomFileUtils.getPathFromCWD("automodpack/automodpack-server.json"); + if (!Files.exists(serverConfigFile)) { + LOGGER.warn("Serverconfigfile is missing, did you delete it?: {}", serverConfigFile); + return false; + } + + Jsons.ServerConfigFields serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFields.class); + if (serverConfig == null || !serverConfig.enableFullServerPack) { + LOGGER.info("FullServerPack creation is disabled or config invalid."); + return false; + } + + List filesToInclude = new ArrayList<>(); + + //check synced files but not excluded, because we will get all files + List syncedFilePaths = serverConfig.syncedFiles != null ? serverConfig.syncedFiles : new ArrayList<>(); + for (String relativePath : syncedFilePaths) { + Path path = CustomFileUtils.getPathFromCWD(relativePath); + if (!Files.exists(path) || Files.isDirectory(path)) continue; + + String formatted = "/" + relativePath.replace("\\", "/"); + LOGGER.info("included from syncedFiles: {}", formatted); + filesToInclude.add(path); + } + + //adding default folders + List includeDefaultDirs = List.of( + CustomFileUtils.getPathFromCWD("mods"), + CustomFileUtils.getPathFromCWD("config"), + CustomFileUtils.getPathFromCWD("resourcepacks"), + CustomFileUtils.getPathFromCWD("shaderpacks") + //add more folders like KubeJS? or something whats needed, what not to be generated automaticly? + ); + + for (Path dir : includeDefaultDirs) { + if (!Files.exists(dir)) continue; + + try (Stream files = Files.walk(dir)) { + files.filter(Files::isRegularFile).forEach(path -> { + if (filesToInclude.contains(path)) return; + + String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); + String formatted = "/" + relative; + + LOGGER.info("included from default folders: {}", formatted); + filesToInclude.add(path); + }); + } catch (Exception e) { + LOGGER.error("Error while looking in folders: {}", dir, e); + } + } + // automodpack-host folders and files adding + Path automodpackHostFolder = CustomFileUtils.getPathFromCWD("automodpack/automodpack-host"); + if (Files.exists(automodpackHostFolder) && Files.isDirectory(automodpackHostFolder)) { + try (Stream files = Files.walk(automodpackHostFolder)) { + files.filter(Files::isRegularFile).forEach(path -> { + String fileName = path.getFileName().toString().toLowerCase(); + if (fileName.equals("fullserverpack-content.json") || fileName.equals("automodpack-content.json")) { + LOGGER.info("skipped content files from automodpack-host: {}", fileName); + return; + } + + String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); + String formatted = "/" + relative; + + LOGGER.info("included from automodpack-host: {}", formatted); + filesToInclude.add(path); + }); + } catch (Exception e) { + LOGGER.error("Error while looking in the automodpack-host folder: {}", automodpackHostFolder, e); + } + } + + // add server config itself + LOGGER.info("automodpack server config import: {}", serverConfigFile); + filesToInclude.add(serverConfigFile); + + // exclude files from loadFullServerPackExclude config defined + Set excludedFullPackFiles = ConfigTools.loadFullServerPackExclude(serverConfigFile); + + filesToInclude.removeIf(path -> { + String formatted = "/" + CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); + boolean isExcluded = excludedFullPackFiles.stream().anyMatch(rule -> { + if (rule.startsWith("!")) rule = rule.substring(1); + return rule.equalsIgnoreCase(formatted); + }); + + if (isExcluded) { + LOGGER.info("excluded files from config defined: {}", formatted); + } + return isExcluded; + }); + + // generate content and save it + Jsons.FullServerPackContentFields fullServerContent = buildFullServerPackContent(filesToInclude); + + Path outputPath = MODPACK_DIR.resolve("fullserverpack-content.json"); + ConfigTools.saveFullServerPackContent(outputPath, fullServerContent); + + LOGGER.info("FullServerPack content saved to: {}", outputPath); + return true; + + } catch (Exception e) { + LOGGER.error("Error during FullServerPack creation", e); + return false; + } + } + + private List collectFiles(Jsons.ServerConfigFields serverConfig) { + List filesToInclude = new ArrayList<>(); + + return filesToInclude; + } + + public Jsons.FullServerPackContentFields buildFullServerPackContent(List files) { + Set contentList = + Collections.synchronizedSet(new HashSet<>()); + + //ADDED ATOMICInteger to read, how much files are processed + AtomicInteger processed = new AtomicInteger(); + List> futures = new ArrayList<>(); for (int i = 0; i < files.size(); i += 6) { List subList = files.subList(i, Math.min(files.size(), i + 6)); - futures.add(CompletableFuture.runAsync(() -> subList.forEach(file -> generate(file, contentList)), executor)); + futures.add(CompletableFuture.runAsync(() -> { + for (Path file : subList) { + generate(file, contentList); + int done = processed.incrementAndGet(); + LOGGER.info("Files processed {} / {}", done, files.size()); + } + }, CREATION_EXECUTOR)); // use class defined executer } futures.forEach(CompletableFuture::join); - executor.shutdown(); return new Jsons.FullServerPackContentFields(contentList); } - private static void generate(Path file, Set contentList) { + private void generate(Path file, Set contentList) { try { if (!Files.isRegularFile(file)) return; @@ -78,6 +218,8 @@ private static void generate(Path file, Set { - if (rule.startsWith("!")) rule = rule.substring(1); - return rule.equalsIgnoreCase(formatted); - }); - - if (isExcluded) { - LOGGER.info("excluded from syncedFiles: {}", formatted); - continue; - } - LOGGER.info("included from syncedFiles: {}", formatted); filesToInclude.add(path); } @@ -141,16 +273,7 @@ public static void generateFromServerConfig() { String relative = CustomFileUtils.getPathFromCWD("").relativize(path).toString().replace("\\", "/"); String formatted = "/" + relative; - boolean isExcluded = excludedFiles.stream().anyMatch(rule -> { - if (rule.startsWith("!")) rule = rule.substring(1); - return rule.equalsIgnoreCase(formatted); - }); - - if (isExcluded) { - LOGGER.info("excluded from defaultDir: {}", formatted); - return; - } - LOGGER.info("included from defaultDir: {}", formatted); + LOGGER.info("included from defaultdir: {}", formatted); filesToInclude.add(path); }); } catch (Exception e) { @@ -186,7 +309,8 @@ public static void generateFromServerConfig() { } try { - Jsons.FullServerPackContentFields fullServerContent = FullServerPackContent.buildFullServerPackContent(filesToInclude); + FullServerPackContent fullServerPack = new FullServerPackContent("FullServer", CustomFileUtils.getPathFromCWD("automodpack/automodpack-host"), (ThreadPoolExecutor) Executors.newFixedThreadPool(4)); + Jsons.FullServerPackContentFields fullServerContent = fullServerPack.buildFullServerPackContent(filesToInclude); Path outputPath = CustomFileUtils.getPathFromCWD("automodpack/automodpack-host/fullserverpack-content.json"); ConfigTools.saveFullServerPackContent(outputPath, fullServerContent); From 14727d45e772be3497f16d338af57b3c58157d7a Mon Sep 17 00:00:00 2001 From: skidam Date: Sat, 29 Mar 2025 11:02:53 +0100 Subject: [PATCH 29/56] make it *work* --- .../automodpack_core/modpack/FullServerPackContent.java | 6 ------ .../automodpack/client/ui/DownloadSelectionScreen.java | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index 8a664682e..15098d844 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -33,12 +33,6 @@ public boolean create() { try { LOGGER.info("Creating Full Server Pack for: {}", MODPACK_NAME); - Path serverConfigFile = CustomFileUtils.getPathFromCWD("automodpack/automodpack-server.json"); - if (!Files.exists(serverConfigFile)) { - LOGGER.warn("Serverconfigfile is missing, did you delete it?: {}", serverConfigFile); - return false; - } - Jsons.ServerConfigFields serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFields.class); if (serverConfig == null || !serverConfig.enableFullServerPack) { LOGGER.info("FullServerPack creation is disabled or config invalid."); diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index b6db043a5..74d379332 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -75,7 +75,7 @@ protected void init() { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startLowUpdate); })); - this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidgSset(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); })); */ From a98e0bbae719daaaa5fa4c802f2763800f69a59e Mon Sep 17 00:00:00 2001 From: skidam Date: Sat, 29 Mar 2025 11:04:30 +0100 Subject: [PATCH 30/56] whoops --- .../skidam/automodpack/client/ui/DownloadSelectionScreen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index 74d379332..b6db043a5 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -75,7 +75,7 @@ protected void init() { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startLowUpdate); })); - this.addDrawableChild(buttonWidgSset(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); })); */ From ada65771102f326ac4997993e2e35064be85249c Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 29 Mar 2025 18:48:25 +0100 Subject: [PATCH 31/56] Revert "whoops" This reverts commit a98e0bbae719daaaa5fa4c802f2763800f69a59e. --- .../skidam/automodpack/client/ui/DownloadSelectionScreen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index b6db043a5..74d379332 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -75,7 +75,7 @@ protected void init() { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startLowUpdate); })); - this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidgSset(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); })); */ From a998740d87685edf39400ded85401020f8f6174c Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 29 Mar 2025 18:48:29 +0100 Subject: [PATCH 32/56] Revert "make it *work*" This reverts commit 14727d45e772be3497f16d338af57b3c58157d7a. --- .../automodpack_core/modpack/FullServerPackContent.java | 6 ++++++ .../automodpack/client/ui/DownloadSelectionScreen.java | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index 15098d844..8a664682e 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -33,6 +33,12 @@ public boolean create() { try { LOGGER.info("Creating Full Server Pack for: {}", MODPACK_NAME); + Path serverConfigFile = CustomFileUtils.getPathFromCWD("automodpack/automodpack-server.json"); + if (!Files.exists(serverConfigFile)) { + LOGGER.warn("Serverconfigfile is missing, did you delete it?: {}", serverConfigFile); + return false; + } + Jsons.ServerConfigFields serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFields.class); if (serverConfig == null || !serverConfig.enableFullServerPack) { LOGGER.info("FullServerPack creation is disabled or config invalid."); diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index 74d379332..b6db043a5 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -75,7 +75,7 @@ protected void init() { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startLowUpdate); })); - this.addDrawableChild(buttonWidgSset(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); })); */ From fcf375b30ca54f9094526532c27db5030f8b60ab Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 29 Mar 2025 18:53:25 +0100 Subject: [PATCH 33/56] Revert config catch from Skidam, added some loggers to debug informations --- core/src/main/java/pl/skidam/automodpack_core/Server.java | 1 + .../java/pl/skidam/automodpack_core/modpack/FullServerPack.java | 1 + .../skidam/automodpack_core/modpack/FullServerPackContent.java | 1 + 3 files changed, 3 insertions(+) diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index 33e920da4..3f43b4908 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -71,6 +71,7 @@ public static void main(String[] args) { } else { LOGGER.error("Failed to generate modpack!"); } + LOGGER.info("Start FullServerPack generation!"); FullServerPack fullserverpack = new FullServerPack(); FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, mainModpackDir, fullserverpack.CREATION_EXECUTOR); boolean fullpackgenerated = fullserverpack.generateNew(fullServerPackContent); diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java index aa5157048..3964a747e 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java @@ -14,6 +14,7 @@ public class FullServerPack { public final ThreadPoolExecutor CREATION_EXECUTOR = (ThreadPoolExecutor) Executors.newFixedThreadPool(Math.max(1, Runtime.getRuntime().availableProcessors() * 2), new CustomThreadFactoryBuilder().setNameFormat("AutoModpackCreation-%d").build()); private FullServerPackContent init() { + LOGGER.info("init() von FullServerPack wurde aufgerufen"); if (isGenerating()) { LOGGER.error("Called generate() twice!"); return null; diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index 8a664682e..dbc46eff3 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -30,6 +30,7 @@ public FullServerPackContent(String modpackName, Path modpackDir, ThreadPoolExec } public boolean create() { + LOGGER.info("FullServerPackContent.create() is called"); try { LOGGER.info("Creating Full Server Pack for: {}", MODPACK_NAME); From bd1070ff38e4d14e20dea409964c8ee6130ec84c Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 29 Mar 2025 20:21:09 +0100 Subject: [PATCH 34/56] something went wrong in the FullServerPack, without INIT, added Content Mapping, need to look, how the first generateNew is running... first fixing generation --- .../java/pl/skidam/automodpack_core/Server.java | 5 +++-- .../automodpack_core/modpack/FullServerPack.java | 16 +++++++++++++--- .../modpack/FullServerPackContent.java | 4 ++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index 3f43b4908..0ce2025bf 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -72,9 +72,10 @@ public static void main(String[] args) { LOGGER.error("Failed to generate modpack!"); } LOGGER.info("Start FullServerPack generation!"); + FullServerPack fullserverpack = new FullServerPack(); - FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, mainModpackDir, fullserverpack.CREATION_EXECUTOR); - boolean fullpackgenerated = fullserverpack.generateNew(fullServerPackContent); + //FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, mainModpackDir, fullserverpack.CREATION_EXECUTOR); + boolean fullpackgenerated = fullserverpack.generateNew(); if (fullpackgenerated) { LOGGER.info("FullServerPack generated!"); diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java index 3964a747e..7d66c2cba 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java @@ -4,6 +4,9 @@ import java.io.IOException; import java.nio.file.Files; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -11,7 +14,10 @@ import static pl.skidam.automodpack_core.GlobalVariables.*; public class FullServerPack { - public final ThreadPoolExecutor CREATION_EXECUTOR = (ThreadPoolExecutor) Executors.newFixedThreadPool(Math.max(1, Runtime.getRuntime().availableProcessors() * 2), new CustomThreadFactoryBuilder().setNameFormat("AutoModpackCreation-%d").build()); + public final ThreadPoolExecutor CREATION_EXECUTOR = (ThreadPoolExecutor) Executors.newFixedThreadPool(Math.max(1, Runtime.getRuntime().availableProcessors() * 2), new CustomThreadFactoryBuilder().setNameFormat("FullServerPackCreation-%d").build()); + public final Map fullpacks = Collections.synchronizedMap(new HashMap<>()); + + private FullServerPackContent init() { LOGGER.info("init() von FullServerPack wurde aufgerufen"); @@ -35,13 +41,17 @@ private FullServerPackContent init() { public boolean generateNew(FullServerPackContent content) { if (content == null) return false; - return content.create(); + boolean generated = content.create(); + fullpacks.put(content.getModpackName(), content); + return generated; } public boolean generateNew() { FullServerPackContent content = init(); if (content == null) return false; - return content.create(); + boolean generated = content.create(); + fullpacks.put(content.getModpackName(), content); + return generated; } public boolean isGenerating() { diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index dbc46eff3..3242740ed 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -29,6 +29,10 @@ public FullServerPackContent(String modpackName, Path modpackDir, ThreadPoolExec this.CREATION_EXECUTOR = executor; } + public String getModpackName() { + return MODPACK_NAME; + } + public boolean create() { LOGGER.info("FullServerPackContent.create() is called"); try { From 1a15178d80cdc11de4be41334768b62cb06c93c5 Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 29 Mar 2025 21:50:28 +0100 Subject: [PATCH 35/56] found in common.java the startserver init, updated the files to check if fullserverpack will generate now --- .../pl/skidam/automodpack_core/GlobalVariables.java | 2 ++ .../main/java/pl/skidam/automodpack_core/Server.java | 4 ++-- src/main/java/pl/skidam/automodpack/init/Common.java | 12 ++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java b/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java index 45c261583..1c24edc86 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java +++ b/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java @@ -4,6 +4,7 @@ import org.apache.logging.log4j.Logger; import pl.skidam.automodpack_core.config.Jsons; import pl.skidam.automodpack_core.loader.*; +import pl.skidam.automodpack_core.modpack.FullServerPack; import pl.skidam.automodpack_core.modpack.Modpack; import pl.skidam.automodpack_core.protocol.netty.NettyServer; @@ -24,6 +25,7 @@ public class GlobalVariables { public static Path THIZ_JAR; public static Path MODS_DIR; public static Modpack modpack; + public static FullServerPack fullpacks; public static NettyServer hostServer; public static Jsons.ServerConfigFields serverConfig; public static Jsons.ClientConfigFields clientConfig; diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index 0ce2025bf..97d20f1c7 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -74,8 +74,8 @@ public static void main(String[] args) { LOGGER.info("Start FullServerPack generation!"); FullServerPack fullserverpack = new FullServerPack(); - //FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, mainModpackDir, fullserverpack.CREATION_EXECUTOR); - boolean fullpackgenerated = fullserverpack.generateNew(); + FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, mainModpackDir, fullserverpack.CREATION_EXECUTOR); + boolean fullpackgenerated = fullserverpack.generateNew(fullServerPackContent); if (fullpackgenerated) { LOGGER.info("FullServerPack generated!"); diff --git a/src/main/java/pl/skidam/automodpack/init/Common.java b/src/main/java/pl/skidam/automodpack/init/Common.java index a973c2af2..f128e01ee 100644 --- a/src/main/java/pl/skidam/automodpack/init/Common.java +++ b/src/main/java/pl/skidam/automodpack/init/Common.java @@ -4,6 +4,7 @@ import net.minecraft.util.Identifier; import pl.skidam.automodpack.loader.GameCall; import pl.skidam.automodpack.networking.ModPackets; +import pl.skidam.automodpack_core.modpack.FullServerPack; import pl.skidam.automodpack_core.modpack.Modpack; import pl.skidam.automodpack_core.loader.LoaderManagerService; import pl.skidam.automodpack_core.protocol.netty.NettyServer; @@ -36,6 +37,15 @@ public static void serverInit() { LOGGER.error("Failed to load modpack!"); } } + if (serverConfig.enableFullServerPack) { + LOGGER.info("Generating FullServerModpack..."); + long genStart = System.currentTimeMillis(); + if (fullpacks.generateNew()) { + LOGGER.info("Modpack generated! took " + (System.currentTimeMillis() - genStart) + "ms"); + } else { + LOGGER.error("Failed to generate modpack!"); + } + } ModPackets.registerS2CPackets(); } @@ -44,6 +54,7 @@ public static void init() { GAME_CALL = new GameCall(); hostServer = new NettyServer(); modpack = new Modpack(); + fullpacks = new FullServerPack(); } public static void afterSetupServer() { @@ -61,6 +72,7 @@ public static void beforeShutdownServer() { hostServer.stop(); modpack.shutdownExecutor(); + fullpacks.shutdownExecutor(); } public static Identifier id(String path) { From 31819c6069395f0a983a934d800b1dbf99ecc37e Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 29 Mar 2025 22:39:01 +0100 Subject: [PATCH 36/56] updated path from fullserver-content.json file, and changed logger text --- core/src/main/java/pl/skidam/automodpack_core/Server.java | 2 +- src/main/java/pl/skidam/automodpack/init/Common.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index 97d20f1c7..b634e5e4f 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -74,7 +74,7 @@ public static void main(String[] args) { LOGGER.info("Start FullServerPack generation!"); FullServerPack fullserverpack = new FullServerPack(); - FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, mainModpackDir, fullserverpack.CREATION_EXECUTOR); + FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, hostContentModpackDir, fullserverpack.CREATION_EXECUTOR); boolean fullpackgenerated = fullserverpack.generateNew(fullServerPackContent); if (fullpackgenerated) { diff --git a/src/main/java/pl/skidam/automodpack/init/Common.java b/src/main/java/pl/skidam/automodpack/init/Common.java index f128e01ee..c22c5be7d 100644 --- a/src/main/java/pl/skidam/automodpack/init/Common.java +++ b/src/main/java/pl/skidam/automodpack/init/Common.java @@ -41,9 +41,9 @@ public static void serverInit() { LOGGER.info("Generating FullServerModpack..."); long genStart = System.currentTimeMillis(); if (fullpacks.generateNew()) { - LOGGER.info("Modpack generated! took " + (System.currentTimeMillis() - genStart) + "ms"); + LOGGER.info("FullServerModpack generated! took " + (System.currentTimeMillis() - genStart) + "ms"); } else { - LOGGER.error("Failed to generate modpack!"); + LOGGER.error("Failed to generate fullservermodpack!"); } } From 48a406da6d76de961d8c2bf3376db11e7df37ea4 Mon Sep 17 00:00:00 2001 From: Suerion Date: Sat, 29 Mar 2025 23:14:13 +0100 Subject: [PATCH 37/56] fixed path and added logger --- .../automodpack_core/modpack/FullServerPackContent.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index 3242740ed..72ce2d18c 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -90,10 +90,11 @@ public boolean create() { } } // automodpack-host folders and files adding - Path automodpackHostFolder = CustomFileUtils.getPathFromCWD("automodpack/automodpack-host"); + Path automodpackHostFolder = CustomFileUtils.getPathFromCWD("automodpack/host-modpack"); if (Files.exists(automodpackHostFolder) && Files.isDirectory(automodpackHostFolder)) { try (Stream files = Files.walk(automodpackHostFolder)) { files.filter(Files::isRegularFile).forEach(path -> { + LOGGER.info("Gefundene Datei: {}", path.toAbsolutePath()); String fileName = path.getFileName().toString().toLowerCase(); if (fileName.equals("fullserverpack-content.json") || fileName.equals("automodpack-content.json")) { LOGGER.info("skipped content files from automodpack-host: {}", fileName); @@ -292,7 +293,7 @@ public static void generateFromServerConfig() { } // adding client mod folders from automodpack host - Path automodpackHostDir = CustomFileUtils.getPathFromCWD("automodpack/automodpack-host"); + Path automodpackHostDir = CustomFileUtils.getPathFromCWD("automodpack/host-modpack"); if (Files.exists(automodpackHostDir) && Files.isDirectory(automodpackHostDir)) { try (Stream files = Files.walk(automodpackHostDir)) { files.filter(Files::isRegularFile).forEach(path -> { From a444ea43c781b07ce93c669ddbebfcaa80fe5123 Mon Sep 17 00:00:00 2001 From: Suerion Date: Sun, 30 Mar 2025 00:12:48 +0100 Subject: [PATCH 38/56] fixed path again --- .../automodpack_core/modpack/FullServerPackContent.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index 72ce2d18c..cdc06c478 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -315,10 +315,10 @@ public static void generateFromServerConfig() { } try { - FullServerPackContent fullServerPack = new FullServerPackContent("FullServer", CustomFileUtils.getPathFromCWD("automodpack/automodpack-host"), (ThreadPoolExecutor) Executors.newFixedThreadPool(4)); + FullServerPackContent fullServerPack = new FullServerPackContent("FullServer", CustomFileUtils.getPathFromCWD("automodpack/host-modpack"), (ThreadPoolExecutor) Executors.newFixedThreadPool(4)); Jsons.FullServerPackContentFields fullServerContent = fullServerPack.buildFullServerPackContent(filesToInclude); - Path outputPath = CustomFileUtils.getPathFromCWD("automodpack/automodpack-host/fullserverpack-content.json"); + Path outputPath = CustomFileUtils.getPathFromCWD("automodpack/host-modpack/fullserverpack-content.json"); ConfigTools.saveFullServerPackContent(outputPath, fullServerContent); LOGGER.info("servermodpack content file saved under: {}", outputPath); From 94408c8cb4719392382d428aeed7dc5747f59525 Mon Sep 17 00:00:00 2001 From: Suerion Date: Sun, 30 Mar 2025 17:10:52 +0200 Subject: [PATCH 39/56] should fixed the path now --- .../automodpack_core/modpack/FullServerPackContent.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index cdc06c478..f7f563eb2 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -33,6 +33,7 @@ public String getModpackName() { return MODPACK_NAME; } + public boolean create() { LOGGER.info("FullServerPackContent.create() is called"); try { @@ -135,10 +136,10 @@ public boolean create() { // generate content and save it Jsons.FullServerPackContentFields fullServerContent = buildFullServerPackContent(filesToInclude); - Path outputPath = MODPACK_DIR.resolve("fullserverpack-content.json"); + Path outputPath = hostModpackDir.resolve("fullserverpack-content.json"); ConfigTools.saveFullServerPackContent(outputPath, fullServerContent); - LOGGER.info("FullServerPack content saved to: {}", outputPath); + LOGGER.info("FullServerPack content saved to: {}", outputPath.toAbsolutePath()); return true; } catch (Exception e) { From 7382b4a3fe61ddf5c126e0dcb0779b86b9cc4acd Mon Sep 17 00:00:00 2001 From: Suerion Date: Sun, 30 Mar 2025 19:58:25 +0200 Subject: [PATCH 40/56] added in the FullServerPack file the ModpackName, MC Version and Loader --- .../java/pl/skidam/automodpack_core/config/Jsons.java | 8 +++++++- .../automodpack_core/modpack/FullServerPackContent.java | 7 ++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java index 8c1a78f06..a43c9666b 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java @@ -103,9 +103,15 @@ public String toString() { } } public static class FullServerPackContentFields { + public String modpackName = ""; + public String mcVersion = ""; + public String loader = ""; public Set list; - public FullServerPackContentFields(Set list) { + public FullServerPackContentFields(String modpackName, String mcVersion, String loader, Set list) { + this.modpackName = modpackName; + this.mcVersion = mcVersion; + this.loader = loader; this.list = list; } diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index f7f563eb2..f9f196dd5 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -176,7 +176,7 @@ public Jsons.FullServerPackContentFields buildFullServerPackContent(List f futures.forEach(CompletableFuture::join); - return new Jsons.FullServerPackContentFields(contentList); + return new Jsons.FullServerPackContentFields(MODPACK_NAME, MC_VERSION, LOADER, contentList); } private void generate(Path file, Set contentList) { @@ -218,7 +218,8 @@ private void generate(Path file, Set Date: Sun, 30 Mar 2025 22:41:36 +0200 Subject: [PATCH 41/56] preapared modpack loader, selection manger for fullservermodpack, and selected modpack changed Preload arguments for updater and also in DataC2SPacket corrected modpackpath if fullserver is selected added modpack dir selection right changed buttons in selectionsscreen and added an selected modpack text fixed language files --- .../automodpack_core/GlobalVariables.java | 1 + .../skidam/automodpack_core/config/Jsons.java | 1 + .../modpack/ModpackContent.java | 3 + .../automodpack_loader_core/Preload.java | 2 +- .../client/ModpackUpdater.java | 24 ++++---- .../client/ModpackUtils.java | 57 +++++-------------- .../utils/SelectionManager.java | 32 +++++------ .../client/ui/DownloadSelectionScreen.java | 27 +++++---- .../networking/packet/DataC2SPacket.java | 2 +- .../assets/automodpack/lang/de_de.json | 1 + .../assets/automodpack/lang/en_us.json | 1 + 11 files changed, 63 insertions(+), 88 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java b/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java index 1c24edc86..03dd505ec 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java +++ b/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java @@ -50,6 +50,7 @@ public class GlobalVariables { public static final Path clientConfigFile = automodpackDir.resolve("automodpack-client.json"); public static final Path clientSecretsFile = privateDir.resolve("automodpack-client-secrets.json"); public static final Path modpacksDir = automodpackDir.resolve("modpacks"); + public static final Path hostFullServerPackDir = automodpackDir.resolve("serverpack"); public static final String clientConfigFileOverrideResource = "overrides-automodpack-client.json"; public static String clientConfigOverride; // read from inside a jar file on preload, used instead of clientConfigFile if exists diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java index a43c9666b..af7aa604e 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java @@ -69,6 +69,7 @@ public static class ModpackContentFields { public String loader = ""; public String loaderVersion = ""; public String mcVersion = ""; + public boolean enableFullServerPack = false; public Set list; public ModpackContentFields(Set list) { diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java index 11d7b366a..aea2984e8 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java @@ -138,6 +138,9 @@ public synchronized void saveModpackContent() { modpackContent.loaderVersion = LOADER_VERSION; modpackContent.loader = LOADER; modpackContent.modpackName = MODPACK_NAME; + //add enableFullServerPack in ModpackContent to Check if Server give Permission to Server Pack + modpackContent.enableFullServerPack = serverConfig.enableFullServerPack; + ConfigTools.saveModpackContent(hostModpackContentFile, modpackContent); } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java index 078b0864b..2605082e3 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java @@ -93,7 +93,7 @@ private void updateAll() { CustomFileUtils.deleteDummyFiles(Path.of(System.getProperty("user.dir")), latestModpackContent == null ? null : latestModpackContent.list); // Update modpack - new ModpackUpdater().prepareUpdate(latestModpackContent, selectedModpackAddress, secret, selectedModpackDir); + new ModpackUpdater().prepareUpdate(latestModpackContent, selectedModpackAddress, secret); } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index 05acd4192..0d3e84cad 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -48,17 +48,21 @@ public String getModpackName() { return serverModpackContent.modpackName; } - public void prepareSelection() {} + public Jsons.ModpackContentFields getServerModpackContent() { + return serverModpackContent; + } - // old one should be okey, with new prepare Update, will look later on it because of content for selection //// public void prepareUpdate(Jsons.ModpackContentFields modpackContent, String link, Path modpackPath) { - public void prepareUpdate(Jsons.ModpackContentFields modpackContent, InetSocketAddress address, Secrets.Secret secret, Path modpackPath) { + public void prepareUpdate(Jsons.ModpackContentFields modpackContent, InetSocketAddress address, Secrets.Secret secret) { serverModpackContent = modpackContent; modpackAddress = address; modpackSecret = secret; - modpackDir = modpackPath; + modpackDir = ModpackUtils.getModpackPath(address, modpackContent.modpackName); + + //check out of selected Modpack + SelectionManager.setSelectedPack(serverModpackContent.modpackName); - if (modpackAddress == null || modpackPath.toString().isEmpty()) { + if (modpackAddress == null || modpackDir.toString().isEmpty()) { throw new IllegalArgumentException("Address or modpackPath is null or empty"); } @@ -170,14 +174,8 @@ public void startLowUpdate() {} public void startServerUpdate() {} */ public void startUpdate() { - String checkoutpack = SelectionManager.getSelectedPack(); - - //should be path one or two? bruhhh, not know yet, trying both - Path modpackFolder = ModpackUtils.getModpackPathFolder(checkoutpack); - Path modpackPathFolder = ModpackUtils.getModpackPathFolder(SelectionManager.getSelectedPack()); - - - + modpackDir = ModpackUtils.getModpackPath(modpackAddress, serverModpackContent.modpackName); + LOGGER.info("Using modpack directory: {}", modpackDir); if (modpackSecret == null) { LOGGER.error("Cannot update modpack, secret is null"); return; diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java index d5ee8cc53..86fb7483a 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java @@ -309,8 +309,18 @@ public static Path getClientPackage() { return getMinecraftPath().resolve("automodpack/host-modpack"); } + //add FullserverPack to selecting packs and it is need to change save folder + //add corrected Modpackpath if fullserverpack is selected + public static Path getCorrectModpackDir(Path modpackDirToSelect) { + if (modpackDirToSelect.getFileName().toString().equalsIgnoreCase("fullserver")) { + return hostFullServerPackDir.resolve("fullserver"); + } + return modpackDirToSelect; + } + // Returns true if value changed public static boolean selectModpack(Path modpackDirToSelect, InetSocketAddress modpackAddressToSelect, Set newDownloadedFiles) { + modpackDirToSelect = getCorrectModpackDir(modpackDirToSelect); final String modpackToSelect = modpackDirToSelect.getFileName().toString(); String selectedModpack = clientConfig.selectedModpack; @@ -368,6 +378,9 @@ public static void addModpackToList(String modpackName, InetSocketAddress addres // Returns modpack name formatted for path or url if server doesn't provide modpack name public static Path getModpackPath(InetSocketAddress address, String modpackName) { + if (modpackName.equalsIgnoreCase("fullserver")) { + return hostFullServerPackDir.resolve("fullserver"); + } String strAddress = address.getHostString() + ":" + address.getPort(); String correctedName = strAddress; @@ -510,48 +523,4 @@ static Set getEditableFiles(Set filesToInclude) { - Jsons.ModpackContentFields content = new Jsons.ModpackContentFields(); - content.modpackName = "FullServerPack"; - content.list = new HashSet<>(); - - for (Path file : filesToInclude) { - try { - - String sha1 = CustomFileUtils.getHash(file); - String murmur = CustomFileUtils.getCurseforgeMurmurHash(file); - String size = String.valueOf(Files.size(file)); - - // path for linux or windows - String formattedPath = "/" + ModpackUtils.getMinecraftPath().relativize(file).toString().replace("\\", "/"); - - // what type is folder - String type; - if (formattedPath.startsWith("/mods/")) { - type = "mod"; - } else if (formattedPath.startsWith("/shaderpacks/")) { - type = "shader"; - } else if (formattedPath.startsWith("/resourcepacks/")) { - type = "resourcepack"; - } else if (formattedPath.startsWith("/config/")) { - type = "config"; - } else { - type = "file"; - } - // filling with content - Jsons.ModpackContentFields.ModpackContentItem item = - new Jsons.ModpackContentFields.ModpackContentItem( - formattedPath, sha1, murmur, false, size, type - ); - - content.list.add(item); - } catch (IOException e) { - LOGGER.error("there is an error on the full server content: {}", file, e); - } - } - - return content; - } } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java index 6841fdd94..4fe8f1fc7 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SelectionManager.java @@ -1,26 +1,19 @@ package pl.skidam.automodpack_loader_core.utils; import pl.skidam.automodpack_loader_core.client.ModpackUtils; -import pl.skidam.automodpack_core.utils.CustomFileUtils; -import pl.skidam.automodpack_core.utils.CustomThreadFactoryBuilder; +import pl.skidam.automodpack_core.config.ConfigTools; +import pl.skidam.automodpack_core.config.Jsons; import java.io.*; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.net.URLConnection; -import java.nio.file.Files; -import java.nio.file.Path; -import java.time.Instant; import java.util.*; -import java.util.concurrent.*; -import java.util.zip.GZIPInputStream; - -import static pl.skidam.automodpack_core.GlobalVariables.AM_VERSION; -import static pl.skidam.automodpack_core.GlobalVariables.LOGGER; +import static pl.skidam.automodpack_core.GlobalVariables.clientConfig; +import static pl.skidam.automodpack_core.GlobalVariables.clientConfigFile; public class SelectionManager { + private static String selectedPack = "main"; + //select folders from host-modpack for difference client packs public static List getModpackFolders() { List modpacks = new ArrayList<>(); @@ -30,7 +23,7 @@ public static List getModpackFolders() { if (folders != null) { for (File dir : folders) { - if (!dir.getName().equalsIgnoreCase("main")) { // "main" überspringen + if (!dir.getName().equalsIgnoreCase("fullserver")) { // not using fullserver modpacks.add(dir.getName()); } } @@ -38,18 +31,19 @@ public static List getModpackFolders() { return modpacks; } - //give only main Pack - private static String selectedPack ="main"; - //give modpack from selected modpack and save to config public static void setSelectedPack(String modpack) { + if (Objects.equals(selectedPack, modpack)) return; selectedPack = modpack; - //TO DO Adding in Config... but how xD + //trying to add selected Modpack + if (!modpack.equalsIgnoreCase("fullserver")) { + clientConfig.selectedModpack = modpack; + ConfigTools.save(clientConfigFile, clientConfig); + } } //fetch modpack from config public static String getSelectedPack() { return selectedPack; } - } \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index b6db043a5..d54967ec5 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -3,10 +3,10 @@ import java.util.List; import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Util; import pl.skidam.automodpack_loader_core.client.ModpackUpdater; +import pl.skidam.automodpack_core.config.Jsons; import pl.skidam.automodpack.client.audio.AudioManager; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; @@ -37,30 +37,35 @@ protected void init() { })); //buttons from Selectionmanager - + String currentSelected = SelectionManager.getSelectedPack(); List modpacks = SelectionManager.getModpackFolders(); - //dynamisch wieviele buttons vorhanden sind + //dynamical how much buttons there int dynamicY = this.height / 2 - (modpacks.size() * 15); int i=0; for (String modpack : modpacks) { - // abstand einfügen + // between buttons int y = dynamicY + (i * 25); + var displayText = VersionedText.literal(modpack).formatted(modpack.equalsIgnoreCase(currentSelected) ? Formatting.GREEN : Formatting.BOLD); + this.addDrawableChild(buttonWidget(this.width / 2, y, 140, 20, VersionedText.literal(modpack).formatted(Formatting.BOLD), button -> { - //Auswählen und dann starten + //select and start SelectionManager.setSelectedPack(modpack); Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); i++; } - //Full Serverpack Button - this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, VersionedText.translatable("automodpack.ds.fullserverpack").formatted(Formatting.RED), button -> { - SelectionManager.setSelectedPack("fullserver"); - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); - })); + //Full Serverpack Button if Modpack has permission from server + Jsons.ModpackContentFields servercontent = modpackUpdaterInstance.getServerModpackContent(); + if (servercontent != null && servercontent.enableFullServerPack) { + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, VersionedText.translatable("automodpack.ds.fullserverpack").formatted(Formatting.RED), button -> { + SelectionManager.setSelectedPack("fullserver"); + Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + })); + } /* Old Buttons this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.ds.standard").formatted(Formatting.BOLD), button -> { @@ -83,6 +88,8 @@ protected void init() { @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { + //ADDE + drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.selected", VersionedText.literal(SelectionManager.getSelectedPack()).formatted(Formatting.GREEN, Formatting.BOLD)),this.width / 2, this.height / 2 - 15, 0xAAAAAA); drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds").formatted(Formatting.BOLD), this.width / 2, this.height / 2 - 60, 16777215); drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.description"), this.width / 2, this.height / 2 - 35, 16777215); drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.secDescription"), this.width / 2, this.height / 2 - 25, 16777215); diff --git a/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java b/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java index b3cae6591..14d983c6c 100644 --- a/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java +++ b/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java @@ -66,7 +66,7 @@ public static CompletableFuture receive(MinecraftClient minecraft if (update) { disconnectImmediately(handler); - new ModpackUpdater().prepareUpdate(optionalServerModpackContent.get(), address, secret, modpackDir); + new ModpackUpdater().prepareUpdate(optionalServerModpackContent.get(), address, secret); needsDisconnecting = true; } else { boolean selectedModpackChanged = ModpackUtils.selectModpack(modpackDir, address, Set.of()); diff --git a/src/main/resources/assets/automodpack/lang/de_de.json b/src/main/resources/assets/automodpack/lang/de_de.json index 74b2ebfb5..d3401d15e 100644 --- a/src/main/resources/assets/automodpack/lang/de_de.json +++ b/src/main/resources/assets/automodpack/lang/de_de.json @@ -26,6 +26,7 @@ "automodpack.ds": "Dieser Server stellt verschiedene Versionen bereit!", "automodpack.ds.description": "Du kannst für dich die benötigte Version auswählen. Welche benötigst du?", "automodpack.ds.secDescription": "Verschiedenen Versionen benötigen andere PC Systeme!", + "automodpack.ds.selected": "Ausgewähltes Modpack: ", "automodpack.ds.fullserverpack": "Server Package", "automodpack.ds.confirm": "Download", "automodpack.ds.cancel": "Abbrechen", diff --git a/src/main/resources/assets/automodpack/lang/en_us.json b/src/main/resources/assets/automodpack/lang/en_us.json index 6fe94eb7a..2bad85787 100644 --- a/src/main/resources/assets/automodpack/lang/en_us.json +++ b/src/main/resources/assets/automodpack/lang/en_us.json @@ -27,6 +27,7 @@ "automodpack.ds.description": "You could chose, what version do you need? Chose the right one for you!", "automodpack.ds.secDescription": "The difference of the versions are dependent on your PC System!", "automodpack.ds.fullserverpack": "Full Server Pack", + "automodpack.ds.selected": "Selected Modpack: ", "automodpack.ds.confirm": "Download", "automodpack.ds.cancel": "Exit", From 171a543caa2bd1ee7a22e6d8f47708e7b2f9c4f4 Mon Sep 17 00:00:00 2001 From: Suerion Date: Mon, 19 May 2025 22:13:44 +0200 Subject: [PATCH 42/56] fix issues on update to bete36 hope the fix would fix it on --- .../automodpack_core/GlobalVariables.java | 3 +- .../pl/skidam/automodpack_core/Server.java | 9 ++-- .../skidam/automodpack_core/config/Jsons.java | 46 ++++++++++++++++++- .../modpack/FullServerPack.java | 23 ++++++++-- .../modpack/ModpackExecutor.java | 4 ++ .../automodpack_loader_core/Preload.java | 3 +- .../client/ModpackUpdater.java | 2 + .../client/ModpackUtils.java | 2 +- .../client/ui/DownloadSelectionScreen.java | 4 +- .../pl/skidam/automodpack/init/Common.java | 5 +- 10 files changed, 77 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java b/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java index 24c7bcc0c..719a8f110 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java +++ b/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java @@ -6,7 +6,6 @@ import pl.skidam.automodpack_core.loader.*; import pl.skidam.automodpack_core.modpack.ModpackExecutor; import pl.skidam.automodpack_core.modpack.FullServerPack; -import pl.skidam.automodpack_core.modpack.Modpack; import pl.skidam.automodpack_core.protocol.netty.NettyServer; import java.nio.file.Path; @@ -25,8 +24,8 @@ public class GlobalVariables { public static GameCallService GAME_CALL = new NullGameCall(); public static Path THIZ_JAR; public static Path MODS_DIR; + // new modpack class, now gen about the Executor public static ModpackExecutor modpackExecutor; - public static Modpack modpack; public static FullServerPack fullpacks; public static NettyServer hostServer; public static Jsons.ServerConfigFields serverConfig; diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index fb7cbf9ac..a3a607116 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -4,7 +4,6 @@ import pl.skidam.automodpack_core.config.Jsons; import pl.skidam.automodpack_core.modpack.ModpackExecutor; import pl.skidam.automodpack_core.modpack.FullServerPack; -import pl.skidam.automodpack_core.modpack.Modpack; import pl.skidam.automodpack_core.modpack.ModpackContent; import pl.skidam.automodpack_core.modpack.FullServerPackContent; import pl.skidam.automodpack_core.protocol.netty.NettyServer; @@ -74,10 +73,8 @@ public static void main(String[] args) { } LOGGER.info("Start FullServerPack generation!"); - modpackExecutor.stop(); - - FullServerPack fullserverpack = new FullServerPack(); - FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, hostContentModpackDir, fullserverpack.CREATION_EXECUTOR); + FullServerPack fullserverpack = new FullServerPack(modpackExecutor); + FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, hostContentModpackDir, fullserverpack.executor.getExecutor()); boolean fullpackgenerated = fullserverpack.generateNew(fullServerPackContent); @@ -87,7 +84,7 @@ public static void main(String[] args) { LOGGER.error("Failed to generate serverpack!"); } - modpack.shutdownExecutor(); + modpackExecutor.stop(); fullserverpack.shutdownExecutor(); LOGGER.info("Starting server on port {}", serverConfig.hostPort); server.start(); diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java index 6d89e047b..ead08f66d 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java @@ -62,8 +62,10 @@ public static class ServerConfigFields { public boolean generateModpackOnStart = true; public List syncedFiles = List.of("/mods/*.jar", "!/mods/iDontWantThisModInModpack.jar", "!/config/andThisConfigToo.json", "!/mods/andAllTheseMods-*.jar", "!/mods/server-*.jar"); public List allowEditsInFiles = List.of("/options.txt", "/config/*", "!/config/excludeThisFile"); + public boolean enableFullServerPack = false; + public List ServerPackExcluded = List.of("!/config/bottokens.toml", "!/config/ipadresses.json"); public boolean autoExcludeUnnecessaryFiles = true; -// public List forceLoad = List.of("/resourcepacks/someResourcePack.zip", "/shaderpacks/someShaderPack.zip"); + // public List forceLoad = List.of("/resourcepacks/someResourcePack.zip", "/shaderpacks/someShaderPack.zip"); // public List> forceLoad = new ArrayList<>(); public boolean requireAutoModpackOnClient = true; public boolean nagUnModdedClients = true; @@ -71,7 +73,7 @@ public static class ServerConfigFields { public String nagClickableMessage = "Click here to get the AutoModpack!"; public String nagClickableLink = "https://modrinth.com/project/automodpack"; public boolean autoExcludeServerSideMods = true; -// public boolean velocityMode = false; compat plugin... someday I hope + // public boolean velocityMode = false; compat plugin... someday I hope // public boolean forceToDisableAllOtherModsOnClients = false; public boolean hostModpackOnMinecraftPort = true; public String hostIp = ""; @@ -138,6 +140,46 @@ public ModpackContentItem(String file, String size, String type, boolean editabl public String toString() { return String.format("ModpackContentItems(file=%s, size=%s, type=%s, editable=%s, sha1=%s, murmur=%s)", file, size, type, editable, sha1, murmur); } + + } + } + public static class FullServerPackContentFields { + public String modpackName = ""; + public String mcVersion = ""; + public String loader = ""; + public Set list; + + public FullServerPackContentFields(String modpackName, String mcVersion, String loader, Set list) { + this.modpackName = modpackName; + this.mcVersion = mcVersion; + this.loader = loader; + this.list = list; + } + + public FullServerPackContentFields() { + this.list = Set.of(); + } + + public static class FullServerPackContentItem { + public String file; + public String size; + public String type; + public String sha1; + public String murmur; + + public FullServerPackContentItem(String file, String size, String type, String sha1, String murmur) { + this.file = file; + this.size = size; + this.type = type; + this.sha1 = sha1; + this.murmur = murmur; + } + + @Override + public String toString() { + return String.format("FullServerPackContentItem(file=%s, size=%s, type=%s, sha1=%s, murmur=%s)", file, size, type, sha1, murmur); + } } } } + diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java index 7d66c2cba..01fa902a2 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java @@ -7,16 +7,18 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import static pl.skidam.automodpack_core.GlobalVariables.*; public class FullServerPack { - public final ThreadPoolExecutor CREATION_EXECUTOR = (ThreadPoolExecutor) Executors.newFixedThreadPool(Math.max(1, Runtime.getRuntime().availableProcessors() * 2), new CustomThreadFactoryBuilder().setNameFormat("FullServerPackCreation-%d").build()); + public final ModpackExecutor executor; + public final Map fullpacks = Collections.synchronizedMap(new HashMap<>()); + public FullServerPack(ModpackExecutor executor) { + this.executor = executor; + } + private FullServerPackContent init() { @@ -36,7 +38,7 @@ private FullServerPackContent init() { return null; } - return new FullServerPackContent(serverConfig.modpackName, hostContentModpackDir, CREATION_EXECUTOR); + return new FullServerPackContent(serverConfig.modpackName, hostContentModpackDir, executor.getExecutor()); } public boolean generateNew(FullServerPackContent content) { @@ -55,13 +57,22 @@ public boolean generateNew() { } public boolean isGenerating() { + return executor.isRunning(); + /* Old executer + int activeCount = CREATION_EXECUTOR.getActiveCount(); int queueSize = CREATION_EXECUTOR.getQueue().size(); return activeCount > 0 || queueSize > 0; + + */ } public void shutdownExecutor() { + executor.stop(); + + /* Old executer CREATION_EXECUTOR.shutdown(); + try { if (!CREATION_EXECUTOR.awaitTermination(5, TimeUnit.SECONDS)) { CREATION_EXECUTOR.shutdownNow(); @@ -72,5 +83,7 @@ public void shutdownExecutor() { } catch (InterruptedException e) { CREATION_EXECUTOR.shutdownNow(); } + */ + } } \ No newline at end of file diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackExecutor.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackExecutor.java index e2d29761d..144556d01 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackExecutor.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackExecutor.java @@ -61,6 +61,10 @@ public boolean isGenerating() { return activeCount > 0 || queueSize > 0; } + public boolean isRunning() { + return !CREATION_EXECUTOR.isShutdown() && !CREATION_EXECUTOR.isTerminated(); + } + public ThreadPoolExecutor getExecutor() { return CREATION_EXECUTOR; } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java index 9137ccd74..1afb84c1d 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java @@ -82,7 +82,8 @@ private void updateAll() { CustomFileUtils.deleteDummyFiles(Path.of(System.getProperty("user.dir")), latestModpackContent == null ? null : latestModpackContent.list); // Update modpack - new ModpackUpdater().prepareUpdate(latestModpackContent, selectedModpackAddress, secret) + new ModpackUpdater().prepareUpdate(latestModpackContent, selectedModpackAddress, secret); + } } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index 0087785fa..7f261d969 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.net.ConnectException; +import java.net.InetSocketAddress; import java.net.SocketTimeoutException; import java.nio.file.*; import java.util.*; @@ -33,6 +34,7 @@ public class ModpackUpdater { public Map> failedDownloads = new HashMap<>(); private final Set newDownloadedFiles = new HashSet<>(); // Only files which did not exist before. Because some files may have the same name/path and be updated. private Jsons.ModpackAddresses modpackAddresses; + private InetSocketAddress modpackAddress; private Secrets.Secret modpackSecret; private Path modpackDir; private Path modpackContentFile; diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java index 6b91cf8ff..fb4d43cf3 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java @@ -357,7 +357,7 @@ public static Path getCorrectModpackDir(Path modpackDirToSelect) { } // Returns true if value changed - public static boolean selectModpack(Path modpackDirToSelect, InetSocketAddress modpackAddressToSelect, Set newDownloadedFiles) { + public static boolean selectModpack(Path modpackDirToSelect, Jsons.ModpackAddresses modpackAddresses, Set newDownloadedFiles) { modpackDirToSelect = getCorrectModpackDir(modpackDirToSelect); final String modpackToSelect = modpackDirToSelect.getFileName().toString(); diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index d54967ec5..ef8943d35 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -6,7 +6,6 @@ import net.minecraft.util.Formatting; import net.minecraft.util.Util; import pl.skidam.automodpack_loader_core.client.ModpackUpdater; -import pl.skidam.automodpack_core.config.Jsons; import pl.skidam.automodpack.client.audio.AudioManager; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; @@ -59,8 +58,7 @@ protected void init() { } //Full Serverpack Button if Modpack has permission from server - Jsons.ModpackContentFields servercontent = modpackUpdaterInstance.getServerModpackContent(); - if (servercontent != null && servercontent.enableFullServerPack) { + if (serverConfig != null && serverConfig.enableFullServerPack) { this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, VersionedText.translatable("automodpack.ds.fullserverpack").formatted(Formatting.RED), button -> { SelectionManager.setSelectedPack("fullserver"); Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); diff --git a/src/main/java/pl/skidam/automodpack/init/Common.java b/src/main/java/pl/skidam/automodpack/init/Common.java index 0bf2f45af..2bec9f5ae 100644 --- a/src/main/java/pl/skidam/automodpack/init/Common.java +++ b/src/main/java/pl/skidam/automodpack/init/Common.java @@ -6,7 +6,6 @@ import pl.skidam.automodpack.networking.ModPackets; import pl.skidam.automodpack_core.modpack.ModpackExecutor; import pl.skidam.automodpack_core.modpack.FullServerPack; -import pl.skidam.automodpack_core.modpack.Modpack; import pl.skidam.automodpack_core.loader.LoaderManagerService; import pl.skidam.automodpack_core.protocol.netty.NettyServer; @@ -56,8 +55,7 @@ public static void init() { hostServer = new NettyServer(); modpackExecutor = new ModpackExecutor(); - modpack = new Modpack(); - fullpacks = new FullServerPack(); + fullpacks = new FullServerPack(modpackExecutor); } @@ -77,7 +75,6 @@ public static void beforeShutdownServer() { hostServer.stop(); modpackExecutor.stop(); - modpack.shutdownExecutor(); fullpacks.shutdownExecutor(); } From f439c6f8f6bbbeed207e9cddd9fba889f6547e46 Mon Sep 17 00:00:00 2001 From: Suerion Date: Mon, 19 May 2025 22:59:34 +0200 Subject: [PATCH 43/56] fix false config input --- core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java | 1 + .../skidam/automodpack/client/ui/DownloadSelectionScreen.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java index ead08f66d..a6e990523 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java @@ -109,6 +109,7 @@ public static class ModpackContentFields { public String loader = ""; public String loaderVersion = ""; public String mcVersion = ""; + public boolean enableFullServerPack = false; public Set list; public ModpackContentFields(Set list) { diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index ef8943d35..bf3e86066 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -13,6 +13,8 @@ import pl.skidam.automodpack.client.ui.versioned.VersionedText; import pl.skidam.automodpack_loader_core.utils.SelectionManager; +import static pl.skidam.automodpack_core.GlobalVariables.serverConfig; + public class DownloadSelectionScreen extends VersionedScreen { private final Screen parent; private final ModpackUpdater modpackUpdaterInstance; From 603742fd342a517538f626df806a707571d969c5 Mon Sep 17 00:00:00 2001 From: Suerion Date: Tue, 20 May 2025 00:09:53 +0200 Subject: [PATCH 44/56] fix false adresses from full modpack --- .../automodpack_loader_core/client/ModpackUpdater.java | 10 +++++----- .../automodpack_loader_core/client/ModpackUtils.java | 5 +++-- .../automodpack/networking/packet/DataC2SPacket.java | 5 +++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index 7f261d969..840c4014c 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -48,12 +48,12 @@ public String getModpackName() { return serverModpackContent.modpackName; } - public void prepareUpdate(Jsons.ModpackContentFields modpackContent, InetSocketAddress address, Secrets.Secret secret) { + public void prepareUpdate(Jsons.ModpackContentFields modpackContent, Jsons.ModpackAddresses modpackAddresses, Secrets.Secret secret) { this.serverModpackContent = modpackContent; - this.modpackAddress = address; + this.modpackAddresses = modpackAddresses; + this.modpackAddress = modpackAddresses.hostAddress; this.modpackSecret = secret; - this.modpackDir = ModpackUtils.getModpackPath(address, modpackContent.modpackName); - this.modpackAddresses = new Jsons.ModpackAddresses(address, null); // falls nur hostAddress benötigt wird + this.modpackDir = ModpackUtils.getModpackPath(modpackAddresses, modpackContent.modpackName); // check out of selected Modpack SelectionManager.setSelectedPack(serverModpackContent.modpackName); @@ -169,7 +169,7 @@ public void startLowUpdate() {} public void startServerUpdate() {} */ public void startUpdate() { - modpackDir = ModpackUtils.getModpackPath(modpackAddress, serverModpackContent.modpackName); + modpackDir = ModpackUtils.getModpackPath(modpackAddresses, serverModpackContent.modpackName); LOGGER.info("Using modpack directory: {}", modpackDir); if (modpackSecret == null) { LOGGER.error("Cannot update modpack, secret is null"); diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java index fb4d43cf3..51f532c78 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java @@ -415,12 +415,13 @@ public static void addModpackToList(String modpackName, Jsons.ModpackAddresses m } // Returns modpack name formatted for path or url if server doesn't provide modpack name - public static Path getModpackPath(InetSocketAddress address, String modpackName) { + public static Path getModpackPath(Jsons.ModpackAddresses address, String modpackName) { if (modpackName.equalsIgnoreCase("fullserver")) { return hostFullServerPackDir.resolve("fullserver"); } - String strAddress = address.getHostString() + ":" + address.getPort(); + InetSocketAddress Address = address.hostAddress; + String strAddress = Address.getHostString() + ":" + Address.getPort(); String correctedName = strAddress; if (FileInspection.isInValidFileName(strAddress)) { diff --git a/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java b/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java index a6387064b..b84895f33 100644 --- a/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java +++ b/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java @@ -68,8 +68,9 @@ public static CompletableFuture receive(MinecraftClient minecraft Boolean needsDisconnecting = null; PacketByteBuf response = new PacketByteBuf(Unpooled.buffer()); - Path modpackDir = ModpackUtils.getModpackPath(modpackAddress, modpackName); + Jsons.ModpackAddresses modpackAddresses = new Jsons.ModpackAddresses(modpackAddress, serverAddress); + Path modpackDir = ModpackUtils.getModpackPath(modpackAddresses, modpackName); var optionalServerModpackContent = ModpackUtils.requestServerModpackContent(modpackAddresses, secret, true); if (optionalServerModpackContent.isPresent()) { @@ -77,7 +78,7 @@ public static CompletableFuture receive(MinecraftClient minecraft if (update) { disconnectImmediately(handler); - new ModpackUpdater().prepareUpdate(optionalServerModpackContent.get(), address, secret); + new ModpackUpdater().prepareUpdate(optionalServerModpackContent.get(), modpackAddresses, secret); needsDisconnecting = true; } else { boolean selectedModpackChanged = ModpackUtils.selectModpack(modpackDir, modpackAddresses, Set.of()); From f669a83f37dac48d9e30a83d541dc5cbf31708f2 Mon Sep 17 00:00:00 2001 From: Suerion Date: Tue, 20 May 2025 00:21:56 +0200 Subject: [PATCH 45/56] fix typo error in preload --- .../main/java/pl/skidam/automodpack_loader_core/Preload.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java index 1afb84c1d..a11ffc073 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java @@ -82,7 +82,7 @@ private void updateAll() { CustomFileUtils.deleteDummyFiles(Path.of(System.getProperty("user.dir")), latestModpackContent == null ? null : latestModpackContent.list); // Update modpack - new ModpackUpdater().prepareUpdate(latestModpackContent, selectedModpackAddress, secret); + new ModpackUpdater().prepareUpdate(latestModpackContent, modpackAddresses, secret); } } From 8328a953f096516d3a162720e70906092995e760 Mon Sep 17 00:00:00 2001 From: Suerion Date: Tue, 20 May 2025 00:30:59 +0200 Subject: [PATCH 46/56] update gradle to 4.1.0-beta1, new feature selection screen should be 4.1.0, would all updates enter, what skidamek has changed before --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8076bac0c..cfa96cd28 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,6 +16,6 @@ mixin_extras = 0.5.0-rc.2 mod_id = automodpack mod_name = AutoModpack -mod_version = 4.0.0-beta36 +mod_version = 4.1.0-beta1 mod_group = pl.skidam.automodpack mod_description = Enjoy a seamless modpack installation process and effortless updates with a user-friendly solution that simplifies management, making your gaming experience a breeze. From 83817868369fa74b8f616fcf79dcfe372b4f6edf Mon Sep 17 00:00:00 2001 From: skidam Date: Fri, 25 Jul 2025 16:28:10 +0200 Subject: [PATCH 47/56] Refactor modpack handling to support group-based configurations with V3 config and update related data structures --- .../automodpack_core/GlobalVariables.java | 6 +- .../pl/skidam/automodpack_core/Server.java | 23 +++---- .../automodpack_core/config/ConfigTools.java | 6 +- .../skidam/automodpack_core/config/Jsons.java | 68 +++++++++++++++++-- .../modpack/ModpackContent.java | 54 ++++++++------- .../modpack/ModpackExecutor.java | 28 ++++---- .../utils/CustomFileUtils.java | 8 +-- .../utils/ModpackContentTools.java | 4 +- .../utils/WorkaroundUtil.java | 4 +- .../automodpack_core/modpack/ModpackTest.java | 2 +- .../automodpack_loader_core/Preload.java | 33 +++++++-- .../automodpack_loader_core/SelfUpdater.java | 8 +-- .../client/ModpackUpdater.java | 22 +++--- .../client/ModpackUtils.java | 38 +++++------ .../client/ui/ChangelogScreen.java | 5 +- .../pl/skidam/automodpack/init/Common.java | 31 +++++---- .../skidam/automodpack/modpack/Commands.java | 16 ++++- 17 files changed, 232 insertions(+), 124 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java b/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java index 4b743f828..f3236b889 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java +++ b/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java @@ -25,7 +25,7 @@ public class GlobalVariables { public static Path MODS_DIR; public static ModpackExecutor modpackExecutor; public static NettyServer hostServer; - public static Jsons.ServerConfigFieldsV2 serverConfig; + public static Jsons.ServerConfigFieldsV3 serverConfig; public static Jsons.ClientConfigFieldsV2 clientConfig; public static Jsons.KnownHostsFields knownHosts; public static final Path automodpackDir = Path.of("automodpack"); @@ -34,8 +34,8 @@ public class GlobalVariables { // Main - required // Addons - optional addon packs // Switches - optional or required packs, chosen by the player, only one can be installed at a time - public static final Path hostContentModpackDir = hostModpackDir.resolve("main"); - public static Path hostModpackContentFile = hostModpackDir.resolve("automodpack-content.json"); + public static final Path mainHostContentModpackDir = hostModpackDir.resolve("main"); + public static final Path hostModpackContentFile = hostModpackDir.resolve("automodpack-content.json"); public static Path serverConfigFile = automodpackDir.resolve("automodpack-server.json"); public static Path serverCoreConfigFile = automodpackDir.resolve("automodpack-core.json"); public static final Path privateDir = automodpackDir.resolve(".private"); diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index 763e8d7cd..d266bc0ef 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -3,11 +3,9 @@ import pl.skidam.automodpack_core.config.ConfigTools; import pl.skidam.automodpack_core.config.Jsons; import pl.skidam.automodpack_core.modpack.ModpackExecutor; -import pl.skidam.automodpack_core.modpack.ModpackContent; import pl.skidam.automodpack_core.protocol.netty.NettyServer; import java.nio.file.Path; -import java.util.ArrayList; import static pl.skidam.automodpack_core.GlobalVariables.*; @@ -31,13 +29,12 @@ public static void main(String[] args) { modpackDir.toFile().mkdirs(); - hostModpackContentFile = modpackDir.resolve("automodpack-content.json"); +// hostModpackContentFile = modpackDir.resolve("automodpack-content.json"); serverConfigFile = modpackDir.resolve("automodpack-server.json"); serverCoreConfigFile = modpackDir.resolve("automodpack-core.json"); - serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV2.class); + serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV3.class); if (serverConfig != null) { - serverConfig.syncedFiles = new ArrayList<>(); serverConfig.validateSecrets = false; ConfigTools.save(serverConfigFile, serverConfig); @@ -60,14 +57,14 @@ public static void main(String[] args) { mainModpackDir.toFile().mkdirs(); ModpackExecutor modpackExecutor = new ModpackExecutor(); - ModpackContent modpackContent = new ModpackContent(serverConfig.modpackName, null, mainModpackDir, serverConfig.syncedFiles, serverConfig.allowEditsInFiles, serverConfig.forceCopyFilesToStandardLocation, modpackExecutor.getExecutor()); - boolean generated = modpackExecutor.generateNew(modpackContent); - - if (generated) { - LOGGER.info("Modpack generated!"); - } else { - LOGGER.error("Failed to generate modpack!"); - } +// ModpackContent modpackContent = new ModpackContent(serverConfig.modpackName, null, mainModpackDir, serverConfig.syncedFiles, serverConfig.allowEditsInFiles, serverConfig.forceCopyFilesToStandardLocation, modpackExecutor.getExecutor()); +// boolean generated = modpackExecutor.generateNew(modpackContent); + +// if (generated) { +// LOGGER.info("Modpack generated!"); +// } else { +// LOGGER.error("Failed to generate modpack!"); +// } modpackExecutor.stop(); diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java b/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java index 7f921017e..873b3820a 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java @@ -123,11 +123,11 @@ public static void save(Path configFile, Object configObject) { // Modpack content stuff - public static Jsons.ModpackContentFields loadModpackContent(Path modpackContentFile) { + public static Jsons.ModpackGroupFields loadModpackContent(Path modpackContentFile) { try { if (Files.isRegularFile(modpackContentFile)) { String json = Files.readString(modpackContentFile); - return GSON.fromJson(json, Jsons.ModpackContentFields.class); + return GSON.fromJson(json, Jsons.ModpackGroupFields.class); } } catch (Exception e) { LOGGER.error("Couldn't load modpack content! {}", modpackContentFile.toAbsolutePath().normalize(), e); @@ -135,7 +135,7 @@ public static Jsons.ModpackContentFields loadModpackContent(Path modpackContentF return null; } - public static void saveModpackContent(Path modpackContentFile, Jsons.ModpackContentFields configObject) { + public static void saveModpackContent(Path modpackContentFile, Jsons.ModpackGroupFields configObject) { try { if (!Files.isDirectory(modpackContentFile.getParent())) { Files.createDirectories(modpackContentFile.getParent()); diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java index d2123e17c..60a222dfc 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java @@ -112,6 +112,54 @@ public static class ServerConfigFieldsV2 { public List acceptedLoaders; } + public static class GroupDeclaration { + public String groupName = ""; + public boolean generateModpackOnStart = true; + public List syncedFiles = List.of(); + public List allowEditsInFiles = List.of(); + public List forceCopyFilesToStandardLocation = List.of(); + public boolean autoExcludeServerSideMods = true; + public boolean autoExcludeUnnecessaryFiles = true; + public boolean required = false; + public boolean checkByDefault = false; + public List breaksWith = List.of(); + public List requiredBy = List.of(); + public List compatibleOS = List.of(); + } + + public static GroupDeclaration mainGroupDeclaration() { + GroupDeclaration decl = new GroupDeclaration(); + decl.required = true; + decl.checkByDefault = true; + decl.syncedFiles = List.of("/mods/*.jar", "/kubejs/**", "!/kubejs/server_scripts/**", "/emotes/*"); + decl.allowEditsInFiles = List.of("/options.txt", "/config/**"); + return decl; + } + + public static class ServerConfigFieldsV3 { + public int DO_NOT_CHANGE_IT = 3; // file version + public boolean modpackHost = true; + public Map groups = Map.of( + "main", mainGroupDeclaration() + ); + public boolean requireAutoModpackOnClient = true; + public boolean nagUnModdedClients = true; + public String nagMessage = "This server provides dedicated modpack through AutoModpack!"; + public String nagClickableMessage = "Click here to get the AutoModpack!"; + public String nagClickableLink = "https://modrinth.com/project/automodpack"; + public String bindAddress = ""; + public int bindPort = -1; + public String addressToSend = ""; + public int portToSend = -1; + public boolean disableInternalTLS = false; + public boolean updateIpsOnEveryStart = false; + public int bandwidthLimit = 0; + public boolean validateSecrets = true; + public long secretLifetime = 336; // 336 hours = 14 days + public boolean selfUpdater = false; + public List acceptedLoaders; + } + public static class ServerCoreConfigFields { public String automodpackVersion = "4.0.0-beta37"; // TODO: dont hardcode it public String loader = "fabric"; @@ -127,19 +175,31 @@ public static class KnownHostsFields { public Map hosts; // host, fingerprint } - public static class ModpackContentFields { - public String modpackName = ""; + public static class ModpackContentMasterFields { public String automodpackVersion = ""; public String loader = ""; public String loaderVersion = ""; public String mcVersion = ""; + public Set groups; + + public ModpackContentMasterFields(Set groups) { + this.groups = groups; + } + + public ModpackContentMasterFields() { + this.groups = Set.of(); + } + } + + public static class ModpackGroupFields { + public String groupName = ""; public Set list; - public ModpackContentFields(Set list) { + public ModpackGroupFields(Set list) { this.list = list; } - public ModpackContentFields() { + public ModpackGroupFields() { this.list = Set.of(); } diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java index 222366dd9..1d0dafe5f 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java @@ -15,17 +15,19 @@ import static pl.skidam.automodpack_core.GlobalVariables.LOGGER; public class ModpackContent { - public final Set list = Collections.synchronizedSet(new HashSet<>()); + public final Set list = Collections.synchronizedSet(new HashSet<>()); public final ObservableMap pathsMap = new ObservableMap<>(); private final String MODPACK_NAME; private final WildCards SYNCED_FILES_CARDS; private final WildCards EDITABLE_CARDS; private final WildCards FORCE_COPY_FILES_TO_STANDARD_LOCATION; + private final boolean AUTO_EXCLUDE_UNNECESSARY_FILES; + private final boolean AUTO_EXCLUDE_SERVER_SIDE_MODS; private final Path MODPACK_DIR; private final ThreadPoolExecutor CREATION_EXECUTOR; private final Map sha1MurmurMapPreviousContent = new HashMap<>(); - public ModpackContent(String modpackName, Path cwd, Path modpackDir, List syncedFiles, List allowEditsInFiles, List forceCopyFilesToStandardLocation, ThreadPoolExecutor CREATION_EXECUTOR) { + public ModpackContent(String modpackName, Path cwd, Path modpackDir, List syncedFiles, List allowEditsInFiles, List forceCopyFilesToStandardLocation, boolean autoExcludeUnnecessaryFiles, boolean autoExcludeServerSideMods, ThreadPoolExecutor CREATION_EXECUTOR) { this.MODPACK_NAME = modpackName; this.MODPACK_DIR = modpackDir; Set directoriesToSearch = new HashSet<>(2); @@ -38,6 +40,8 @@ public ModpackContent(String modpackName, Path cwd, Path modpackDir, List getPreviousContent() { + public Optional getPreviousContent() { var optionalModpackContentFile = ModpackContentTools.getModpackContentFile(MODPACK_DIR); return optionalModpackContentFile.map(ConfigTools::loadModpackContent); } @@ -103,12 +107,12 @@ public Optional getPreviousContent() { public boolean loadPreviousContent() { var optionalModpackContent = getPreviousContent(); if (optionalModpackContent.isEmpty()) return false; - Jsons.ModpackContentFields modpackContent = optionalModpackContent.get(); + Jsons.ModpackGroupFields modpackContent = optionalModpackContent.get(); synchronized (list) { list.addAll(modpackContent.list); - for (Jsons.ModpackContentFields.ModpackContentItem modpackContentItem : list) { + for (Jsons.ModpackGroupFields.ModpackContentItem modpackContentItem : list) { Path file = CustomFileUtils.getPath(MODPACK_DIR, modpackContentItem.file); if (!Files.exists(file)) file = CustomFileUtils.getPathFromCWD(modpackContentItem.file); if (!Files.exists(file)) { @@ -133,15 +137,24 @@ public boolean loadPreviousContent() { // This is important to make it synchronized otherwise it could corrupt the file and crash public synchronized void saveModpackContent() { synchronized (list) { - Jsons.ModpackContentFields modpackContent = new Jsons.ModpackContentFields(list); + Jsons.ModpackGroupFields modpackContent = new Jsons.ModpackGroupFields(list); + modpackContent.groupName = MODPACK_NAME; + ConfigTools.saveModpackContent(MODPACK_DIR.resolve(hostModpackContentFile.getFileName().toString()), modpackContent); + + synchronized (hostModpackContentFile) { + Jsons.ModpackContentMasterFields masterContent = ConfigTools.load(hostModpackContentFile, Jsons.ModpackContentMasterFields.class); + if (masterContent == null) { + masterContent = new Jsons.ModpackContentMasterFields(); + } - modpackContent.automodpackVersion = AM_VERSION; - modpackContent.mcVersion = MC_VERSION; - modpackContent.loaderVersion = LOADER_VERSION; - modpackContent.loader = LOADER; - modpackContent.modpackName = MODPACK_NAME; + masterContent.automodpackVersion = AM_VERSION; + masterContent.mcVersion = MC_VERSION; + masterContent.loaderVersion = LOADER_VERSION; + masterContent.loader = LOADER; - ConfigTools.saveModpackContent(hostModpackContentFile, modpackContent); + masterContent.groups.removeIf(group -> group.groupName.equals(MODPACK_NAME)); + masterContent.groups.add(modpackContent); + } } } @@ -158,7 +171,7 @@ private List> generateAsync(List files) { private void generate(Path file) { try { - Jsons.ModpackContentFields.ModpackContentItem item = generateContent(file); + Jsons.ModpackGroupFields.ModpackContentItem item = generateContent(file); if (item != null) { LOGGER.info("generated content for {}", item.file); synchronized (list) { @@ -185,7 +198,7 @@ public void remove(Path file) { String modpackFile = CustomFileUtils.formatPath(file, MODPACK_DIR); synchronized (list) { - for (Jsons.ModpackContentFields.ModpackContentItem item : this.list) { + for (Jsons.ModpackGroupFields.ModpackContentItem item : this.list) { if (item.file.equals(modpackFile)) { this.pathsMap.remove(item.sha1); this.list.remove(item); @@ -208,14 +221,9 @@ public static boolean isInnerFile(Path file) { return isInner; } - private Jsons.ModpackContentFields.ModpackContentItem generateContent(final Path file) throws Exception { + private Jsons.ModpackGroupFields.ModpackContentItem generateContent(final Path file) throws Exception { if (!Files.isRegularFile(file)) return null; - if (serverConfig == null) { - LOGGER.error("Server config is null!"); - return null; - } - if (isInnerFile(file)) { return null; } @@ -229,7 +237,7 @@ private Jsons.ModpackContentFields.ModpackContentItem generateContent(final Path final String size = String.valueOf(Files.size(file)); - if (serverConfig.autoExcludeUnnecessaryFiles) { + if (AUTO_EXCLUDE_UNNECESSARY_FILES) { if (size.equals("0")) { LOGGER.info("Skipping file {} because it is empty", formattedFile); return null; @@ -260,7 +268,7 @@ private Jsons.ModpackContentFields.ModpackContentItem generateContent(final Path if (FileInspection.isMod(file)) { type = "mod"; - if (serverConfig.autoExcludeServerSideMods && Objects.equals(FileInspection.getModEnvironment(file), LoaderManagerService.EnvironmentType.SERVER)) { + if (AUTO_EXCLUDE_SERVER_SIDE_MODS && Objects.equals(FileInspection.getModEnvironment(file), LoaderManagerService.EnvironmentType.SERVER)) { LOGGER.info("File {} is server mod! Skipping...", formattedFile); return null; } @@ -305,7 +313,7 @@ private Jsons.ModpackContentFields.ModpackContentItem generateContent(final Path LOGGER.info("File {} is forced to copy to standard location!", formattedFile); } - return new Jsons.ModpackContentFields.ModpackContentItem(formattedFile, size, type, isEditable, forcedToCopy, sha1, murmur); + return new Jsons.ModpackGroupFields.ModpackContentItem(formattedFile, size, type, isEditable, forcedToCopy, sha1, murmur); } } \ No newline at end of file diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackExecutor.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackExecutor.java index 887dd7aeb..3cf3da213 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackExecutor.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackExecutor.java @@ -14,26 +14,30 @@ public class ModpackExecutor { private final ThreadPoolExecutor CREATION_EXECUTOR = (ThreadPoolExecutor) Executors.newFixedThreadPool(Math.max(1, Runtime.getRuntime().availableProcessors() * 2), new CustomThreadFactoryBuilder().setNameFormat("AutoModpackCreation-%d").build()); public final Map modpacks = Collections.synchronizedMap(new HashMap<>()); - private ModpackContent init() { + private ModpackContent init(String groupId) { if (isGenerating()) { LOGGER.error("Called generate() twice!"); return null; } + Path modpackHostPath = hostModpackDir.resolve(groupId); + try { - if (!Files.exists(hostContentModpackDir)) { - Files.createDirectories(hostContentModpackDir); - Files.createDirectory(hostContentModpackDir.resolve("mods")); - Files.createDirectory(hostContentModpackDir.resolve("config")); - Files.createDirectory(hostContentModpackDir.resolve("shaderpacks")); - Files.createDirectory(hostContentModpackDir.resolve("resourcepacks")); + if (!Files.exists(modpackHostPath)) { + Files.createDirectories(modpackHostPath); + Files.createDirectory(modpackHostPath.resolve("mods")); + Files.createDirectory(modpackHostPath.resolve("config")); + Files.createDirectory(modpackHostPath.resolve("shaderpacks")); + Files.createDirectory(modpackHostPath.resolve("resourcepacks")); } } catch (IOException e) { e.printStackTrace(); } + var groupDecl = serverConfig.groups.get(groupId); + Path cwd = Path.of(System.getProperty("user.dir")); - return new ModpackContent(serverConfig.modpackName, cwd, hostContentModpackDir, serverConfig.syncedFiles, serverConfig.allowEditsInFiles, serverConfig.forceCopyFilesToStandardLocation, CREATION_EXECUTOR); + return new ModpackContent(groupDecl.groupName, cwd, modpackHostPath, groupDecl.syncedFiles, groupDecl.allowEditsInFiles, groupDecl.forceCopyFilesToStandardLocation, groupDecl.autoExcludeUnnecessaryFiles, groupDecl.autoExcludeServerSideMods, CREATION_EXECUTOR); } public boolean generateNew(ModpackContent content) { @@ -43,16 +47,16 @@ public boolean generateNew(ModpackContent content) { return generated; } - public boolean generateNew() { - ModpackContent content = init(); + public boolean generateNew(String groupId) { + ModpackContent content = init(groupId); if (content == null) return false; boolean generated = content.create(); modpacks.put(content.getModpackName(), content); return generated; } - public boolean loadLast() { - ModpackContent content = init(); + public boolean loadLast(String groupId) { + ModpackContent content = init(groupId); if (content == null) return false; boolean generated = content.loadPreviousContent(); modpacks.put(content.getModpackName(), content); diff --git a/core/src/main/java/pl/skidam/automodpack_core/utils/CustomFileUtils.java b/core/src/main/java/pl/skidam/automodpack_core/utils/CustomFileUtils.java index 8fa727290..9871277b4 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/utils/CustomFileUtils.java +++ b/core/src/main/java/pl/skidam/automodpack_core/utils/CustomFileUtils.java @@ -163,7 +163,7 @@ public static String formatPath(final Path modpackFile, final Path modpackPath) } - public static void deleteDummyFiles(Path directory, Set ignoreList) { + public static void deleteDummyFiles(Path directory, Set ignoreList) { if (directory == null || ignoreList == null) { return; } @@ -180,14 +180,14 @@ public static void deleteDummyFiles(Path directory, Set ignoreList) { + private static boolean shouldIgnore(Path file, Set ignoreList) { if (ignoreList == null) { return false; } - String modpackFile = CustomFileUtils.formatPath(file, Objects.requireNonNullElse(selectedModpackDir, hostContentModpackDir)); + String modpackFile = CustomFileUtils.formatPath(file, Objects.requireNonNullElse(selectedModpackDir, mainHostContentModpackDir)); - for (Jsons.ModpackContentFields.ModpackContentItem item : ignoreList) { + for (Jsons.ModpackGroupFields.ModpackContentItem item : ignoreList) { if (item.file.equals(modpackFile)) { return true; } diff --git a/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java b/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java index bd24f32bc..91b190e23 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java +++ b/core/src/main/java/pl/skidam/automodpack_core/utils/ModpackContentTools.java @@ -9,8 +9,8 @@ import static pl.skidam.automodpack_core.GlobalVariables.*; public class ModpackContentTools { - public static String getFileType(String file, Jsons.ModpackContentFields list) { - for (Jsons.ModpackContentFields.ModpackContentItem item : list.list) { + public static String getFileType(String file, Jsons.ModpackGroupFields list) { + for (Jsons.ModpackGroupFields.ModpackContentItem item : list.list) { if (item.file.contains(file)) { // compare file absolute path if it contains item.file return item.type; } diff --git a/core/src/main/java/pl/skidam/automodpack_core/utils/WorkaroundUtil.java b/core/src/main/java/pl/skidam/automodpack_core/utils/WorkaroundUtil.java index 931fab77f..64f9e544a 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/utils/WorkaroundUtil.java +++ b/core/src/main/java/pl/skidam/automodpack_core/utils/WorkaroundUtil.java @@ -17,7 +17,7 @@ public WorkaroundUtil(Path modapckPath) { // returns list of formatted modpack files which are mods with services (these mods need special treatment in order to work properly) // mods returned by this method should be installed in standard `~/mods/` directory - public Set getWorkaroundMods(Jsons.ModpackContentFields modpackContentFields) { + public Set getWorkaroundMods(Jsons.ModpackGroupFields modpackGroupFields) { Set workaroundMods = new HashSet<>(); // this workaround is needed only for neo/forge mods @@ -25,7 +25,7 @@ public Set getWorkaroundMods(Jsons.ModpackContentFields modpackContentFi return workaroundMods; } - for (Jsons.ModpackContentFields.ModpackContentItem item : modpackContentFields.list) { + for (Jsons.ModpackGroupFields.ModpackContentItem item : modpackGroupFields.list) { if (item.type.equals("mod")) { Path modPath = CustomFileUtils.getPath(modpackPath, item.file); if (FileInspection.hasSpecificServices(modPath)) { diff --git a/core/src/test/java/pl/skidam/automodpack_core/modpack/ModpackTest.java b/core/src/test/java/pl/skidam/automodpack_core/modpack/ModpackTest.java index e97b197fb..92602efc6 100644 --- a/core/src/test/java/pl/skidam/automodpack_core/modpack/ModpackTest.java +++ b/core/src/test/java/pl/skidam/automodpack_core/modpack/ModpackTest.java @@ -48,7 +48,7 @@ void modpackTest() { "ModpackContentItems(file=/mods/server-mod-1.20.jar, size=1, type=other, editable=false, sha1=86f7e437faa5a7fce15d1ddcb9eaeaea377667b8, murmur=null)" ); - ModpackContent content = new ModpackContent("TestPack", null, testFilesDir, new ArrayList<>(), new ArrayList<>(editable), new ArrayList<>(), new ModpackExecutor().getExecutor()); + ModpackContent content = new ModpackContent("TestPack", null, testFilesDir, new ArrayList<>(), new ArrayList<>(editable), new ArrayList<>(), false, false, new ModpackExecutor().getExecutor()); content.create(); boolean correct = true; diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java index 60217a188..5d523772a 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java @@ -172,10 +172,32 @@ private void loadConfigs() { ConfigTools.save(serverConfigFile, serverConfigV2); LOGGER.info("Updated server config version to {}", serverConfigVersion.DO_NOT_CHANGE_IT); } + + if (serverConfigVersion.DO_NOT_CHANGE_IT == 2) { + // Update the configs schemes to not crash the game if loaded with old config! + var serverConfigV2 = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV2.class); + var serverConfigV3 = ConfigTools.softLoad(serverConfigFile, Jsons.ServerConfigFieldsV3.class); + if (serverConfigV2 != null && serverConfigV3 != null) { + serverConfigVersion.DO_NOT_CHANGE_IT = 3; + serverConfigV3.DO_NOT_CHANGE_IT = 3; + + // copy all modpack fields from v2 to main modpack v3 + serverConfigV3.groups.get("main").groupName = serverConfigV2.modpackName; + serverConfigV3.groups.get("main").generateModpackOnStart = serverConfigV2.generateModpackOnStart; + serverConfigV3.groups.get("main").autoExcludeUnnecessaryFiles = serverConfigV2.autoExcludeUnnecessaryFiles; + serverConfigV3.groups.get("main").autoExcludeServerSideMods = serverConfigV2.autoExcludeServerSideMods; + serverConfigV3.groups.get("main").allowEditsInFiles = serverConfigV2.allowEditsInFiles; + serverConfigV3.groups.get("main").syncedFiles = serverConfigV2.syncedFiles; + serverConfigV3.groups.get("main").forceCopyFilesToStandardLocation = serverConfigV2.forceCopyFilesToStandardLocation; + + ConfigTools.save(serverConfigFile, serverConfigV3); + LOGGER.info("Updated server config version to {}", serverConfigVersion.DO_NOT_CHANGE_IT); + } + } } // load server config - serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV2.class); + serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV3.class); if (serverConfig != null) { // Add current loader to the list @@ -186,9 +208,12 @@ private void loadConfigs() { } // Check modpack name and fix it if needed, because it will be used for naming a folder on client - if (!serverConfig.modpackName.isEmpty() && FileInspection.isInValidFileName(serverConfig.modpackName)) { - serverConfig.modpackName = FileInspection.fixFileName(serverConfig.modpackName); - LOGGER.info("Changed modpack name to {}", serverConfig.modpackName); + for (String groupId : serverConfig.groups.keySet()) { + if (!groupId.isEmpty() && FileInspection.isInValidFileName(groupId)) { + serverConfig.groups.put(FileInspection.fixFileName(groupId), serverConfig.groups.get(groupId)); + serverConfig.groups.remove(groupId); + LOGGER.info("Changed modpack name to {}", groupId); + } } // Save changes diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/SelfUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/SelfUpdater.java index f2e9ef8ee..4016f77a6 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/SelfUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/SelfUpdater.java @@ -31,7 +31,7 @@ public static boolean update () { return update(null); } - public static boolean update(Jsons.ModpackContentFields serverModpackContent) { + public static boolean update(Jsons.ModpackContentMasterFields serverModpackContentMaster) { if (LOADER_MANAGER.isDevelopmentEnvironment()) return false; if (LOADER_MANAGER.getEnvironmentType() == LoaderManagerService.EnvironmentType.SERVER && !serverConfig.selfUpdater) { @@ -43,15 +43,15 @@ public static boolean update(Jsons.ModpackContentFields serverModpackContent) { boolean gettingServerVersion = false; // Check if server version is available - if (serverModpackContent != null && serverModpackContent.automodpackVersion != null) { - modrinthAPIList.add(ModrinthAPI.getModSpecificVersion(AUTOMODPACK_ID, serverModpackContent.automodpackVersion, serverModpackContent.mcVersion)); + if (serverModpackContentMaster != null && serverModpackContentMaster.automodpackVersion != null) { + modrinthAPIList.add(ModrinthAPI.getModSpecificVersion(AUTOMODPACK_ID, serverModpackContentMaster.automodpackVersion, serverModpackContentMaster.mcVersion)); gettingServerVersion = true; } else { modrinthAPIList = ModrinthAPI.getModInfosFromID(AUTOMODPACK_ID); } if (gettingServerVersion) { - LOGGER.info("Syncing AutoModpack to server version: {}", serverModpackContent.automodpackVersion); + LOGGER.info("Syncing AutoModpack to server version: {}", serverModpackContentMaster.automodpackVersion); } else if (LOADER_MANAGER.getEnvironmentType() == LoaderManagerService.EnvironmentType.CLIENT && !clientConfig.selfUpdater) { LOGGER.info("AutoModpack self-updater is disabled in client config."); return false; diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index fe18cbc7c..eb3d992f3 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -28,9 +28,9 @@ public class ModpackUpdater { public FetchManager fetchManager; public long totalBytesToDownload = 0; public boolean fullDownload = false; - private Jsons.ModpackContentFields serverModpackContent; + private Jsons.ModpackGroupFields serverModpackContent; private String modpackContentJson; - public Map> failedDownloads = new HashMap<>(); + public Map> failedDownloads = new HashMap<>(); private final Set newDownloadedFiles = new HashSet<>(); // Only files which did not exist before. Because some files may have the same name/path and be updated. private Jsons.ModpackAddresses modpackAddresses; private Secrets.Secret modpackSecret; @@ -39,10 +39,10 @@ public class ModpackUpdater { public String getModpackName() { - return serverModpackContent.modpackName; + return serverModpackContent.groupName; } - public void prepareUpdate(Jsons.ModpackContentFields modpackContent, Jsons.ModpackAddresses modpackAddresses, Secrets.Secret secret, Path modpackPath) { + public void prepareUpdate(Jsons.ModpackGroupFields modpackContent, Jsons.ModpackAddresses modpackAddresses, Secrets.Secret secret, Path modpackPath) { this.serverModpackContent = modpackContent; this.modpackAddresses = modpackAddresses; this.modpackSecret = secret; @@ -159,7 +159,7 @@ public void startUpdate() { modpackDir = ModpackUtils.renameModpackDir(serverModpackContent, modpackDir); modpackContentFile = modpackDir.resolve(modpackContentFile.getFileName()); - Iterator iterator = serverModpackContent.list.iterator(); + Iterator iterator = serverModpackContent.list.iterator(); // CLEAN UP THE LIST @@ -167,7 +167,7 @@ public void startUpdate() { int skippedEditableFiles = 0; while (iterator.hasNext()) { - Jsons.ModpackContentFields.ModpackContentItem modpackContentField = iterator.next(); + Jsons.ModpackGroupFields.ModpackContentItem modpackContentField = iterator.next(); String file = modpackContentField.file; String serverSHA1 = modpackContentField.sha1; @@ -208,7 +208,7 @@ public void startUpdate() { List fetchDatas = new LinkedList<>(); - for (Jsons.ModpackContentFields.ModpackContentItem field : serverModpackContent.list) { + for (Jsons.ModpackGroupFields.ModpackContentItem field : serverModpackContent.list) { totalBytesToDownload += Long.parseLong(field.size); @@ -418,7 +418,7 @@ private boolean applyModpack() throws Exception { } catch (IllegalArgumentException e) { LOGGER.error("Failed to save client secret", e); } - Jsons.ModpackContentFields modpackContent = ConfigTools.loadModpackContent(modpackContentFile); + Jsons.ModpackGroupFields modpackContent = ConfigTools.loadModpackContent(modpackContentFile); if (modpackContent == null) { throw new IllegalStateException("Failed to load modpack content"); // Something gone very wrong... @@ -511,11 +511,11 @@ private boolean applyModpack() throws Exception { } // returns set of formated files which we should not copy to the cwd - let them stay in the modpack directory - private Set getFilesNotToCopy(Set modpackContentItems, Set workaroundMods) { + private Set getFilesNotToCopy(Set modpackContentItems, Set workaroundMods) { Set filesNotToCopy = new HashSet<>(); // Make list of files which we do not copy to the running directory - for (Jsons.ModpackContentFields.ModpackContentItem item : modpackContentItems) { + for (Jsons.ModpackGroupFields.ModpackContentItem item : modpackContentItems) { if (item.forceCopy) { continue; } @@ -535,7 +535,7 @@ private Set getFilesNotToCopy(Set modpackFiles = modpackContent.list.stream().map(modpackContentField -> modpackContentField.file).toList(); List pathList; try (Stream pathStream = Files.walk(modpackDir)) { diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java index d66b3fe9e..090e6c854 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java @@ -25,7 +25,7 @@ public class ModpackUtils { - public static boolean isUpdate(Jsons.ModpackContentFields serverModpackContent, Path modpackDir) { + public static boolean isUpdate(Jsons.ModpackGroupFields serverModpackContent, Path modpackDir) { if (serverModpackContent == null || serverModpackContent.list == null) { throw new IllegalArgumentException("Server modpack content list is null"); } @@ -35,13 +35,13 @@ public static boolean isUpdate(Jsons.ModpackContentFields serverModpackContent, var optionalClientModpackContentFile = ModpackContentTools.getModpackContentFile(modpackDir); if (optionalClientModpackContentFile.isPresent() && Files.exists(optionalClientModpackContentFile.get())) { - Jsons.ModpackContentFields clientModpackContent = ConfigTools.loadModpackContent(optionalClientModpackContentFile.get()); + Jsons.ModpackGroupFields clientModpackContent = ConfigTools.loadModpackContent(optionalClientModpackContentFile.get()); if (clientModpackContent == null) { return true; } LOGGER.info("Checking files..."); - for (Jsons.ModpackContentFields.ModpackContentItem modpackContentField : serverModpackContent.list) { + for (Jsons.ModpackGroupFields.ModpackContentItem modpackContentField : serverModpackContent.list) { String file = modpackContentField.file; String serverSHA1 = modpackContentField.sha1; @@ -62,7 +62,7 @@ public static boolean isUpdate(Jsons.ModpackContentFields serverModpackContent, } // Server also might have deleted some files - for (Jsons.ModpackContentFields.ModpackContentItem modpackContentField : clientModpackContent.list) { + for (Jsons.ModpackGroupFields.ModpackContentItem modpackContentField : clientModpackContent.list) { var serverItemOpt = serverModpackContent.list.stream().filter(item -> item.file.equals(modpackContentField.file)).findFirst(); if (serverItemOpt.isEmpty()) { LOGGER.info("File does not exist on server {}", modpackContentField.file); @@ -77,11 +77,11 @@ public static boolean isUpdate(Jsons.ModpackContentFields serverModpackContent, } } - public static boolean correctFilesLocations(Path modpackDir, Jsons.ModpackContentFields serverModpackContent, Set filesNotToCopy) throws IOException { + public static boolean correctFilesLocations(Path modpackDir, Jsons.ModpackGroupFields serverModpackContent, Set filesNotToCopy) throws IOException { boolean needsRestart = false; // correct the files locations - for (Jsons.ModpackContentFields.ModpackContentItem contentItem : serverModpackContent.list) { + for (Jsons.ModpackGroupFields.ModpackContentItem contentItem : serverModpackContent.list) { String formattedFile = contentItem.file; Path modpackFile = CustomFileUtils.getPath(modpackDir, formattedFile); Path runFile = CustomFileUtils.getPathFromCWD(formattedFile); @@ -131,10 +131,10 @@ public static boolean correctFilesLocations(Path modpackDir, Jsons.ModpackConten return needsRestart; } - public static boolean removeRestModsNotToCopy(Jsons.ModpackContentFields serverModpackContent, Set filesNotToCopy, Set modsToKeep) { + public static boolean removeRestModsNotToCopy(Jsons.ModpackGroupFields serverModpackContent, Set filesNotToCopy, Set modsToKeep) { boolean needsRestart = false; - for (Jsons.ModpackContentFields.ModpackContentItem contentItem : serverModpackContent.list) { + for (Jsons.ModpackGroupFields.ModpackContentItem contentItem : serverModpackContent.list) { String formattedFile = contentItem.file; Path runFile = CustomFileUtils.getPathFromCWD(formattedFile); boolean isMod = "mod".equals(contentItem.type); @@ -299,14 +299,14 @@ private static void addDependenciesRecursively(FileInspection.Mod mod, Collectio } } - public static Path renameModpackDir(Jsons.ModpackContentFields serverModpackContent, Path modpackDir) { + public static Path renameModpackDir(Jsons.ModpackGroupFields serverModpackContent, Path modpackDir) { if (clientConfig.installedModpacks == null || clientConfig.selectedModpack == null || clientConfig.selectedModpack.isBlank()) { return modpackDir; } String installedModpackName = clientConfig.selectedModpack; Jsons.ModpackAddresses installedModpackAddresses = clientConfig.installedModpacks.get(installedModpackName); - String serverModpackName = serverModpackContent.modpackName; + String serverModpackName = serverModpackContent.groupName; if (installedModpackAddresses != null && !serverModpackName.equals(installedModpackName) && !serverModpackName.isEmpty()) { @@ -340,7 +340,7 @@ public static boolean selectModpack(Path modpackDirToSelect, Jsons.ModpackAddres // Save current editable files Path selectedModpackDir = modpacksDir.resolve(selectedModpack); Path selectedModpackContentFile = selectedModpackDir.resolve(hostModpackContentFile.getFileName()); - Jsons.ModpackContentFields modpackContent = ConfigTools.loadModpackContent(selectedModpackContentFile); + Jsons.ModpackGroupFields modpackContent = ConfigTools.loadModpackContent(selectedModpackContentFile); if (modpackContent != null) { Set editableFiles = getEditableFiles(modpackContent.list); ModpackUtils.preserveEditableFiles(selectedModpackDir, editableFiles, newDownloadedFiles); @@ -349,7 +349,7 @@ public static boolean selectModpack(Path modpackDirToSelect, Jsons.ModpackAddres // Copy editable files from modpack to select Path modpackContentFile = modpackDirToSelect.resolve(hostModpackContentFile.getFileName()); - Jsons.ModpackContentFields modpackContentToSelect = ConfigTools.loadModpackContent(modpackContentFile); + Jsons.ModpackGroupFields modpackContentToSelect = ConfigTools.loadModpackContent(modpackContentFile); if (modpackContentToSelect != null) { Set editableFiles = getEditableFiles(modpackContentToSelect.list); ModpackUtils.copyPreviousEditableFiles(modpackDirToSelect, editableFiles, newDownloadedFiles); @@ -412,19 +412,19 @@ public static Path getModpackPath(InetSocketAddress address, String modpackName) return modpackDir; } - public static Optional requestServerModpackContent(Jsons.ModpackAddresses modpackAddresses, Secrets.Secret secret, boolean allowAskingUser) { + public static Optional requestServerModpackContent(Jsons.ModpackAddresses modpackAddresses, Secrets.Secret secret, boolean allowAskingUser) { return fetchModpackContent(modpackAddresses, secret, (client) -> client.downloadFile(new byte[0], modpackContentTempFile, null), "Fetched", allowAskingUser); } - public static Optional refreshServerModpackContent(Jsons.ModpackAddresses modpackAddresses, Secrets.Secret secret, byte[][] fileHashes, boolean allowAskingUser) { + public static Optional refreshServerModpackContent(Jsons.ModpackAddresses modpackAddresses, Secrets.Secret secret, byte[][] fileHashes, boolean allowAskingUser) { return fetchModpackContent(modpackAddresses, secret, (client) -> client.requestRefresh(fileHashes, modpackContentTempFile), "Re-fetched", allowAskingUser); } - private static Optional fetchModpackContent(Jsons.ModpackAddresses modpackAddresses, Secrets.Secret secret, Function> operation, String fetchType, boolean allowAskingUser) { + private static Optional fetchModpackContent(Jsons.ModpackAddresses modpackAddresses, Secrets.Secret secret, Function> operation, String fetchType, boolean allowAskingUser) { if (secret == null) return Optional.empty(); if (modpackAddresses.isAnyEmpty()) @@ -522,8 +522,8 @@ private static Boolean askUserAboutCertificate(InetSocketAddress address, String } // check if modpackContent is valid/isn't malicious - public static boolean potentiallyMalicious(Jsons.ModpackContentFields serverModpackContent) { - String modpackName = serverModpackContent.modpackName; + public static boolean potentiallyMalicious(Jsons.ModpackGroupFields serverModpackContent) { + String modpackName = serverModpackContent.groupName; if (modpackName.contains("../") || modpackName.contains("/..")) { LOGGER.error("Modpack content is invalid, it contains /../ in modpack name"); return true; @@ -583,10 +583,10 @@ public static void copyPreviousEditableFiles(Path modpackDir, Set editab } } - static Set getEditableFiles(Set modpackContentItems) { + static Set getEditableFiles(Set modpackContentItems) { Set editableFiles = new HashSet<>(); - for (Jsons.ModpackContentFields.ModpackContentItem modpackContentItem : modpackContentItems) { + for (Jsons.ModpackGroupFields.ModpackContentItem modpackContentItem : modpackContentItems) { if (modpackContentItem.editable) { editableFiles.add(modpackContentItem.file); } diff --git a/src/main/java/pl/skidam/automodpack/client/ui/ChangelogScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/ChangelogScreen.java index a20a6fc1c..fc0d9e834 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/ChangelogScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/ChangelogScreen.java @@ -14,8 +14,7 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; + import net.minecraft.Util; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.EditBox; @@ -101,7 +100,7 @@ public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, drawSummaryOfChanges(matrices); } - private Jsons.ModpackContentFields modpackContent = null; + private Jsons.ModpackGroupFields modpackContent = null; private void drawSummaryOfChanges(VersionedMatrices matrices) { diff --git a/src/main/java/pl/skidam/automodpack/init/Common.java b/src/main/java/pl/skidam/automodpack/init/Common.java index b69d53471..f28f47288 100644 --- a/src/main/java/pl/skidam/automodpack/init/Common.java +++ b/src/main/java/pl/skidam/automodpack/init/Common.java @@ -19,21 +19,24 @@ public class Common { public static MinecraftServer server = null; public static void serverInit() { - if (serverConfig.generateModpackOnStart) { - LOGGER.info("Generating modpack..."); - long genStart = System.currentTimeMillis(); - if (modpackExecutor.generateNew()) { - LOGGER.info("Modpack generated! took " + (System.currentTimeMillis() - genStart) + "ms"); + for (String groupId : serverConfig.groups.keySet()) { + var groupDecl = serverConfig.groups.get(groupId); + if (groupDecl.generateModpackOnStart) { + LOGGER.info("Generating modpack..."); + long genStart = System.currentTimeMillis(); + if (modpackExecutor.generateNew(groupId)) { + LOGGER.info("Modpack generated! took " + (System.currentTimeMillis() - genStart) + "ms"); + } else { + LOGGER.error("Failed to generate modpack!"); + } } else { - LOGGER.error("Failed to generate modpack!"); - } - } else { - LOGGER.info("Loading last modpack..."); - long genStart = System.currentTimeMillis(); - if (modpackExecutor.loadLast()) { - LOGGER.info("Modpack loaded! took " + (System.currentTimeMillis() - genStart) + "ms"); - } else { - LOGGER.error("Failed to load modpack!"); + LOGGER.info("Loading last modpack..."); + long genStart = System.currentTimeMillis(); + if (modpackExecutor.loadLast(groupId)) { + LOGGER.info("Modpack loaded! took " + (System.currentTimeMillis() - genStart) + "ms"); + } else { + LOGGER.error("Failed to load modpack!"); + } } } diff --git a/src/main/java/pl/skidam/automodpack/modpack/Commands.java b/src/main/java/pl/skidam/automodpack/modpack/Commands.java index c804b1fdb..0aa3fccad 100644 --- a/src/main/java/pl/skidam/automodpack/modpack/Commands.java +++ b/src/main/java/pl/skidam/automodpack/modpack/Commands.java @@ -114,7 +114,7 @@ private static int connections(CommandContext context) { private static int reload(CommandContext context) { Util.backgroundExecutor().execute(() -> { - var tempServerConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV2.class); + var tempServerConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV3.class); if (tempServerConfig != null) { serverConfig = tempServerConfig; send(context, "AutoModpack server config reloaded!", ChatFormatting.GREEN, true); @@ -208,7 +208,19 @@ private static int generateModpack(CommandContext context) { } send(context, "Generating Modpack...", ChatFormatting.YELLOW, true); long start = System.currentTimeMillis(); - if (modpackExecutor.generateNew()) { + + // generate every group + boolean allGenerated = true; + for (String groupId : serverConfig.groups.keySet()) { + if (!modpackExecutor.generateNew(groupId)) { + allGenerated = false; + send(context, "Failed to generate modpack for group: " + groupId, ChatFormatting.RED, true); + } else { + send(context, "Modpack generated for group: " + groupId, ChatFormatting.GREEN, true); + } + } + + if (allGenerated) { send(context, "Modpack generated! took " + (System.currentTimeMillis() - start) + "ms", ChatFormatting.GREEN, true); } else { send(context, "Modpack generation failed! Check logs for more info.", ChatFormatting.RED, true); From 71bfad2619edb4a4162758c32c6204e0727c300b Mon Sep 17 00:00:00 2001 From: skidam Date: Sat, 26 Jul 2025 20:40:10 +0200 Subject: [PATCH 48/56] groups in the protocol --- .../modpack/ModpackContent.java | 6 +- .../protocol/DownloadClient.java | 45 ++++++++++++++ .../automodpack_core/protocol/NetUtils.java | 2 +- .../netty/handler/ProtocolMessageDecoder.java | 6 +- .../netty/handler/ProtocolMessageEncoder.java | 45 -------------- .../netty/handler/ServerMessageHandler.java | 58 +++++++++++++------ ...ssage.java => PackMetaRequestMessage.java} | 10 ++-- 7 files changed, 100 insertions(+), 72 deletions(-) delete mode 100644 core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolMessageEncoder.java rename core/src/main/java/pl/skidam/automodpack_core/protocol/netty/message/{EchoMessage.java => PackMetaRequestMessage.java} (55%) diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java index 1d0dafe5f..358106c5d 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java @@ -49,6 +49,10 @@ public String getModpackName() { return MODPACK_NAME; } + public Path getModpackContentFile() { + return MODPACK_DIR.resolve(hostModpackContentFile.getFileName().toString()); + } + public boolean create() { try { pathsMap.clear(); @@ -139,7 +143,7 @@ public synchronized void saveModpackContent() { synchronized (list) { Jsons.ModpackGroupFields modpackContent = new Jsons.ModpackGroupFields(list); modpackContent.groupName = MODPACK_NAME; - ConfigTools.saveModpackContent(MODPACK_DIR.resolve(hostModpackContentFile.getFileName().toString()), modpackContent); + ConfigTools.saveModpackContent(getModpackContentFile(), modpackContent); synchronized (hostModpackContentFile) { Jsons.ModpackContentMasterFields masterContent = ConfigTools.load(hostModpackContentFile, Jsons.ModpackContentMasterFields.class); diff --git a/core/src/main/java/pl/skidam/automodpack_core/protocol/DownloadClient.java b/core/src/main/java/pl/skidam/automodpack_core/protocol/DownloadClient.java index 912c4c22b..27589312f 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/protocol/DownloadClient.java +++ b/core/src/main/java/pl/skidam/automodpack_core/protocol/DownloadClient.java @@ -148,6 +148,15 @@ public CompletableFuture downloadFile(byte[] fileHash, Path destination, I return conn.sendDownloadFile(fileHash, destination, chunkCallback); } + /** + * + */ + public CompletableFuture fetchPackMeta(String groupId, Path destination, IntConsumer chunkCallback) { + Connection conn = getFreeConnection(); + return conn.sendPackMetaRequest(groupId, destination, chunkCallback); + } + + /** * Sends a refresh request with the given file hashes. */ @@ -395,6 +404,42 @@ public CompletableFuture sendDownloadFile(byte[] fileHash, Path destinatio }, executor); } + /** + * Sends a pack meta request over this connection. + */ + public CompletableFuture sendPackMetaRequest(String groupId, Path destination, IntConsumer chunkCallback) { + if (destination == null) { + throw new IllegalArgumentException("Destination cannot be null"); + } + + byte[] groupIdBytes = groupId.getBytes(); + + return CompletableFuture.supplyAsync(() -> { + Exception exception = null; + try { + // Build File Request message: + // [protocolVersion][FILE_REQUEST_TYPE][secret][int: groupIdBytes.length][groupIdBytes] + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + dos.writeByte(PROTOCOL_VERSION); + dos.writeByte(FILE_REQUEST_TYPE); + dos.write(secretBytes); + dos.writeInt(groupIdBytes.length); + dos.write(groupIdBytes); + dos.flush(); + byte[] payload = baos.toByteArray(); + + writeProtocolMessage(payload); + return readFileResponse(destination, chunkCallback); + } catch (Exception e) { + exception = e; + throw new CompletionException(e); + } finally { + finalBlock(exception); + } + }, executor); + } + /** * Sends a refresh request over this connection. */ diff --git a/core/src/main/java/pl/skidam/automodpack_core/protocol/NetUtils.java b/core/src/main/java/pl/skidam/automodpack_core/protocol/NetUtils.java index cc4a0994d..a58086f8e 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/protocol/NetUtils.java +++ b/core/src/main/java/pl/skidam/automodpack_core/protocol/NetUtils.java @@ -28,7 +28,7 @@ public class NetUtils { public static final int MAGIC_AMMC = 0x414D4D43; public static final int MAGIC_AMOK = 0x414D4F4B; - public static final byte ECHO_TYPE = 0x00; + public static final byte PACK_META_REQUEST_TYPE = 0x00; public static final byte FILE_REQUEST_TYPE = 0x01; public static final byte FILE_RESPONSE_TYPE = 0x02; public static final byte REFRESH_REQUEST_TYPE = 0x03; diff --git a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolMessageDecoder.java b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolMessageDecoder.java index d73095f3c..e38845601 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolMessageDecoder.java +++ b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolMessageDecoder.java @@ -4,7 +4,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import pl.skidam.automodpack_core.protocol.NetUtils; -import pl.skidam.automodpack_core.protocol.netty.message.EchoMessage; +import pl.skidam.automodpack_core.protocol.netty.message.PackMetaRequestMessage; import pl.skidam.automodpack_core.protocol.netty.message.FileRequestMessage; import pl.skidam.automodpack_core.protocol.netty.message.FileResponseMessage; import pl.skidam.automodpack_core.protocol.netty.message.RefreshRequestMessage; @@ -23,11 +23,11 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) t in.readBytes(secret); switch (type) { - case ECHO_TYPE: + case PACK_META_REQUEST_TYPE: int dataLength = in.readInt(); byte[] data = new byte[dataLength]; in.readBytes(data); - out.add(new EchoMessage(version, secret, data)); + out.add(new PackMetaRequestMessage(version, secret, data)); break; case FILE_REQUEST_TYPE: int fileHashLength = in.readInt(); diff --git a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolMessageEncoder.java b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolMessageEncoder.java deleted file mode 100644 index 9a8c59691..000000000 --- a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolMessageEncoder.java +++ /dev/null @@ -1,45 +0,0 @@ -package pl.skidam.automodpack_core.protocol.netty.handler; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.MessageToByteEncoder; -import pl.skidam.automodpack_core.protocol.netty.message.*; - -import static pl.skidam.automodpack_core.protocol.NetUtils.*; - -public class ProtocolMessageEncoder extends MessageToByteEncoder { - @Override - protected void encode(ChannelHandlerContext ctx, ProtocolMessage msg, ByteBuf out) throws Exception { - out.writeByte(msg.getVersion()); - out.writeByte(msg.getType()); - out.writeBytes(msg.getSecret()); - - switch (msg.getType()) { - case ECHO_TYPE: - EchoMessage echoMsg = (EchoMessage) msg; - out.writeInt(echoMsg.getDataLength()); - out.writeBytes(echoMsg.getData()); - break; - case FILE_REQUEST_TYPE: - FileRequestMessage fileRequestMessage = (FileRequestMessage) msg; - out.writeInt(fileRequestMessage.getFileHashLength()); - out.writeBytes(fileRequestMessage.getFileHash()); - break; - case FILE_RESPONSE_TYPE: - FileResponseMessage fileResponseMessage = (FileResponseMessage) msg; - out.writeInt(fileResponseMessage.getDataLength()); - out.writeBytes(fileResponseMessage.getData()); - break; - case REFRESH_REQUEST_TYPE: - RefreshRequestMessage refreshRequestMessage = (RefreshRequestMessage) msg; - out.writeInt(refreshRequestMessage.getFileHashesCount()); - out.writeInt(refreshRequestMessage.getFileHashesLength()); - for (byte[] fileHash : refreshRequestMessage.getFileHashesList()) { - out.writeBytes(fileHash); - } - break; - default: - throw new IllegalArgumentException("Unknown message type: " + msg.getType()); - } - } -} diff --git a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ServerMessageHandler.java b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ServerMessageHandler.java index f21968b58..fc39df5d8 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ServerMessageHandler.java +++ b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ServerMessageHandler.java @@ -8,8 +8,9 @@ import io.netty.handler.stream.ChunkedFile; import io.netty.util.CharsetUtil; import pl.skidam.automodpack_core.auth.Secrets; +import pl.skidam.automodpack_core.config.Jsons; import pl.skidam.automodpack_core.modpack.ModpackContent; -import pl.skidam.automodpack_core.protocol.netty.message.EchoMessage; +import pl.skidam.automodpack_core.protocol.netty.message.PackMetaRequestMessage; import pl.skidam.automodpack_core.protocol.netty.message.FileRequestMessage; import pl.skidam.automodpack_core.protocol.netty.message.ProtocolMessage; import pl.skidam.automodpack_core.protocol.netty.message.RefreshRequestMessage; @@ -48,19 +49,18 @@ protected void channelRead0(ChannelHandlerContext ctx, ProtocolMessage msg) thro } switch (msg.getType()) { - case ECHO_TYPE: - EchoMessage echoMsg = (EchoMessage) msg; - ByteBuf echoBuf = Unpooled.buffer(1 + 1 + msg.getSecret().length + echoMsg.getData().length); - echoBuf.writeByte(clientProtocolVersion); - echoBuf.writeByte(ECHO_TYPE); - echoBuf.writeBytes(echoMsg.getSecret()); - echoBuf.writeBytes(echoMsg.getData()); - ctx.writeAndFlush(echoBuf); - ctx.channel().close(); + case PACK_META_REQUEST_TYPE: + PackMetaRequestMessage metaRequest = (PackMetaRequestMessage) msg; + sendPackMeta(ctx, metaRequest.getData()); break; case FILE_REQUEST_TYPE: FileRequestMessage fileRequest = (FileRequestMessage) msg; - sendFile(ctx, fileRequest.getFileHash()); + Path filePath = resolveFile(fileRequest.getFileHash()); + if (filePath == null) { + sendError(ctx, (byte) 1, "File not found"); + } else { + sendFile(ctx, filePath); + } break; case REFRESH_REQUEST_TYPE: RefreshRequestMessage refreshRequest = (RefreshRequestMessage) msg; @@ -108,7 +108,7 @@ private void refreshModpackFiles(ChannelHandlerContext context, byte[][] FileHas LOGGER.info("Sending new modpack-content.json"); // Sends new json - sendFile(context, new byte[0]); + sendPackMeta(context, new byte[0]); } @@ -130,16 +130,40 @@ private boolean validateSecret(ChannelHandlerContext ctx, SocketAddress address, return valid; } - private void sendFile(ChannelHandlerContext ctx, byte[] bsha1) throws IOException { + private void sendPackMeta(ChannelHandlerContext ctx, byte[] data) throws IOException { + final String groupId = new String(data, CharsetUtil.UTF_8); + Jsons.GroupDeclaration requestedGroup = null; + if (!groupId.isBlank()) { + requestedGroup = serverConfig.groups.getOrDefault(groupId, null); + } + + if (requestedGroup == null) { + sendError(ctx, PROTOCOL_VERSION, "Group not found: " + groupId); + return; + } + + ModpackContent modpackContent = modpackExecutor.modpacks.get(requestedGroup.groupName); + Path hostModpackContentFile = modpackContent.getModpackContentFile(); + if (hostModpackContentFile == null || !Files.exists(hostModpackContentFile)) { + sendError(ctx, PROTOCOL_VERSION, "Modpack content file not found for group: " + groupId); + return; + } + + sendFile(ctx, hostModpackContentFile); + } + + private Path resolveFile(byte[] bsha1) { final String sha1 = new String(bsha1, CharsetUtil.UTF_8); final Optional optionalPath = resolvePath(sha1); - if (optionalPath.isEmpty() || !Files.exists(optionalPath.get())) { - sendError(ctx, (byte) 1, "File not found"); - return; + if (optionalPath.isPresent() && Files.exists(optionalPath.get())) { + return optionalPath.get(); } - final Path path = optionalPath.get(); + return null; + } + + private void sendFile(ChannelHandlerContext ctx, Path path) throws IOException { final long fileSize = Files.size(path); // Send file response header: version, FILE_RESPONSE type, then file size (8 bytes) diff --git a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/message/EchoMessage.java b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/message/PackMetaRequestMessage.java similarity index 55% rename from core/src/main/java/pl/skidam/automodpack_core/protocol/netty/message/EchoMessage.java rename to core/src/main/java/pl/skidam/automodpack_core/protocol/netty/message/PackMetaRequestMessage.java index e13a0110d..1a72e4bc6 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/message/EchoMessage.java +++ b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/message/PackMetaRequestMessage.java @@ -1,13 +1,13 @@ package pl.skidam.automodpack_core.protocol.netty.message; -import static pl.skidam.automodpack_core.protocol.NetUtils.ECHO_TYPE; +import static pl.skidam.automodpack_core.protocol.NetUtils.*; -public class EchoMessage extends ProtocolMessage { +public class PackMetaRequestMessage extends ProtocolMessage { private final int dataLength; private final byte[] data; - public EchoMessage(byte version, byte[] secret, byte[] data) { - super(version, ECHO_TYPE, secret); + public PackMetaRequestMessage(byte version, byte[] secret, byte[] data) { + super(version, PACK_META_REQUEST_TYPE, secret); this.dataLength = data.length; this.data = data; } @@ -19,4 +19,4 @@ public int getDataLength() { public byte[] getData() { return data; } -} +} \ No newline at end of file From 2942104d5025bbab500429e8dd942eacc092ba9c Mon Sep 17 00:00:00 2001 From: Suerion Date: Sun, 27 Jul 2025 13:36:31 +0200 Subject: [PATCH 49/56] update to latest beta --- .github/ISSUE_TEMPLATE/bug_report.yml | 3 +- .github/workflows/build.yml | 55 +--- .github/workflows/gradle.yml | 7 +- .github/workflows/release.yml | 18 +- .github/workflows/scripts/summary.py | 73 ----- .github/workflows/tests.yml | 2 +- .imgbotconfig | 14 - CONTRIBUTING.md | 2 +- README.md | 22 +- build.fabric.gradle.kts | 73 +++++ build.forge.gradle.kts | 106 +++++++ build.gradle.kts | 260 ---------------- build.neoforge.gradle.kts | 51 ++++ buildSrc/build.gradle.kts | 13 + .../main/kotlin/automodpack.common.gradle.kts | 247 ++++++++++++++++ core/build.gradle.kts | 14 +- .../automodpack_core/GlobalVariables.java | 2 +- .../pl/skidam/automodpack_core/Server.java | 26 +- .../automodpack_core/config/ConfigTools.java | 21 +- .../skidam/automodpack_core/config/Jsons.java | 48 ++- .../modpack/ModpackContent.java | 14 +- .../modpack/ModpackExecutor.java | 6 +- .../protocol/DownloadClient.java | 39 ++- .../automodpack_core/protocol/NetUtils.java | 15 +- .../protocol/netty/NettyServer.java | 112 +++---- .../protocol/netty/handler/ErrorPrinter.java | 3 +- .../netty/handler/ProtocolServerHandler.java | 42 +-- .../utils/AddressHelpers.java | 5 +- .../utils/CustomFileUtils.java | 8 +- .../automodpack_core/utils/WildCards.java | 15 +- .../utils/WorkaroundUtil.java | 8 +- .../automodpack_core/modpack/ModpackTest.java | 2 +- docs/.translated/fr_fr/_homepage.mdx | 9 + docs/.translated/fr_fr/_meta.json | 34 +++ docs/.translated/fr_fr/commands/_meta.json | 6 + docs/.translated/fr_fr/commands/commands.mdx | 11 + .../fr_fr/compatibility/_meta.json | 14 + .../fr_fr/compatibility/launchers.mdx | 15 + docs/.translated/fr_fr/compatibility/mods.mdx | 5 + .../fr_fr/compatibility/proxies.mdx | 14 + .../fr_fr/configuration/_meta.json | 14 + .../fr_fr/configuration/client-config.mdx | 10 + .../fr_fr/configuration/server-config.mdx | 29 ++ .../fr_fr/configuration/troubleshooting.mdx | 6 + docs/.translated/fr_fr/faq.mdx | 49 ++++ docs/.translated/fr_fr/quick-start.mdx | 36 +++ docs/.translated/fr_fr/technicals/_meta.json | 22 ++ .../fr_fr/technicals/certificate.mdx | 74 +++++ .../fr_fr/technicals/connection.mdx | 35 +++ .../fr_fr/technicals/file-structure.mdx | 24 ++ .../fr_fr/technicals/modpack-creation.mdx | 17 ++ .../fr_fr/technicals/modpack-hosting.mdx | 2 + docs/.translated/pl_pl/_homepage.mdx | 7 + docs/_homepage.mdx | 9 + docs/_meta.json | 34 +++ docs/commands/_meta.json | 6 + docs/commands/commands.mdx | 11 + docs/compatibility/_meta.json | 14 + docs/compatibility/launchers.mdx | 15 + docs/compatibility/mods.mdx | 6 + docs/compatibility/proxies.mdx | 14 + docs/configuration/_meta.json | 14 + docs/configuration/client-config.mdx | 10 + docs/configuration/server-config.mdx | 30 ++ docs/configuration/troubleshooting.mdx | 6 + docs/faq.mdx | 49 ++++ docs/quick-start.mdx | 35 +++ docs/sinytra-wiki.json | 7 + docs/technicals/_meta.json | 22 ++ docs/technicals/certificate.mdx | 45 +++ docs/technicals/connection.mdx | 35 +++ docs/technicals/file-structure.mdx | 21 ++ docs/technicals/modpack-creation.mdx | 17 ++ docs/technicals/modpack-hosting.mdx | 2 + gradle.properties | 19 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../automodpack_loader_core/Preload.java | 53 +++- .../automodpack_loader_core/SelfUpdater.java | 48 ++- .../client/ModpackUpdater.java | 22 +- .../client/ModpackUtils.java | 14 +- .../platforms/CurseForgeAPI.java | 2 +- .../platforms/ModrinthAPI.java | 27 +- .../utils/DownloadManager.java | 9 +- .../utils/FetchManager.java | 2 +- .../utils/SpeedMeter.java | 31 +- loader/fabric/15/gradle.properties | 5 +- loader/fabric/16/gradle.properties | 5 +- loader/fabric/core/gradle.properties | 5 +- .../core/src/main/resources/fabric.mod.json | 2 +- loader/forge/fml40/gradle.properties | 5 +- .../src/main/resources/META-INF/mods.toml | 2 +- loader/forge/fml47/gradle.properties | 5 +- .../src/main/resources/META-INF/mods.toml | 2 +- loader/loader-core.gradle.kts | 11 +- loader/loader-fabric-core.gradle.kts | 14 +- loader/loader-fabric.gradle.kts | 27 +- loader/loader-forge.gradle.kts | 67 ++--- loader/loader-neoforge.gradle.kts | 100 +++++++ loader/neoforge/fml2/gradle.properties | 5 +- .../src/main/resources/META-INF/mods.toml | 2 +- loader/neoforge/fml4/gradle.properties | 5 +- .../resources/META-INF/neoforge.mods.toml | 2 +- settings.gradle.kts | 67 ++--- .../skidam/automodpack/client/ScreenImpl.java | 36 +-- .../client/audio/AudioManager.java | 49 ++-- .../client/audio/CustomSoundInstance.java | 24 +- .../client/ui/ChangelogScreen.java | 85 +++--- .../automodpack/client/ui/DangerScreen.java | 52 +--- .../automodpack/client/ui/DownloadScreen.java | 98 +++---- .../automodpack/client/ui/ErrorScreen.java | 16 +- .../automodpack/client/ui/FetchScreen.java | 15 +- .../automodpack/client/ui/RestartScreen.java | 29 +- .../automodpack/client/ui/TextColors.java | 63 ++++ .../client/ui/ValidationScreen.java | 63 ++-- .../ui/versioned/VersionedCommandSource.java | 32 +- .../ui/versioned/VersionedMatrices.java | 48 ++- .../client/ui/versioned/VersionedScreen.java | 96 +++--- .../client/ui/versioned/VersionedText.java | 26 +- .../automodpack/client/ui/widget/Badge.java | 7 +- .../client/ui/widget/ListEntry.java | 53 ++-- .../client/ui/widget/ListEntryWidget.java | 56 ++-- .../pl/skidam/automodpack/init/Common.java | 8 +- .../mixin/core/ClientConnectionAccessor.java | 4 +- .../ClientLoginNetworkHandlerAccessor.java | 8 +- .../core/ClientLoginNetworkHandlerMixin.java | 16 +- .../mixin/core/ConnectScreenMixin.java | 32 +- .../mixin/core/DrawContextAccessor.java | 21 -- .../mixin/core/FabricLoginMixin.java | 4 +- .../core/LoginQueryRequestS2CPacketMixin.java | 12 +- .../LoginQueryResponseC2SPacketMixin.java | 14 +- .../mixin/core/MinecraftServerMixin.java | 8 +- .../mixin/core/MusicTrackerMixin.java | 27 +- .../mixin/core/PlayerManagerMixin.java | 55 ++-- .../ServerLoginNetworkHandlerAccessor.java | 14 +- .../core/ServerLoginNetworkHandlerMixin.java | 18 +- .../mixin/core/ServerNetworkIoMixin.java | 4 +- .../automodpack/mixin/dev/TestButton.java | 11 +- .../skidam/automodpack/modpack/Commands.java | 173 ++++++----- .../automodpack/modpack/GameHelpers.java | 38 ++- .../networking/LoginNetworkingIDs.java | 11 +- .../networking/LoginQueryParser.java | 45 ++- .../automodpack/networking/ModPackets.java | 16 +- .../automodpack/networking/PacketSender.java | 13 +- .../automodpack/networking/PayloadHelper.java | 10 +- .../client/ClientLoginNetworkAddon.java | 28 +- .../client/ClientLoginNetworking.java | 20 +- .../client/LoginResponsePayload.java | 14 +- .../networking/content/DataPacket.java | 6 +- .../networking/packet/DataC2SPacket.java | 57 ++-- .../networking/packet/DataS2CPacket.java | 53 ++-- .../networking/packet/HandshakeC2SPacket.java | 28 +- .../networking/packet/HandshakeS2CPacket.java | 87 ++---- .../server/LoginRequestPayload.java | 13 +- .../server/ServerLoginNetworkAddon.java | 34 +-- .../server/ServerLoginNetworking.java | 18 +- .../resources/META-INF/accesstransformer.cfg | 1 + src/main/resources/META-INF/mods.toml | 8 +- .../resources/META-INF/neoforge.mods.toml | 8 +- .../assets/automodpack/lang/fr_fr.json | Bin 5450 -> 3433 bytes .../assets/automodpack/lang/zh_cn.json | 10 +- .../resources/automodpack-main.mixins.json | 1 - src/main/resources/automodpack.accesswidener | 2 +- src/main/resources/fabric.mod.json | 2 +- src/main/resources/pack.mcmeta | 3 +- stonecutter.gradle.kts | 277 ++---------------- versions/1.18.2-fabric/gradle.properties | 13 +- versions/1.18.2-forge/gradle.properties | 13 +- versions/1.19.2-fabric/gradle.properties | 13 +- versions/1.19.2-forge/gradle.properties | 13 +- versions/1.19.4-fabric/gradle.properties | 13 +- versions/1.19.4-forge/gradle.properties | 13 +- versions/1.20.1-fabric/gradle.properties | 13 +- versions/1.20.1-forge/gradle.properties | 13 +- versions/1.20.4-fabric/gradle.properties | 13 +- versions/1.20.4-neoforge/gradle.properties | 13 +- versions/1.20.6-fabric/gradle.properties | 13 +- versions/1.20.6-neoforge/gradle.properties | 13 +- versions/1.21.1-fabric/gradle.properties | 13 +- versions/1.21.1-neoforge/gradle.properties | 13 +- versions/1.21.3-fabric/gradle.properties | 13 +- versions/1.21.3-neoforge/gradle.properties | 13 +- versions/1.21.4-fabric/gradle.properties | 13 +- versions/1.21.4-neoforge/gradle.properties | 13 +- versions/1.21.5-fabric/gradle.properties | 5 + versions/1.21.5-neoforge/gradle.properties | 5 + versions/1.21.6-fabric/gradle.properties | 4 + versions/1.21.6-neoforge/gradle.properties | 4 + 187 files changed, 2927 insertions(+), 2126 deletions(-) delete mode 100644 .github/workflows/scripts/summary.py delete mode 100644 .imgbotconfig create mode 100644 build.fabric.gradle.kts create mode 100644 build.forge.gradle.kts delete mode 100644 build.gradle.kts create mode 100644 build.neoforge.gradle.kts create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/src/main/kotlin/automodpack.common.gradle.kts create mode 100644 docs/.translated/fr_fr/_homepage.mdx create mode 100644 docs/.translated/fr_fr/_meta.json create mode 100644 docs/.translated/fr_fr/commands/_meta.json create mode 100644 docs/.translated/fr_fr/commands/commands.mdx create mode 100644 docs/.translated/fr_fr/compatibility/_meta.json create mode 100644 docs/.translated/fr_fr/compatibility/launchers.mdx create mode 100644 docs/.translated/fr_fr/compatibility/mods.mdx create mode 100644 docs/.translated/fr_fr/compatibility/proxies.mdx create mode 100644 docs/.translated/fr_fr/configuration/_meta.json create mode 100644 docs/.translated/fr_fr/configuration/client-config.mdx create mode 100644 docs/.translated/fr_fr/configuration/server-config.mdx create mode 100644 docs/.translated/fr_fr/configuration/troubleshooting.mdx create mode 100644 docs/.translated/fr_fr/faq.mdx create mode 100644 docs/.translated/fr_fr/quick-start.mdx create mode 100644 docs/.translated/fr_fr/technicals/_meta.json create mode 100644 docs/.translated/fr_fr/technicals/certificate.mdx create mode 100644 docs/.translated/fr_fr/technicals/connection.mdx create mode 100644 docs/.translated/fr_fr/technicals/file-structure.mdx create mode 100644 docs/.translated/fr_fr/technicals/modpack-creation.mdx create mode 100644 docs/.translated/fr_fr/technicals/modpack-hosting.mdx create mode 100644 docs/.translated/pl_pl/_homepage.mdx create mode 100644 docs/_homepage.mdx create mode 100644 docs/_meta.json create mode 100644 docs/commands/_meta.json create mode 100644 docs/commands/commands.mdx create mode 100644 docs/compatibility/_meta.json create mode 100644 docs/compatibility/launchers.mdx create mode 100644 docs/compatibility/mods.mdx create mode 100644 docs/compatibility/proxies.mdx create mode 100644 docs/configuration/_meta.json create mode 100644 docs/configuration/client-config.mdx create mode 100644 docs/configuration/server-config.mdx create mode 100644 docs/configuration/troubleshooting.mdx create mode 100644 docs/faq.mdx create mode 100644 docs/quick-start.mdx create mode 100644 docs/sinytra-wiki.json create mode 100644 docs/technicals/_meta.json create mode 100644 docs/technicals/certificate.mdx create mode 100644 docs/technicals/connection.mdx create mode 100644 docs/technicals/file-structure.mdx create mode 100644 docs/technicals/modpack-creation.mdx create mode 100644 docs/technicals/modpack-hosting.mdx create mode 100644 loader/loader-neoforge.gradle.kts create mode 100644 src/main/java/pl/skidam/automodpack/client/ui/TextColors.java delete mode 100644 src/main/java/pl/skidam/automodpack/mixin/core/DrawContextAccessor.java create mode 100644 src/main/resources/META-INF/accesstransformer.cfg create mode 100644 versions/1.21.5-fabric/gradle.properties create mode 100644 versions/1.21.5-neoforge/gradle.properties create mode 100644 versions/1.21.6-fabric/gradle.properties create mode 100644 versions/1.21.6-neoforge/gradle.properties diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c44455092..755175316 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -44,7 +44,6 @@ body: Please send the corresponding Minecraft log from the `logs` folder here. Please upload the log file as an attachment, or upload the log to [mclo.gs](https://mclo.gs/) and paste the url here - mclo.gs sanitizes sensitive information such as ip addresses. Please refrain from pasting the entire log file directly. - Leave empty if there is none. placeholder: https://mclo.gs/ - type: input id: versions @@ -93,5 +92,5 @@ body: required: true - label: I have provided all the necessary information to reproduce the issue. required: true - - label: I have verified that the issue does not occur without the AutoModpack - Ignore you are reporting a mod conflict issue. + - label: I have verified that the issue does not occur without the AutoModpack - Ignore if you are reporting a mod conflict issue. required: false diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b2a39e938..73ab596fc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,12 +12,6 @@ on: type: string required: false default: '' -# # [FEATURE] MIXIN_AUDITOR -# mixin_audit: -# description: run mixin audit for Minecraft server after build -# type: boolean -# required: false -# default: false jobs: build: @@ -48,8 +42,7 @@ jobs: if [ -z "${{ inputs.target_subproject }}" ]; then echo "Building all subprojects" ./gradlew clean - ./gradlew chiseledBuild -x mergeJars - ./gradlew mergeJars + ./gradlew build else args=$(echo "${{ inputs.target_subproject }}" | tr ',' '\n' | sed 's/$/:build/' | paste -sd ' ') echo "Building with arguments=$args" @@ -59,52 +52,8 @@ jobs: BUILD_ID: ${{ github.run_number }} BUILD_RELEASE: ${{ inputs.release }} - # # [FEATURE] MIXIN_AUDITOR - # - name: Run mixin audit check for Minecraft server - # if: ${{ inputs.mixin_audit }} - # timeout-minutes: 10 - # run: | - # mkdir -p ./run - # echo eula=true > ./run/eula.txt - # ./gradlew runServerMixinAudit - - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: build-artifacts - path: merged - - # # [FEATURE] FALLENS_MAVEN - # - name: Publish with gradle - # if: inputs.release || github.ref == 'refs/heads/dev' - # run: | - # if [ -z "${{ inputs.target_subproject }}" ]; then - # echo "Publishing all subprojects" - # ./gradlew publish - # else - # args=$(echo "${{ inputs.target_subproject }}" | tr ',' '\n' | sed 's/$/:publish/' | paste -sd ' ') - # echo "Publishing with arguments=$args" - # ./gradlew $args - # fi - # env: - # BUILD_RELEASE: ${{ inputs.release }} - # FALLENS_MAVEN_TOKEN: ${{ secrets.FALLENS_MAVEN_TOKEN }} - -# summary: -# runs-on: ubuntu-22.04 -# needs: -# - build -# -# steps: -# - uses: actions/checkout@v4 -# -# - name: Download build artifacts -# uses: actions/download-artifact@v4 -# with: -# name: build-artifacts -# path: build-artifacts -# -# - name: Make build summary -# run: python3 .github/workflows/scripts/summary.py # ubuntu-22.04 uses Python 3.10.6 -# env: -# TARGET_SUBPROJECT: ${{ inputs.target_subproject }} \ No newline at end of file + path: merged \ No newline at end of file diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index bc9ef67e2..0595316a3 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,6 +1,6 @@ name: Dev Builds -on: [workflow_dispatch, pull_request, push] +on: [workflow_dispatch, push] jobs: tests: # runs on linux and windows @@ -8,7 +8,4 @@ jobs: secrets: inherit build: # runs on linux uses: ./.github/workflows/build.yml - secrets: inherit -# # [FEATURE] MIXIN_AUDITOR -# with: -# mixin_audit: true \ No newline at end of file + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cff308c48..cf483ef71 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -103,25 +103,25 @@ jobs: fi - name: Read common properties - id: properties_common + id: properties_c uses: christian-draeger/read-properties@1.1.1 with: path: gradle.properties properties: 'mod_name mod_version' - name: Read version-specific properties - id: properties_versioned + id: properties_v uses: christian-draeger/read-properties@1.1.1 with: path: ${{ format('versions/{0}/gradle.properties', matrix.subproject) }} - properties: 'minecraft_version game_versions' + properties: 'publish_versions' - name: Fix game version - id: game_versions + id: publish_versions run: | - # Fixed \n in game_versions isn't parsed by christian-draeger/read-properties as a line separator + # Fixed \n in publish_versions isn't parsed by christian-draeger/read-properties as a line separator echo 'value<> $GITHUB_OUTPUT - echo -e "${{ steps.properties_versioned.outputs.game_versions }}" >> $GITHUB_OUTPUT + echo -e "${{ steps.properties_v.outputs.publish_versions }}" >> $GITHUB_OUTPUT echo 'EOF' >> $GITHUB_OUTPUT - name: Prepare file information @@ -166,12 +166,12 @@ jobs: files: ${{ steps.file_info.outputs.path }} - name: ${{ format('{0} {1} {2}', steps.properties_common.outputs.mod_name, steps.properties_common.outputs.mod_version, matrix.mod_brand) }} - version: ${{ steps.properties_common.outputs.mod_version }} + name: ${{ format('{0} {1} {2}', steps.properties_c.outputs.mod_name, steps.properties_c.outputs.mod_version, matrix.mod_brand) }} + version: ${{ steps.properties_c.outputs.mod_version }} version-type: release loaders: ${{ matrix.mod_brand }} - game-versions: ${{ steps.game_versions.outputs.value }} + game-versions: ${{ steps.publish_versions.outputs.value }} game-version-filter: any dependencies: '' # declare the dependencies explicitly, so mc-publish won't try to load from fabric.mod.json diff --git a/.github/workflows/scripts/summary.py b/.github/workflows/scripts/summary.py deleted file mode 100644 index 3da4c2f93..000000000 --- a/.github/workflows/scripts/summary.py +++ /dev/null @@ -1,73 +0,0 @@ -""" -A script to scan through all valid mod jars in build-artifacts.zip/$version/build/libs, -and generate an artifact summary table for that to GitHub action step summary -""" -__author__ = 'Fallen_Breath' - -import functools -import glob -import hashlib -import json -import os - - -def read_prop(file_name: str, key: str) -> str: - with open(file_name) as prop: - return next(filter( - lambda l: l.split('=', 1)[0].strip() == key, - prop.readlines() - )).split('=', 1)[1].lstrip() - - -def get_sha256_hash(file_path: str) -> str: - sha256_hash = hashlib.sha256() - - with open(file_path, 'rb') as f: - for buf in iter(functools.partial(f.read, 4096), b''): - sha256_hash.update(buf) - - return sha256_hash.hexdigest() - - -def main(): - target_subproject_env = os.environ.get('TARGET_SUBPROJECT', '') - target_subprojects = list(filter(None, target_subproject_env.split(',') if target_subproject_env != '' else [])) - print('target_subprojects: {}'.format(target_subprojects)) - - with open('settings.json') as f: - settings: dict = json.load(f) - - with open(os.environ['GITHUB_STEP_SUMMARY'], 'w') as f: - f.write('## Build Artifacts Summary\n\n') - f.write('| Subproject | for Minecraft | File | Size | SHA-256 |\n') - f.write('| --- | --- | --- | --- | --- |\n') - - warnings = [] - for subproject in settings['versions']: - if len(target_subprojects) > 0 and subproject not in target_subprojects: - print('skipping {}'.format(subproject)) - continue - game_versions = read_prop('versions/{}/gradle.properties'.format(subproject), 'game_versions') - game_versions = game_versions.strip().replace('\\n', ', ') - file_paths = glob.glob('build-artifacts/{}/build/libs/*.jar'.format(subproject)) - file_paths = list(filter(lambda fp: not fp.endswith('-sources.jar') and not fp.endswith('-dev.jar') and not fp.endswith('-shadow.jar'), file_paths)) - if len(file_paths) == 0: - file_name = '*not found*' - sha256 = '*N/A*' - else: - file_name = '`{}`'.format(os.path.basename(file_paths[0])) - file_size = '{} B'.format(os.path.getsize(file_paths[0])) - sha256 = '`{}`'.format(get_sha256_hash(file_paths[0])) - if len(file_paths) > 1: - warnings.append('Found too many build files in subproject {}: {}'.format(subproject, ', '.join(file_paths))) - - f.write('| {} | {} | {} | {} | {} |\n'.format(subproject, game_versions, file_name, file_size, sha256)) - - if len(warnings) > 0: - f.write('\n### Warnings\n\n') - for warning in warnings: - f.write('- {}\n'.format(warning)) - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e822e1f87..05b235732 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,7 +4,7 @@ on: [workflow_call] jobs: tests: - runs-on: windows-2019 + runs-on: windows-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 21 diff --git a/.imgbotconfig b/.imgbotconfig deleted file mode 100644 index 1828d9c0b..000000000 --- a/.imgbotconfig +++ /dev/null @@ -1,14 +0,0 @@ -{ - "schedule": "daily", // daily|weekly|monthly -// "ignoredFiles": [ -// "*.jpg", // ignore by extension -// "image1.png", // ignore by filename -// "public/special_images/*", // ignore by folderpath -// ], -// "aggressiveCompression": "true", // true|false -// "compressWiki": "true", // true|false - "minKBReduced": null, // delay new prs until size reduction meets this threshold (default to 10) -// "prTitle" : "Images are optimized!", -// "prBody" : " Text before optimization ratio {optimization_ratio} Text after optimization ratio -// Text before optimization details {optimization_details} Text after optimization details", -} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 83226ad34..91803241c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ If you're a developer, you can contribute to the AutoModpack project by writing 1. Discuss the changes you want to make. By e.g. creating an issue. 2. Fork the repository and create a new branch for your feature or bug fix. 3. Make your code changes. -4. Build code with `./gradlew chiseledBuild` command. +4. Build code with `./gradlew build` command. 5. Test your changes thoroughly to prevent regressions. 6. Submit a pull request, describing your changes and providing relevant context. diff --git a/README.md b/README.md index 0925a4972..ed2c14c85 100644 --- a/README.md +++ b/README.md @@ -40,36 +40,38 @@ This isn't just another mod; it's a game-changer for private servers. Here's why ## 🛠️ How the Magic Happens -AutoModpack works by generating a modpack (**metadata file**) on the server, containing all the files of your modpack. The server then hosts this file and the modpack files. +AutoModpack works by generating a modpack (**metadata file**) on the server, which contains all the files of your modpack. The server then hosts this file and the modpack files. -When a client connects to server (simplified): +When a client connects to the server: -1. AutoModpack securely connects to the modpack host server and fetches the metadata. -2. It uses Modrinth and CurseForge APIs to download directly your modpack's files where possible. -3. All files are downloaded to the client's automodpack folder. -4. Restart the game, AutoModpack loads the modpack and the client is perfectly synced and ready to play! +1. Connection: AutoModpack establishes a secure connection and prompts you to [verify the server's certificate fingerprint](https://moddedmc.wiki/en/project/automodpack/docs/technicals/certificate). +2. Direct links: Fetches the APIs for direct downloads of your modpack's files from Modrinth and CurseForge, where possible (mods, resource packs, shaders). +3. Modpack download: All files are downloaded to the client's automodpack folder. +4. Game restart: AutoModpack loads the modpack, and the client is perfectly synced and ready to play! -On subsequent game boots, AutoModpack checks for updates. If changes are detected, it updates the modpack in the background, no additional restarts required! +On subsequent game launches, AutoModpack checks for updates. If changes are detected, it updates the modpack in the background—no additional restarts are required! ## ⚠️ Security and Trust - Read This! > With great power comes great responsibility. -Because it downloads files directly into your game folder, it's crucial to **only use it on servers you absolutely trust**. A malicious server (administrator) *can* include harmful files. +Be aware that this mod allows remote servers to download *arbitrary executable* files directly into your game folder. It's crucial to **only use it on servers you absolutely trust**. A malicious server (administrator) *can* include malicious/harmful files. While AutoModpack itself tries to be as secure as possible, due to the nature of the internet, the creators and contributors of AutoModpack are not responsible for any harm, damage, loss, or issues that may result from files downloaded from a server you connect to using the mod. **By using AutoModpack, you acknowledge and accept this risk.** -**If you have valuable security insights or concerns, please reach out!** You can contact privately on [Discord](https://discordapp.com/users/464522287618457631) or open an issue on GitHub. +**If you have valuable security insights or concerns, please reach out!** You can contact privately on [Discord](https://discordapp.com/users/464522287618457631) or publicly on [Discord server](https://discord.gg/hS6aMyeA9P) or just open an issue on [GitHub](https://github.com/Skidamek/AutoModpack/issues). ## 🚀 Getting Started is a Breeze! Installing AutoModpack is as simple as installing any other mod. 1. Download the AutoModpack from the releases page on [GitHub](https://github.com/Skidamek/AutoModpack/releases), [CurseForge](https://www.curseforge.com/minecraft/mc-mods/automodpack), or [Modrinth](https://modrinth.com/mod/automodpack). 2. Place the downloaded file into the `/mods/` folder of both your server and client Minecraft installations. +3. Start your server and let AutoModpack generate the initial modpack metadata. +4. Connect to your server with the mod installed on your client. That's typically all you need to do! AutoModpack will automatically create the modpack from your server's mods. -**Want to customize your modpack further?** Add configs, client-side-only mods, and more? **Check out the [wiki](https://github.com/Skidamek/AutoModpack/wiki)!** It *hopefully* has all the details you need to tailor AutoModpack to your specific needs. +**Want to customize your modpack further?** Add configs, client-side-only mods, and more? **Check out the [documentation](https://moddedmc.wiki/en/project/automodpack/docs)!** There's also a start guide covering more stuff. If you encounter any issues or have questions, feel free to join [Discord server](https://discord.gg/hS6aMyeA9P) or open an issue on [GitHub](https://github.com/Skidamek/AutoModpack/issues). Prefer an all-in-one solution? You can also use our [modified Fabric installer](https://github.com/Skidamek/AutoModpack-Installer/releases/tag/Latest) which downloads AutoModpack alongside the Fabric loader. diff --git a/build.fabric.gradle.kts b/build.fabric.gradle.kts new file mode 100644 index 000000000..fbc31398e --- /dev/null +++ b/build.fabric.gradle.kts @@ -0,0 +1,73 @@ +@file:Suppress("UnstableApiUsage") + +plugins { + kotlin("jvm") + id("automodpack.common") + id("fabric-loom") +} + +version = "${property("mod_version")}" +group = "${property("mod.group")}" +base.archivesName.set("${property("mod_name")}-mc${property("deps.minecraft")}-fabric".lowercase()) + +loom { + accessWidenerPath = rootProject.file("src/main/resources/automodpack.accesswidener") +} + +dependencies { + implementation(project(":core")) + implementation(project(":loader-core")) + + minecraft("com.mojang:minecraft:${property("deps.minecraft")}") + mappings(loom.layered { + officialMojangMappings() + if (hasProperty("deps.parchment")) + parchment("org.parchmentmc.data:parchment-${property("deps.parchment")}@zip") + }) + + modImplementation("net.fabricmc:fabric-loader:${property("deps.fabric-loader")}") + + // TODO transitive false + setOf( + "api-base", // Required by modules below + "resource-loader-v0", // Required for translatable texts + "registry-sync-v0", // Required for custom sounds + "networking-api-v1" // Required by registry sync module + ).forEach { + include(modImplementation(fabricApi.module("fabric-$it", property("deps.fabric-api") as String))!!) + } + + if (stonecutter.eval(stonecutter.current.version, "<1.19.2")) { + include(modImplementation(fabricApi.module("fabric-command-api-v1", property("deps.fabric-api") as String))!!) // TODO transitive false + } else { + include(modImplementation(fabricApi.module("fabric-command-api-v2", property("deps.fabric-api") as String))!!) // TODO transitive false + } + + include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${property("deps.mixin-extras")}")!!)!!) +} + +java { + if (stonecutter.eval(stonecutter.current.version, ">=1.20.5")) { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) + } else { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + } + withSourcesJar() +} + +tasks { + processResources { + exclude("**/neoforge.mods.toml", "**/mods.toml", "**/accesstransformer.cfg") + } + + register("buildAndCollect") { + group = "build" + from(remapJar.map { it.archiveFile }) + into(rootProject.layout.buildDirectory.file("libs/${project.property("mod_version")}")) + dependsOn("build") + } +} \ No newline at end of file diff --git a/build.forge.gradle.kts b/build.forge.gradle.kts new file mode 100644 index 000000000..332229a0f --- /dev/null +++ b/build.forge.gradle.kts @@ -0,0 +1,106 @@ +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.SerializationFeature +import com.fasterxml.jackson.databind.node.ObjectNode + +plugins { + kotlin("jvm") + id("automodpack.common") + id("net.neoforged.moddev.legacyforge") +} + +version = "${property("mod_version")}" +group = "${property("mod.group")}" +base.archivesName.set("${property("mod_name")}-mc${property("deps.minecraft")}-forge".lowercase()) + +legacyForge { + version = property("deps.forge") as String + validateAccessTransformers = true + + if (hasProperty("deps.parchment")) parchment { + val (mc, ver) = (property("deps.parchment") as String).split(':') + mappingsVersion = ver + minecraftVersion = mc + } +} + +dependencies { + implementation(project(":core")) + implementation(project(":loader-core")) + + compileOnly("net.fabricmc.fabric-api:fabric-api:0.92.2+1.20.1") + compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:${property("deps.mixin-extras")}")!!) + implementation(jarJar("io.github.llamalad7:mixinextras-forge:${property("deps.mixin-extras")}")!!) + annotationProcessor("org.spongepowered:mixin:0.8.5:processor") // required to generate refmaps +} + +mixin { // Add mixins + add(sourceSets.main.get(), "automodpack-main.mixins.refmap.json") + config("automodpack-main.mixins.json") +} + +tasks.getByName("processResources") { + doLast { // Add refmap to the mixin config + val mixinConfigFile = File(destinationDir, "automodpack-main.mixins.json") + addRefmapToJsonFile(mixinConfigFile, "automodpack-main.mixins.refmap.json") + } +} + +tasks { + jar { // add the mixin config to the jar + manifest { + attributes( + "MixinConfigs" to "automodpack-main.mixins.json" + ) + } + } + + processResources { + exclude("**/fabric.mod.json", "**/automodpack.accesswidener") + } + + named("createMinecraftArtifacts") { + dependsOn("stonecutterGenerate") + } + + register("buildAndCollect") { + group = "build" + from(jar.map { it.archiveFile }) + into(rootProject.layout.buildDirectory.file("libs/${project.property("mod_version")}")) + dependsOn("build") + } +} + +java { + if (stonecutter.eval(stonecutter.current.version, ">=1.20.5")) { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) + } else { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) + } + withSourcesJar() +} + +fun addRefmapToJsonFile(jsonFile: File, refmap: String) { + if (!jsonFile.exists()) { + error("JSON file not found: ${jsonFile.absolutePath}") + } + + val objectMapper = ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT) + try { + val jsonNode = objectMapper.readTree(jsonFile) + if (jsonNode.isObject) { + val objectNode = jsonNode as ObjectNode + objectNode.put("refmap", refmap) + objectMapper.writeValue(jsonFile, objectNode) + println("Added refmap ($refmap) to ${jsonFile.name}") + } else { + error("JSON file ${jsonFile.name} is not a JSON object, couldn't add refmap.") + } + } catch (e: Exception) { + println("Error processing JSON file ${jsonFile.absolutePath}: ${e.message}") + e.printStackTrace() + } +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts deleted file mode 100644 index 351d40fc0..000000000 --- a/build.gradle.kts +++ /dev/null @@ -1,260 +0,0 @@ -import java.util.* - -plugins { - id("dev.architectury.loom") -} - -class ModData { - val id = property("mod_id").toString() - val name = property("mod_name").toString() - val version = property("mod_version").toString() - val group = property("mod_group").toString() - val minecraftDependency = property("minecraft_dependency").toString() - val description = property("mod_description").toString() -} - -class LoaderData { - private val name = loom.platform.get().name.lowercase() - val isFabric = name == "fabric" - val isForge = name == "forge" - val isNeoForge = name == "neoforge" - - fun getVersion() : String? { - return if (isForge) { - property("loader_forge")?.toString() - } else if (isNeoForge) { - property("loader_neoforge")?.toString() - } else if (isFabric) { - property("loader_fabric")?.toString() - } else { - null - } - } - - override fun toString(): String { - return name - } -} - -class MinecraftVersionData { - private val name = stonecutter.current.version.substringBeforeLast("-") - val needsJava21 = greaterOrEqual("1.20.5") - - fun greaterThan(other: String) : Boolean { - return stonecutter.compare(name, other.lowercase()) > 0 - } - - fun lessThan(other: String) : Boolean { - return stonecutter.compare(name, other.lowercase()) < 0 - } - - fun greaterOrEqual(other: String) : Boolean { - return stonecutter.compare(name, other.lowercase()) >= 0 - } - - fun lessOrEqual(other: String) : Boolean { - return stonecutter.compare(name, other.lowercase()) <= 0 - } - - override fun equals(other: Any?) : Boolean { - return name == other - } - - override fun toString(): String { - return name - } - - override fun hashCode(): Int { - var result = name.hashCode() - result = 31 * result + needsJava21.hashCode() - return result - } -} - -val mod = ModData() -val loader = LoaderData() -val minecraftVersion = MinecraftVersionData() - - -version = mod.version -group = mod.group -base.archivesName.set("${mod.name}-mc$minecraftVersion-$loader".lowercase(Locale.getDefault())) - -repositories { - mavenCentral() - mavenLocal() - maven { url = uri("https://api.modrinth.com/maven") } - maven { url = uri("https://maven.neoforged.net/releases") } - maven { url = uri("https://files.minecraftforge.net/maven/") } - maven { url = uri("https://libraries.minecraft.net/") } -} - -dependencies { - // just for IDE not complaining (its already included in the shadow jar of core-${mod_brand}) - // + needed for runtime in dev env - implementation(project(":core")) - implementation(project(":loader-core")) - - testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.2") - - // TODO fix dev env launch - - minecraft("com.mojang:minecraft:$minecraftVersion") - - // Mappings have to be patched for new neoforge - if (loader.isNeoForge && minecraftVersion.equals("1.20.6")) { - mappings( - loom.layered { - mappings("net.fabricmc:yarn:${property("yarn_mappings")}:v2") - mappings("dev.architectury:yarn-mappings-patch-neoforge:1.20.6+build.4") - } - ) - } else if (loader.isNeoForge && minecraftVersion.greaterOrEqual("1.21")) { - mappings( - loom.layered { - mappings("net.fabricmc:yarn:${property("yarn_mappings")}:v2") - mappings("dev.architectury:yarn-mappings-patch-neoforge:1.21+build.4") - } - ) - } else { - mappings("net.fabricmc:yarn:${property("yarn_mappings")}:v2") - } - - if (loader.isFabric) { - setOf( - "fabric-api-base", // Required by modules below - "fabric-resource-loader-v0", // Required for translatable texts - "fabric-registry-sync-v0", // Required for custom sounds - "fabric-networking-api-v1" // Required by registry sync module - ).forEach { - include(modImplementation(fabricApi.module(it, property("fabric_version") as String))!!) // TODO transitive false - } - if (minecraftVersion.lessThan("1.19.2")) { - include(modImplementation(fabricApi.module("fabric-command-api-v1", property("fabric_version") as String))!!) // TODO transitive false - } else { - include(modImplementation(fabricApi.module("fabric-command-api-v2", property("fabric_version") as String))!!) // TODO transitive false - } - - // JiJ lastest version of mixin extras so all mods work (workaround) - remove when we detect such incompatibilities and copy the jij mod to the mods folder, currently the stable loader version would be loaded instead of the lastest required by some mods - include(implementation(annotationProcessor("io.github.llamalad7:mixinextras-fabric:${property("mixin_extras")}")!!)!!) - } - - if (loader.isFabric) { - modImplementation("net.fabricmc:fabric-loader:${loader.getVersion()}") - } else if (loader.isForge) { - "forge"("net.minecraftforge:forge:$minecraftVersion-${loader.getVersion()}") - - // For pseudo mixin (compat with Forgified Fabric API) - compileOnly(fabricApi.module("fabric-networking-api-v1", "0.92.2+1.20.1")) // version is not important - - implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:${property("mixin_extras")}")!!) - implementation(include("io.github.llamalad7:mixinextras-forge:${property("mixin_extras")}")!!) - } else if (loader.isNeoForge) { - - // For pseudo mixin (compat with Forgified Fabric API) - compileOnly(fabricApi.module("fabric-networking-api-v1", "0.92.2+1.20.1")) // version is not important - - "neoForge"("net.neoforged:neoforge:${loader.getVersion()}") - - // Bundle mixin extras to 1.20.2 since it has too old version of it - if (minecraftVersion.equals("1.20.2")) { - implementation(include("io.github.llamalad7:mixinextras-neoforge:${property("mixin_extras")}")!!) - } - } -} - -loom { - runConfigs["client"].apply { - ideConfigGenerated(true) - vmArgs("-Dmixin.debug.export=true") - runDir = "../../run" - } - - runConfigs["server"].apply { - ideConfigGenerated(true) - vmArgs("-Dmixin.debug.export=true") - runDir = "../../run" - } - - if (loader.isForge) { - forge { - convertAccessWideners = true - mixinConfigs = listOf("automodpack-main.mixins.json") - } - } - - accessWidenerPath = file("../../src/main/resources/automodpack.accesswidener") -} - -if (stonecutter.current.isActive) { - rootProject.tasks.register("buildActive") { - group = "project" - dependsOn(tasks.named("build")) - finalizedBy("mergeJars") - } -} - -tasks.processResources { - val map = mapOf( - "id" to mod.id, - "name" to mod.name, - "version" to mod.version, - "minecraft_dependency" to mod.minecraftDependency, - "description" to mod.description - ) - - inputs.properties(map) - - if (loader.isFabric) { - exclude("META-INF/neoforge.mods.toml") - exclude("META-INF/mods.toml") - filesMatching("fabric.mod.json") { - expand(map) - } - } else if (loader.isNeoForge) { - exclude("fabric.mod.json") - exclude("META-INF/mods.toml") - filesMatching("META-INF/neoforge.mods.toml") { - expand(map) - } - } else if (loader.isForge) { - exclude("fabric.mod.json") - exclude("META-INF/neoforge-mods.toml") - filesMatching("META-INF/mods.toml") { - expand(map) - } - } - - if (loader.isForge || loader.isNeoForge) { - filesMatching("assets/automodpack/icon.png") { - path = "icon.png" - } - } - - duplicatesStrategy = DuplicatesStrategy.EXCLUDE - from("../../src/main/resources") { - include("META-INF/services/**") - } -} - -java { - if (minecraftVersion.needsJava21) { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 - } else { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - withSourcesJar() -} - -tasks.withType { - options.encoding = "UTF-8" -} - -tasks.named("jar") { - from(rootProject.file("LICENSE")) { - rename { "${it}_${mod.id}" } - } -} \ No newline at end of file diff --git a/build.neoforge.gradle.kts b/build.neoforge.gradle.kts new file mode 100644 index 000000000..7e1bba8fd --- /dev/null +++ b/build.neoforge.gradle.kts @@ -0,0 +1,51 @@ +plugins { + kotlin("jvm") + id("automodpack.common") + id("net.neoforged.moddev") +} + +version = "${property("mod_version")}" +group = "${property("mod.group")}" +base.archivesName.set("${property("mod_name")}-mc${property("deps.minecraft")}-neoforge".lowercase()) + +neoForge { + version = property("deps.neoforge") as String + validateAccessTransformers = true + + if (hasProperty("deps.parchment")) parchment { + val (mc, ver) = (property("deps.parchment") as String).split(':') + mappingsVersion = ver + minecraftVersion = mc + } +} + +dependencies { + implementation(project(":core")) + implementation(project(":loader-core")) + + compileOnly("net.fabricmc.fabric-api:fabric-api:0.92.2+1.20.1") +} + +tasks { + processResources { + exclude("**/fabric.mod.json", "**/automodpack.accesswidener", "**/forge.mods.toml") + } + + named("createMinecraftArtifacts") { + dependsOn("stonecutterGenerate") + } + + register("buildAndCollect") { + group = "build" + from(jar.map { it.archiveFile }) + into(rootProject.layout.buildDirectory.file("libs/${project.property("mod_version")}")) + dependsOn("build") + } +} + +java { + withSourcesJar() + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) +} \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 000000000..6083ada0a --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,13 @@ +plugins { + `kotlin-dsl` + kotlin("jvm") version "2.1.21" +} + +repositories { + mavenCentral() + gradlePluginPortal() +} + +dependencies { + implementation("com.fasterxml.jackson.core:jackson-databind:2.19.1") // For JSON parsing e.g. in build.forge.gradle.kts +} \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/automodpack.common.gradle.kts b/buildSrc/src/main/kotlin/automodpack.common.gradle.kts new file mode 100644 index 000000000..774da674e --- /dev/null +++ b/buildSrc/src/main/kotlin/automodpack.common.gradle.kts @@ -0,0 +1,247 @@ +import java.io.FileInputStream +import java.io.FileOutputStream +import java.util.zip.ZipEntry +import java.util.zip.ZipInputStream +import java.util.zip.ZipOutputStream + +plugins { + idea +} + +idea { + module { + isDownloadJavadoc = true + isDownloadSources = true + } +} + +repositories { + fun strictMaven(url: String, vararg groups: String) = exclusiveContent { + forRepository { maven(url) } + filter { groups.forEach(::includeGroup) } + } + strictMaven("https://maven.parchmentmc.org", "org.parchmentmc.data") + maven("https://maven.fabricmc.net/") +} + +tasks.named("processResources") { + fun prop(name: String) = project.property(name) as String + + val props = HashMap().apply { + this["version"] = prop("mod_version") + this["minecraft"] = prop("meta.minecraft") + this["id"] = prop("mod.id") + this["name"] = prop("mod_name") + this["description"] = prop("mod.description") + } + + filesMatching(listOf("pack.mcmeta", "fabric.mod.json", "META-INF/neoforge.mods.toml", "META-INF/mods.toml")) { + expand(props) + } +} + +tasks.named("build") { + // We need to build the loader modules first, so that we can merge the jars later + dependsOn(":core:build", ":loader-core:build") + when { + project.name.contains("fabric") -> { + dependsOn(":loader-fabric-core:build", ":loader-fabric-15:build", ":loader-fabric-16:build") + } + project.name.contains("neoforge") -> { + dependsOn(":loader-neoforge-fml2:build", ":loader-neoforge-fml4:build") + } + project.name.contains("forge") -> { + dependsOn(":loader-forge-fml40:build", ":loader-forge-fml47:build") + } + } + + finalizedBy(tasks.named("mergeJar")) +} + +val mergedDir = File("${rootProject.projectDir}/merged") + +tasks.named("clean") { + finalizedBy("cleanMerged") +} + +tasks.register("cleanMerged") { + doLast { + mergedDir.deleteRecursively() + } +} + +// TODO make it faster +// If something goes wrong, try to run the "clean" task +tasks.register("mergeJar") { + doLast { + mergedDir.mkdirs() + val buildDirLibs = project.layout.buildDirectory.dir("libs").get().asFile + val jarToMerge = buildDirLibs.listFiles() + ?.firstOrNull { file -> file.isFile && !file.name.endsWith("-sources.jar") && file.name.endsWith(".jar") } + ?: error("No jar found to merge in build/libs directory! ${buildDirLibs.absolutePath}") + + val time = System.currentTimeMillis() + println("Found $jarToMerge to merge. Merging...") + + val minecraftVersionStr = jarToMerge.name.substringAfterLast("-mc").substringBefore("-") + if (minecraftVersionStr.isEmpty()) { + error("Could not identify Minecraft version in the jar name: ${jarToMerge.name}") + } + + var loaderModule = "" + if (jarToMerge.name.contains("fabric")) { + loaderModule = "fabric-core" + } else if (jarToMerge.name.contains("neoforge")) { + loaderModule = when (minecraftVersionStr) { + "1.20.6", "1.20.4", "1.20.1", "1.19.4", "1.19.2", "1.18.2" -> "neoforge-fml2" + else -> "neoforge-fml4" + } + } else if (jarToMerge.name.contains("forge")) { + loaderModule = if (minecraftVersionStr == "1.18.2") { + "forge-fml40" + } else { + "forge-fml47" + } + } + + val loaderModuleProject = rootProject.findProject("loader-$loaderModule") + ?: error("Loader module '$loaderModule' not found in the project.") + + val loaderFile = loaderModuleProject.layout.buildDirectory.dir("libs").get().asFile.listFiles() + ?.single { it.isFile && !it.name.endsWith("-sources.jar") && it.name.endsWith(".jar") } + ?: error("No loader jar found in loader/$loaderModule/build/libs directory! Make sure to build the loader module first.") + + val finalJar = File("$mergedDir/${jarToMerge.name}") + loaderFile.copyTo(finalJar, overwrite = true) + appendFileToZip(finalJar, jarToMerge, "automodpack-mod.jar") + + println("Merged: ${jarToMerge.name} into: ${finalJar.name} from: ${loaderFile.name} Took: ${System.currentTimeMillis() - time}ms") + } +} + +fun appendFileToZip(zipFile: File, fileToAppend: File, entryName: String) { + val entries = ZipInputStream(FileInputStream(zipFile)).use { zipStream -> + generateSequence { zipStream.nextEntry } + .toList() + } + + val graph = mutableMapOf>() + + entries.forEach { entry -> + val children = entry.name.split("/") + var currentParent = "" + children.forEach { child -> + if (child.isNotEmpty()) { + currentParent = "$currentParent$child/" + val parent = graph.getOrPut(currentParent) { mutableListOf() } + parent.add(child) + } + } + } + +// graph.forEach { (parent, children) -> +// println("$parent -> $children") +// } + + val filteredGraph = filterEntries(entries, graph, zipFile) + + // Doing with temp file since for some reason just adding the file breaks the zip/jar file + val tempFile = File("$zipFile.temp") + tempFile.createNewFile() + + ZipOutputStream(FileOutputStream(tempFile)).use { zipStream -> + ZipInputStream(FileInputStream(zipFile)).use { existingZipStream -> + while (true) { + val entry = existingZipStream.nextEntry ?: break + if (filteredGraph.containsKey("${entry.name}/")) { + try { + val zipEntry = ZipEntry(entry.name) + zipStream.putNextEntry(zipEntry) + existingZipStream.copyTo(zipStream) + zipStream.closeEntry() + } catch (_: Exception) { + println("Error while copying entry: ${entry.name}") + } + } + } + } + + // Add the new entry + zipStream.putNextEntry(ZipEntry(entryName)) + FileInputStream(fileToAppend).use { fileInputStream -> + fileInputStream.copyTo(zipStream) + } + zipStream.closeEntry() + } + + // Replace the original zip file with the one containing the new entry + zipFile.delete() + tempFile.renameTo(zipFile) +} + +val dupesDir = File("${rootProject.projectDir}/dupes") + +fun filterEntries(entries: List, graph: Map>, zipFile: File): Map> { + + val emptyDirs = mutableSetOf() + + // find empty directories + graph.forEach { (parent, children) -> + if (children.size == 0) { + emptyDirs.add(parent) + } + } + + // dump duplicate entries + dupesDir.deleteRecursively() + dupesDir.mkdirs() + + dumpDupeEntries(zipFile, entries) + + // filter empty directories + // filter single duplicate files (leave only one) + val dupes = mutableSetOf() + + val filteredGraph = graph.filter { (parent, children) -> + if (emptyDirs.contains(parent)) { + println("Filtering empty dir: $parent -> $children") + return@filter false + } + + val count = graph.count { parent == it.key } + if (count > 1 && !dupes.add(children[0])) { + return@filter false + } + + return@filter true + } + + return filteredGraph +} + +fun dumpDupeEntries(zipFile: File, entries: List) { + // check for duplicates + val entryNames = mutableSetOf() + entries.forEach { duplicate -> + if (!entryNames.add(duplicate.name)) { + println("Duplicate entry: $duplicate") + + // write the entry to the file + ZipInputStream(FileInputStream(zipFile)).use { zipStream -> + var i = 0 + generateSequence { zipStream.nextEntry } + .filter { it.name == duplicate.name } + .forEach { _ -> + i++ + val dupeFile = File("$dupesDir/$i-$duplicate.dupe") + println("Extracting to: $dupeFile") + dupeFile.parentFile.mkdirs() + dupeFile.createNewFile() + FileOutputStream(dupeFile).use { fileOutputStream -> + zipStream.copyTo(fileOutputStream) + } + } + } + } + } +} diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 965cd2955..ce131a635 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -2,13 +2,13 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") } base { - archivesName = property("mod_id") as String + "-" + project.name + archivesName = property("mod.id") as String + "-" + project.name version = property("mod_version") as String - group = property("mod_group") as String + group = property("mod.group") as String } repositories { @@ -16,13 +16,13 @@ repositories { } dependencies { - implementation("org.apache.logging.log4j:log4j-core:2.20.0") + implementation("org.apache.logging.log4j:log4j-core:2.19.0") implementation("com.google.code.gson:gson:2.10.1") - implementation("io.netty:netty-all:4.1.118.Final") + compileOnly("io.netty:netty-all:4.1.118.Final") implementation("org.bouncycastle:bcpkix-jdk18on:1.80") implementation("com.github.luben:zstd-jni:1.5.7-3") implementation("org.tomlj:tomlj:1.1.1") - implementation("org.apache.httpcomponents.client5:httpclient5:5.4.4") + implementation("org.apache.httpcomponents.client5:httpclient5:5.5") testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.2") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.9.2") } @@ -31,7 +31,7 @@ java { // leave it on java 17 to be compatible with older versions and we dont really need 21 there anyway sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 - + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) withSourcesJar() } diff --git a/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java b/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java index 24c7bcc0c..4b4df2ef8 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java +++ b/core/src/main/java/pl/skidam/automodpack_core/GlobalVariables.java @@ -29,7 +29,7 @@ public class GlobalVariables { public static Modpack modpack; public static FullServerPack fullpacks; public static NettyServer hostServer; - public static Jsons.ServerConfigFields serverConfig; + public static Jsons.ServerConfigFieldsV2 serverConfig; public static Jsons.ClientConfigFieldsV2 clientConfig; public static Jsons.KnownHostsFields knownHosts; public static final Path automodpackDir = Path.of("automodpack"); diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index fb7cbf9ac..763e8d7cd 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -3,10 +3,7 @@ import pl.skidam.automodpack_core.config.ConfigTools; import pl.skidam.automodpack_core.config.Jsons; import pl.skidam.automodpack_core.modpack.ModpackExecutor; -import pl.skidam.automodpack_core.modpack.FullServerPack; -import pl.skidam.automodpack_core.modpack.Modpack; import pl.skidam.automodpack_core.modpack.ModpackContent; -import pl.skidam.automodpack_core.modpack.FullServerPackContent; import pl.skidam.automodpack_core.protocol.netty.NettyServer; import java.nio.file.Path; @@ -38,14 +35,13 @@ public static void main(String[] args) { serverConfigFile = modpackDir.resolve("automodpack-server.json"); serverCoreConfigFile = modpackDir.resolve("automodpack-core.json"); - serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFields.class); + serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV2.class); if (serverConfig != null) { serverConfig.syncedFiles = new ArrayList<>(); - serverConfig.hostModpackOnMinecraftPort = false; serverConfig.validateSecrets = false; ConfigTools.save(serverConfigFile, serverConfig); - if (serverConfig.hostPort == -1) { + if (serverConfig.bindPort == -1) { LOGGER.error("Host port not set in config!"); return; } @@ -64,7 +60,7 @@ public static void main(String[] args) { mainModpackDir.toFile().mkdirs(); ModpackExecutor modpackExecutor = new ModpackExecutor(); - ModpackContent modpackContent = new ModpackContent(serverConfig.modpackName, null, mainModpackDir, serverConfig.syncedFiles, serverConfig.allowEditsInFiles, modpackExecutor.getExecutor()); + ModpackContent modpackContent = new ModpackContent(serverConfig.modpackName, null, mainModpackDir, serverConfig.syncedFiles, serverConfig.allowEditsInFiles, serverConfig.forceCopyFilesToStandardLocation, modpackExecutor.getExecutor()); boolean generated = modpackExecutor.generateNew(modpackContent); if (generated) { @@ -72,24 +68,10 @@ public static void main(String[] args) { } else { LOGGER.error("Failed to generate modpack!"); } - LOGGER.info("Start FullServerPack generation!"); modpackExecutor.stop(); - FullServerPack fullserverpack = new FullServerPack(); - FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, hostContentModpackDir, fullserverpack.CREATION_EXECUTOR); - boolean fullpackgenerated = fullserverpack.generateNew(fullServerPackContent); - - - if (fullpackgenerated) { - LOGGER.info("FullServerPack generated!"); - } else { - LOGGER.error("Failed to generate serverpack!"); - } - - modpack.shutdownExecutor(); - fullserverpack.shutdownExecutor(); - LOGGER.info("Starting server on port {}", serverConfig.hostPort); + LOGGER.info("Starting server on port {}", serverConfig.bindPort); server.start(); // wait for server to stop while (server.isRunning()) { diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java b/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java index 8fa495954..0aae21193 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/ConfigTools.java @@ -27,7 +27,6 @@ public class ConfigTools { public static Gson GSON = new GsonBuilder() - .serializeNulls() .disableHtmlEscaping() .setPrettyPrinting() .registerTypeAdapter(InetSocketAddress.class, new InetSocketAddressTypeAdapter()) @@ -57,27 +56,13 @@ public static T getConfigObject(Class configClass) { } // Config stuff - public static T loadCheck(Path configFile, Class configClass) { + public static T softLoad(Path configFile, Class configClass) { try { if (Files.isRegularFile(configFile)) { String json = Files.readString(configFile); - T obj = GSON.fromJson(json, configClass); - if (obj == null) { - LOGGER.error("Parsed object is null. Possible JSON syntax error in file: " + configFile); - return null; - } - - return obj; + return GSON.fromJson(json, configClass); } - } catch (JsonSyntaxException e) { - LOGGER.error("JSON syntax error while loading config! {} {}", configClass, e.getMessage()); - LOGGER.error("This error most often happens when you e.g. forget to put a comma between fields in JSON file. Check the file: " + configFile.toAbsolutePath().normalize()); - return null; - } catch (Exception e) { - LOGGER.error("Couldn't load config! " + configClass); - e.printStackTrace(); - } - + } catch (Exception ignored) { } return null; } diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java index 6d89e047b..d2123e17c 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java @@ -33,6 +33,7 @@ public static class ClientConfigFieldsV2 { public static class ModpackAddresses { public InetSocketAddress hostAddress; // modpack host address public InetSocketAddress serverAddress; // minecraft server address + public boolean requiresMagic; // if true, client will use magic packets to connect to the modpack host public ModpackAddresses() { // Default constructor for Gson @@ -45,9 +46,10 @@ public ModpackAddresses() { * @param serverAddress minecraft server address that represents the target address * which client uses to connect. This value CANNOT be manipulated by the server. */ - public ModpackAddresses(InetSocketAddress hostAddress, InetSocketAddress serverAddress) { + public ModpackAddresses(InetSocketAddress hostAddress, InetSocketAddress serverAddress, boolean requiresMagic) { this.hostAddress = hostAddress; this.serverAddress = serverAddress; + this.requiresMagic = requiresMagic; } public boolean isAnyEmpty() { @@ -55,24 +57,20 @@ public boolean isAnyEmpty() { } } - public static class ServerConfigFields { + public static class ServerConfigFieldsV1 { public int DO_NOT_CHANGE_IT = 1; // file version public String modpackName = ""; public boolean modpackHost = true; public boolean generateModpackOnStart = true; - public List syncedFiles = List.of("/mods/*.jar", "!/mods/iDontWantThisModInModpack.jar", "!/config/andThisConfigToo.json", "!/mods/andAllTheseMods-*.jar", "!/mods/server-*.jar"); - public List allowEditsInFiles = List.of("/options.txt", "/config/*", "!/config/excludeThisFile"); + public List syncedFiles = List.of("/mods/*.jar", "/kubejs/**", "!/kubejs/server_scripts/**", "/emotes/*"); + public List allowEditsInFiles = List.of("/options.txt", "/config/**"); public boolean autoExcludeUnnecessaryFiles = true; -// public List forceLoad = List.of("/resourcepacks/someResourcePack.zip", "/shaderpacks/someShaderPack.zip"); -// public List> forceLoad = new ArrayList<>(); public boolean requireAutoModpackOnClient = true; public boolean nagUnModdedClients = true; public String nagMessage = "This server provides dedicated modpack through AutoModpack!"; public String nagClickableMessage = "Click here to get the AutoModpack!"; public String nagClickableLink = "https://modrinth.com/project/automodpack"; public boolean autoExcludeServerSideMods = true; -// public boolean velocityMode = false; compat plugin... someday I hope -// public boolean forceToDisableAllOtherModsOnClients = false; public boolean hostModpackOnMinecraftPort = true; public String hostIp = ""; public String hostLocalIp = ""; @@ -86,8 +84,36 @@ public static class ServerConfigFields { public List acceptedLoaders; } + public static class ServerConfigFieldsV2 { + public int DO_NOT_CHANGE_IT = 2; // file version + public String modpackName = ""; + public boolean modpackHost = true; + public boolean generateModpackOnStart = true; + public List syncedFiles = List.of("/mods/*.jar", "/kubejs/**", "!/kubejs/server_scripts/**", "/emotes/*"); + public List allowEditsInFiles = List.of("/options.txt", "/config/**"); + public List forceCopyFilesToStandardLocation = List.of(); + public boolean autoExcludeServerSideMods = true; + public boolean autoExcludeUnnecessaryFiles = true; + public boolean requireAutoModpackOnClient = true; + public boolean nagUnModdedClients = true; + public String nagMessage = "This server provides dedicated modpack through AutoModpack!"; + public String nagClickableMessage = "Click here to get the AutoModpack!"; + public String nagClickableLink = "https://modrinth.com/project/automodpack"; + public String bindAddress = ""; + public int bindPort = -1; + public String addressToSend = ""; + public int portToSend = -1; + public boolean disableInternalTLS = false; + public boolean updateIpsOnEveryStart = false; + public int bandwidthLimit = 0; + public boolean validateSecrets = true; + public long secretLifetime = 336; // 336 hours = 14 days + public boolean selfUpdater = false; + public List acceptedLoaders; + } + public static class ServerCoreConfigFields { - public String automodpackVersion = "4.0.0-beta35"; // TODO: dont hardcode it + public String automodpackVersion = "4.0.0-beta37"; // TODO: dont hardcode it public String loader = "fabric"; public String loaderVersion = "0.16.14"; public String mcVersion = "1.21.1"; @@ -122,14 +148,16 @@ public static class ModpackContentItem { public String size; public String type; public boolean editable; + public boolean forceCopy; public String sha1; public String murmur; - public ModpackContentItem(String file, String size, String type, boolean editable, String sha1, String murmur) { + public ModpackContentItem(String file, String size, String type, boolean editable, boolean forceCopy, String sha1, String murmur) { this.file = file; this.size = size; this.type = type; this.editable = editable; + this.forceCopy = forceCopy; this.sha1 = sha1; this.murmur = murmur; } diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java index 350ebeeed..2bcc22c8c 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/ModpackContent.java @@ -20,11 +20,12 @@ public class ModpackContent { private final String MODPACK_NAME; private final WildCards SYNCED_FILES_CARDS; private final WildCards EDITABLE_CARDS; + private final WildCards FORCE_COPY_FILES_TO_STANDARD_LOCATION; private final Path MODPACK_DIR; private final ThreadPoolExecutor CREATION_EXECUTOR; private final Map sha1MurmurMapPreviousContent = new HashMap<>(); - public ModpackContent(String modpackName, Path cwd, Path modpackDir, List syncedFiles, List allowEditsInFiles, ThreadPoolExecutor CREATION_EXECUTOR) { + public ModpackContent(String modpackName, Path cwd, Path modpackDir, List syncedFiles, List allowEditsInFiles, List forceCopyFilesToStandardLocation, ThreadPoolExecutor CREATION_EXECUTOR) { this.MODPACK_NAME = modpackName; this.MODPACK_DIR = modpackDir; Set directoriesToSearch = new HashSet<>(2); @@ -36,6 +37,7 @@ public ModpackContent(String modpackName, Path cwd, Path modpackDir, List start() { } try { - if (!Files.exists(serverCertFile) || !Files.exists(serverPrivateKeyFile)) { - // Create a self-signed certificate - KeyPair keyPair = NetUtils.generateKeyPair(); - X509Certificate cert = NetUtils.selfSign(keyPair); - - // save it to the file - NetUtils.saveCertificate(cert, serverCertFile); - NetUtils.savePrivateKey(keyPair.getPrivate(), serverPrivateKeyFile); - } + if (serverConfig.disableInternalTLS && serverConfig.bindPort != -1) { + LOGGER.warn("Internal TLS is disabled. Clients will not be able to connect directly; you must use e.g. a reverse proxy with TLS."); + } else { + if (serverConfig.disableInternalTLS) { + LOGGER.error("Internal TLS cannot be disabled. You have to bind modpack host on a separate port, preferably also on a loopback address or atleast some private one."); + } - X509Certificate cert = NetUtils.loadCertificate(serverCertFile); + if (!Files.exists(serverCertFile) || !Files.exists(serverPrivateKeyFile)) { + // Create a self-signed certificate + KeyPair keyPair = NetUtils.generateKeyPair(); + X509Certificate cert = NetUtils.selfSign(keyPair); - if (cert == null) { - throw new IllegalStateException("Server certificate couldn't be loaded"); - } + // save it to the file + NetUtils.saveCertificate(cert, serverCertFile); + NetUtils.savePrivateKey(keyPair.getPrivate(), serverPrivateKeyFile); + } - // Shiny TLS 1.3 - sslCtx = SslContextBuilder.forServer(serverCertFile.toFile(), serverPrivateKeyFile.toFile()) - .sslProvider(SslProvider.JDK) - .protocols("TLSv1.3") - .ciphers(Arrays.asList( - "TLS_AES_128_GCM_SHA256", - "TLS_AES_256_GCM_SHA384", - "TLS_CHACHA20_POLY1305_SHA256")) - .build(); + X509Certificate cert = NetUtils.loadCertificate(serverCertFile); - // generate sha256 from cert as a fingerprint - certificateFingerprint = NetUtils.getFingerprint(cert); - LOGGER.warn("Certificate fingerprint for client validation: {}", certificateFingerprint); + if (cert == null) { + throw new IllegalStateException("Server certificate couldn't be loaded"); + } + + // Shiny TLS 1.3 + sslCtx = SslContextBuilder.forServer(serverCertFile.toFile(), serverPrivateKeyFile.toFile()) + .sslProvider(SslProvider.JDK) + .protocols("TLSv1.3") + .ciphers(Arrays.asList( + "TLS_AES_128_GCM_SHA256", + "TLS_AES_256_GCM_SHA384", + "TLS_CHACHA20_POLY1305_SHA256")) + .build(); + + // generate sha256 from cert as a fingerprint + certificateFingerprint = NetUtils.getFingerprint(cert); + if (certificateFingerprint != null) { + LOGGER.warn("Certificate fingerprint: {}", certificateFingerprint); + } + } if (!canStart()) { new TrafficShaper(null); return Optional.empty(); } - int port = serverConfig.hostPort; - InetSocketAddress bindAddress = new InetSocketAddress("0.0.0.0", port); + String address = serverConfig.bindAddress; + int port = serverConfig.bindPort; + InetSocketAddress bindAddress = null; + if (port != -1) { + if (address == null || address.isBlank()) { + bindAddress = new InetSocketAddress(port); + } else { + bindAddress = new InetSocketAddress(address, port); + } + } + LOGGER.info("Starting modpack host server on {}", bindAddress); Class socketChannelClass; @@ -157,14 +176,13 @@ public boolean shouldHost() { // Returns true if stopped successfully public boolean stop() { try { - if (serverChannel == null) { - if (shouldHost) { - shouldHost = false; - } - } else { + if (serverChannel != null) { serverChannel.channel().close().sync(); + serverChannel = null; } + shouldHost = false; + TrafficShaper.close(); if (eventLoopGroup != null) { @@ -200,35 +218,29 @@ private boolean canStart() { return false; } - if (serverConfig.hostModpackOnMinecraftPort) { - shouldHost = true; - LOGGER.info("Hosting modpack on Minecraft port"); - return false; - } - - if (serverConfig.updateIpsOnEveryStart || (serverConfig.hostIp == null || serverConfig.hostIp.isEmpty())) { + if (serverConfig.updateIpsOnEveryStart) { String publicIp = AddressHelpers.getPublicIp(); if (publicIp != null) { - serverConfig.hostIp = publicIp; - ConfigTools.save(serverConfigFile, serverConfig); - LOGGER.warn("Setting Host IP to {}", serverConfig.hostIp); + serverConfig.addressToSend = publicIp; + LOGGER.warn("Setting Host IP to {}", serverConfig.addressToSend); } else { - LOGGER.error("Host IP isn't set in config, please change it manually! Couldn't get public IP"); - return false; + LOGGER.error("Couldn't get public IP, please change it manually! "); } - } - if (serverConfig.updateIpsOnEveryStart || (serverConfig.hostLocalIp == null || serverConfig.hostLocalIp.isEmpty())) { try { - serverConfig.hostLocalIp = AddressHelpers.getLocalIp(); ConfigTools.save(serverConfigFile, serverConfig); - LOGGER.warn("Setting Host local IP to {}", serverConfig.hostLocalIp); } catch (Exception e) { e.printStackTrace(); } } - shouldHost = true; - return true; + shouldHost = true; // At this point we know that we want to host the modpack + + if (serverConfig.bindPort == -1) { + LOGGER.info("Hosting modpack on Minecraft port"); + return false; // Dont start separate server for modpack hosting, use minecraft port instead + } else { + return true; // Start separate server for modpack hosting + } } } diff --git a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ErrorPrinter.java b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ErrorPrinter.java index f0276aa4b..5f2da1aa0 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ErrorPrinter.java +++ b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ErrorPrinter.java @@ -3,6 +3,7 @@ import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.DecoderException; +import io.netty.handler.ssl.NotSslRecordException; import javax.net.ssl.SSLHandshakeException; @@ -15,7 +16,7 @@ public class ErrorPrinter extends ChannelDuplexHandler { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - if (cause instanceof DecoderException && cause.getCause() != null && cause.getCause() instanceof SSLHandshakeException) { + if (cause instanceof DecoderException && cause.getCause() != null && (cause.getCause() instanceof SSLHandshakeException || cause.getCause() instanceof NotSslRecordException)) { // Probably the client rejecting the server certificate. Omit stack trace to reduce log output. LOGGER.debug("Error occurred in connection to client at address {}: {}", ctx.channel().remoteAddress(), cause.getMessage()); } else { diff --git a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolServerHandler.java b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolServerHandler.java index 94cd0b1fc..3776ac3a6 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolServerHandler.java +++ b/core/src/main/java/pl/skidam/automodpack_core/protocol/netty/handler/ProtocolServerHandler.java @@ -10,6 +10,7 @@ import java.util.List; +import static pl.skidam.automodpack_core.GlobalVariables.serverConfig; import static pl.skidam.automodpack_core.protocol.NetUtils.*; public class ProtocolServerHandler extends ByteToMessageDecoder { @@ -27,7 +28,7 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { } int magic = in.getInt(0); - if (magic == MAGIC_AMMC) { + if (magic == MAGIC_AMMC) { // Server should always support AMMC protocol (magic packets) (preferred way to connect, required for hosting on Minecraft port and good for backwards compatibility) // Consume the packet in.skipBytes(in.readableBytes()); @@ -40,24 +41,9 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { var handlers = ctx.pipeline().toMap(); handlers.forEach((name, handler) -> ctx.pipeline().remove(handler)); -// InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress(); -// boolean isLocalConnection = AddressHelpers.isLocal(address); -// -// // Use compression only for non-local connections -// ctx.pipeline().channel().attr(NetUtils.USE_COMPRESSION).set(!isLocalConnection); - - ctx.pipeline().channel().attr(NettyServer.USE_COMPRESSION).set(true); - - // Set up the pipeline for our protocol - ctx.pipeline() - .addLast("traffic-shaper", TrafficShaper.trafficShaper.getTrafficShapingHandler()) - .addLast("tls", sslCtx.newHandler(ctx.alloc())) - .addLast("zstd-encoder", new ZstdEncoder()) - .addLast("zstd-decoder", new ZstdDecoder()) - .addLast("chunked-write", new ChunkedWriteHandler()) - .addLast("protocol-msg-decoder", new ProtocolMessageDecoder()) - .addLast("msg-handler", new ServerMessageHandler()) - .addLast("error-printer", new ErrorPrinter()); + setupPipeline(ctx); + } else if (sslCtx == null || serverConfig.bindPort != -1) { // However if there's no magic packet and we don't use internal TLS or we are hosting on a separate port, we have to try to connect anyway, for use with reverse proxy setups + setupPipeline(ctx); } // Always remove this handler after processing if its still there @@ -65,4 +51,22 @@ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { ctx.pipeline().remove(this); } } + + private void setupPipeline(ChannelHandlerContext ctx) { + ctx.pipeline().channel().attr(NettyServer.USE_COMPRESSION).set(true); + + // add error handler pipeline + ctx.pipeline().addLast("error-printer-first", new ErrorPrinter()); + ctx.pipeline().addLast("traffic-shaper", TrafficShaper.trafficShaper.getTrafficShapingHandler()); + if (sslCtx != null) { // If SSL context is provided, add TLS handler + ctx.pipeline().addLast("tls", sslCtx.newHandler(ctx.alloc())); + } + ctx.pipeline() // Add the rest + .addLast("zstd-encoder", new ZstdEncoder()) + .addLast("zstd-decoder", new ZstdDecoder()) + .addLast("chunked-write", new ChunkedWriteHandler()) + .addLast("protocol-msg-decoder", new ProtocolMessageDecoder()) + .addLast("msg-handler", new ServerMessageHandler()) + .addLast("error-printer-last", new ErrorPrinter()); + } } \ No newline at end of file diff --git a/core/src/main/java/pl/skidam/automodpack_core/utils/AddressHelpers.java b/core/src/main/java/pl/skidam/automodpack_core/utils/AddressHelpers.java index f135ba31f..28f19dd66 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/utils/AddressHelpers.java +++ b/core/src/main/java/pl/skidam/automodpack_core/utils/AddressHelpers.java @@ -91,6 +91,7 @@ public static InetSocketAddress format(String host, int port) { if (host.endsWith(".")) { // It breaks our checks and looks ugly, but its a valid domain... host = host.substring(0, host.length() - 1); } + host = host.toLowerCase(); // #382 return InetSocketAddress.createUnresolved(host, port); } @@ -103,11 +104,11 @@ public static InetSocketAddress parse(String address) { String host = address.substring(0, portIndex); String port = address.substring(portIndex + 1); if (port.matches("\\d+")) { - socketAddress = InetSocketAddress.createUnresolved(host, Integer.parseInt(port)); + socketAddress = format(host, Integer.parseInt(port)); } } if (socketAddress == null) { - socketAddress = InetSocketAddress.createUnresolved(address, 0); + socketAddress = format(address, 0); } } catch (Exception e) { LOGGER.error("Error while parsing address", e); diff --git a/core/src/main/java/pl/skidam/automodpack_core/utils/CustomFileUtils.java b/core/src/main/java/pl/skidam/automodpack_core/utils/CustomFileUtils.java index 116eb7531..8fa727290 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/utils/CustomFileUtils.java +++ b/core/src/main/java/pl/skidam/automodpack_core/utils/CustomFileUtils.java @@ -144,10 +144,10 @@ public static String formatPath(final Path modpackFile, final Path modpackPath) String formattedFile = modpackFileStr; // Checks if in file parents paths (absolute path) there is modpack directory (absolute path) - if (modpackFileStrAbs.contains(modpackPathStrAbs)) { - formattedFile = modpackFileStrAbs.replace(modpackPathStrAbs, ""); - } else if (modpackFileStrAbs.contains(cwdStrAbs)) { - formattedFile = modpackFileStrAbs.replace(cwdStrAbs, ""); + if (modpackFileStrAbs.startsWith(modpackPathStrAbs)) { + formattedFile = modpackFileStrAbs.substring(modpackPathStrAbs.length()); + } else if (modpackFileStrAbs.startsWith(cwdStrAbs)) { + formattedFile = modpackFileStrAbs.substring(cwdStrAbs.length()); } else if (!modpackFileStrAbs.equals(modpackFileStr)) { // possible in e.g. docker LOGGER.error("File: {} ({}) is not in modpack directory: {} ({}) or current working directory: {}", modpackFileStr, modpackFileStrAbs, modpackPath, modpackPathStrAbs, cwdStrAbs); } diff --git a/core/src/main/java/pl/skidam/automodpack_core/utils/WildCards.java b/core/src/main/java/pl/skidam/automodpack_core/utils/WildCards.java index 75a16e4ea..e188a696f 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/utils/WildCards.java +++ b/core/src/main/java/pl/skidam/automodpack_core/utils/WildCards.java @@ -26,6 +26,10 @@ public Map getWildcardMatches() { public void separateRules(List rules) { for (String rule : rules) { + if (rule == null || rule.isBlank()) { + continue; + } + if (rule.startsWith("!")) { blackListRules.add(rule.substring(1)); } else { @@ -42,7 +46,12 @@ public WildCards(List rules, Set startDirectories) { for (Path startDirectory : startDirectories) { try (Stream paths = Files.walk(startDirectory)) { - paths.forEach(node -> matchWhiteRules(node, startDirectory, composedWhiteRules)); + try { // Fixes some wierd edge cases + paths.filter(Files::isRegularFile) + .forEach(node -> matchWhiteRules(node, startDirectory, composedWhiteRules)); + } catch (Exception e) { + LOGGER.error("Error processing files in directory: {}", startDirectory, e); + } } matchBlackRules(startDirectory, composedBlackRules); @@ -187,6 +196,10 @@ public Map> composeRules(List rules) { Map> directoryRulePathsMap = new HashMap<>(rules.size()); for (String rule : rules) { + if (rule == null || rule.isBlank()) { + continue; + } + int lastSlashIndex = rule.lastIndexOf("/"); if (lastSlashIndex == -1) { continue; diff --git a/core/src/main/java/pl/skidam/automodpack_core/utils/WorkaroundUtil.java b/core/src/main/java/pl/skidam/automodpack_core/utils/WorkaroundUtil.java index d207e0543..931fab77f 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/utils/WorkaroundUtil.java +++ b/core/src/main/java/pl/skidam/automodpack_core/utils/WorkaroundUtil.java @@ -25,11 +25,11 @@ public Set getWorkaroundMods(Jsons.ModpackContentFields modpackContentFi return workaroundMods; } - for (Jsons.ModpackContentFields.ModpackContentItem mod : modpackContentFields.list) { - if (mod.type.equals("mod")) { - Path modPath = CustomFileUtils.getPath(modpackPath, mod.file); + for (Jsons.ModpackContentFields.ModpackContentItem item : modpackContentFields.list) { + if (item.type.equals("mod")) { + Path modPath = CustomFileUtils.getPath(modpackPath, item.file); if (FileInspection.hasSpecificServices(modPath)) { - workaroundMods.add(mod.file); + workaroundMods.add(item.file); } } } diff --git a/core/src/test/java/pl/skidam/automodpack_core/modpack/ModpackTest.java b/core/src/test/java/pl/skidam/automodpack_core/modpack/ModpackTest.java index ee5e2bf0d..e97b197fb 100644 --- a/core/src/test/java/pl/skidam/automodpack_core/modpack/ModpackTest.java +++ b/core/src/test/java/pl/skidam/automodpack_core/modpack/ModpackTest.java @@ -48,7 +48,7 @@ void modpackTest() { "ModpackContentItems(file=/mods/server-mod-1.20.jar, size=1, type=other, editable=false, sha1=86f7e437faa5a7fce15d1ddcb9eaeaea377667b8, murmur=null)" ); - ModpackContent content = new ModpackContent("TestPack", null, testFilesDir, new ArrayList<>(), new ArrayList<>(editable), new ModpackExecutor().getExecutor()); + ModpackContent content = new ModpackContent("TestPack", null, testFilesDir, new ArrayList<>(), new ArrayList<>(editable), new ArrayList<>(), new ModpackExecutor().getExecutor()); content.create(); boolean correct = true; diff --git a/docs/.translated/fr_fr/_homepage.mdx b/docs/.translated/fr_fr/_homepage.mdx new file mode 100644 index 000000000..3f7e2f1aa --- /dev/null +++ b/docs/.translated/fr_fr/_homepage.mdx @@ -0,0 +1,9 @@ +Bienvenue dans la documentation d'AutoModpack ! + +Si vous débutez avec AutoModpack, nous vous recommandons de commencer par le [Guide de démarrage rapide](docs/quick-start) pour vous familiariser avec les bases de l'utilisation d'AutoModpack. + +Si vous recherchez des informations plus détaillées, vous pouvez les trouver dans la section `👨‍💻 Détails techniques`. + +Vous avez des questions ou besoin d'aide ? Rejoignez notre [serveur Discord](https://discord.gg/hS6aMyeA9P). + +Vous trouvez ce projet utile ? Envisagez de soutenir son développement et sa maintenance continus en faisant un don à l'auteur sur [Ko-fi](https://ko-fi.com/skidam). \ No newline at end of file diff --git a/docs/.translated/fr_fr/_meta.json b/docs/.translated/fr_fr/_meta.json new file mode 100644 index 000000000..96177897b --- /dev/null +++ b/docs/.translated/fr_fr/_meta.json @@ -0,0 +1,34 @@ +{ + "quick-start.mdx": { + "name": "🚀 Démarrage rapide", + "icon": null + }, + "usage": { + "name": "Utilisation", + "icon": null + }, + "configuration": { + "name": "\uD83D\uDEE0\uFE0F Configuration", + "icon": null + }, + "commands": { + "name": "⌨\uFE0F Commandes", + "icon": null + }, + "examples": { + "name": "\uD83D\uDCF7 Exemples", + "icon": null + }, + "technicals": { + "name": "\uD83D\uDC68\u200D\uD83D\uDCBB Détails techniques", + "icon": null + }, + "compatibility": { + "name": "\uD83D\uDCDA Compatibilité", + "icon": null + }, + "faq.mdx": { + "name": "❔ FAQ", + "icon": null + } +} \ No newline at end of file diff --git a/docs/.translated/fr_fr/commands/_meta.json b/docs/.translated/fr_fr/commands/_meta.json new file mode 100644 index 000000000..5610f28c6 --- /dev/null +++ b/docs/.translated/fr_fr/commands/_meta.json @@ -0,0 +1,6 @@ +{ + "commands.mdx": { + "name": "Commandes", + "icon": null + } +} diff --git a/docs/.translated/fr_fr/commands/commands.mdx b/docs/.translated/fr_fr/commands/commands.mdx new file mode 100644 index 000000000..df07b58dc --- /dev/null +++ b/docs/.translated/fr_fr/commands/commands.mdx @@ -0,0 +1,11 @@ +`/amp` est un alias pour `/automodpack`. + +- `/automodpack` - Statut d'AutoModpack et aide générale. +- `/automodpack generate` - Générer le modpack. +- `/automodpack host` - Statut de l'hébergement du modpack. +- `/automodpack host start` - Démarrer l'hébergement du modpack. +- `/automodpack host stop` - Arrêter l'hébergement du modpack. +- `/automodpack host restart` - Redémarrer l'hébergement du modpack. +- `/automodpack host connections` - Liste toutes les connexions actives à l'hébergement du modpack. +- `/automodpack host fingerprint` - Obtenir le [certificat de l'empreinte](../technicals/certificate) de l'hôte du modpack. +- `/automodpack config reload` - Recharger les fichiers de configuration. \ No newline at end of file diff --git a/docs/.translated/fr_fr/compatibility/_meta.json b/docs/.translated/fr_fr/compatibility/_meta.json new file mode 100644 index 000000000..29d93bf90 --- /dev/null +++ b/docs/.translated/fr_fr/compatibility/_meta.json @@ -0,0 +1,14 @@ +{ + "launchers.mdx": { + "name": "Compatibilité des launchers", + "icon": null + }, + "mods.mdx": { + "name": "Modifications compatibility", + "icon": null + }, + "proxies.mdx": { + "name": "Proxies compatibility", + "icon": null + } +} diff --git a/docs/.translated/fr_fr/compatibility/launchers.mdx b/docs/.translated/fr_fr/compatibility/launchers.mdx new file mode 100644 index 000000000..33cea4460 --- /dev/null +++ b/docs/.translated/fr_fr/compatibility/launchers.mdx @@ -0,0 +1,15 @@ +Most of the launchers will work without any issues, but some modified custom clients won't work. Here is a list of known launchers and their compatibility with AutoModpack: + +| Launcher Name | Compatibility | Notes | +|---------------------------|---------------|----------------------------------------------------------------------------------------------------------------| +| Vanilla official Launcher | ✅ | Supported | +| Prism/MultiMC Launcher | ✅ | Prism is recommended - Perfect support, with additional features like modloader version synchronization | +| Modrinth Launcher | ✅ | Supported | +| CurseForge | ✅ | Supported | +| GDLauncher | ✅ | Supported | +| ATLauncher | ✅ | Supported | +| PojavLauncher (Android) | ⚠️ | Currently broken, worked on previous versions, [read more](https://github.com/Skidamek/AutoModpack/issues/379) | +| FCL (Android) | ⚠️ | Currently broken, worked on previous versions, [read more](https://github.com/Skidamek/AutoModpack/issues/379) | +| Feather Client | ❌ | Unsupported - breaks modpack loading | +| Lunar Client | ❌ | Unsupported - breaks modpack loading | +| PCL2 | ❌ | Unsupported - breaks modpack loading | diff --git a/docs/.translated/fr_fr/compatibility/mods.mdx b/docs/.translated/fr_fr/compatibility/mods.mdx new file mode 100644 index 000000000..94748cef5 --- /dev/null +++ b/docs/.translated/fr_fr/compatibility/mods.mdx @@ -0,0 +1,5 @@ +AutoModpack devrait fonctionner avec toutes les modifications Minecraft (sinon, ce ne serait pas un bon outil de mise à jour de modpack). Cependant, il existe quelques exceptions et limitations dont vous devez être conscient : + +- Mods de Majrusz : Nécessitent une version modifiée de la Majrusz Library pour fonctionner avec AutoModpack. [Github Issue](https://github.com/Skidamek/AutoModpack/issues/268). +- [ModSets](https://modrinth.com/mod/mod-sets) : Ne fonctionne actuellement pas en raison de similitudes dans le processus de modification du chargement des mods. +- [Cesium](https://modrinth.com/mod/cesium) : Cesium est actuellement incompatible en raison d'un mauvais empaquetage de zstd du côté d'AutoModpack. Cela sera bientôt corrigé. [GitHub Issue](https://github.com/Skidamek/AutoModpack/issues/384) \ No newline at end of file diff --git a/docs/.translated/fr_fr/compatibility/proxies.mdx b/docs/.translated/fr_fr/compatibility/proxies.mdx new file mode 100644 index 000000000..f4f6e370a --- /dev/null +++ b/docs/.translated/fr_fr/compatibility/proxies.mdx @@ -0,0 +1,14 @@ +La plupart des proxys Minecraft ne fonctionneront pas avec AutoModpack en raison des paquets de la phase de connexion précoce. Cependant, Gate Lite est supporté et fonctionne bien avec AutoModpack. Voici une liste des proxys connus et de leur compatibilité : + +| Nom du Proxy                                      | Compatibilité | Notes         | +|---------------------------------------------------|----------------|---------------| +| [Gate Lite](https://gate.minekube.com/guide/lite) | ✅             | Supporté      | +| Gate                                              | ❌             | Non supporté  | +| Velocity                                          | ❌             | Non supporté  | +| Waterfall                                         | ❌             | Non supporté  | +| BungeeCord                                        | ❌             | Non supporté  | + +Lorsque vous utilisez Gate Lite, il est crucial de configurer correctement `portToSend`. Par défaut, les clients tentent de se connecter à l'hôte du modpack en utilisant le même port que celui utilisé pour se connecter à votre serveur Minecraft. Cependant, lorsque vous utilisez un proxy comme Gate, ce port diffère du port réel de votre serveur Minecraft, empêchant les clients de se connecter pour télécharger le modpack. + +Par conséquent, si votre modpack est hébergé avec `bindPort` défini sur `-1`, `portToSend` doit être défini sur le port depuis lequel votre serveur Minecraft est accessible (généralement, ce sera le même port sur lequel le serveur Minecraft écoute). +De même, si `bindPort` est défini sur un port spécifique, `portToSend` doit être défini sur le port depuis lequel l'hôte du modpack est accessible (généralement, ce sera le même que `bindPort`). \ No newline at end of file diff --git a/docs/.translated/fr_fr/configuration/_meta.json b/docs/.translated/fr_fr/configuration/_meta.json new file mode 100644 index 000000000..aed4f3058 --- /dev/null +++ b/docs/.translated/fr_fr/configuration/_meta.json @@ -0,0 +1,14 @@ +{ + "server-config.mdx": { + "name": "Server Configuration", + "icon": null + }, + "client-config.mdx": { + "name": "Client Configuration", + "icon": null + }, + "troubleshooting.mdx": { + "name": "Troubleshooting", + "icon": null + } +} diff --git a/docs/.translated/fr_fr/configuration/client-config.mdx b/docs/.translated/fr_fr/configuration/client-config.mdx new file mode 100644 index 000000000..630f8c8f7 --- /dev/null +++ b/docs/.translated/fr_fr/configuration/client-config.mdx @@ -0,0 +1,10 @@ +### Fichier de Configuration Client + +`/automodpack/automodpack-client.json` + +| Nom                  | Valeur par Défaut | Description                                                                                                                                                        | +|---------------------|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `DO_NOT_CHANGE_IT`  | ``  | Numéro de version du fichier utilisé pour la conversion automatique des anciennes versions de configuration vers les nouvelles lors de la mise à jour d'AutoModpack.  | +| `selectedModpack`   |                  | Le dossier principal du modpack auquel vous voulez jouer. Taper le nom du modpack ici provoquera son chargement.                                            | +| `installedModpacks` |                  | Une liste des modpacks qui sont installés sur le client.                                                                                                       | +| `selfUpdater`       | `false`          | Active/désactive les mises à jour automatiques d'AutoModpack. Cela n'affecte pas l'activité du mod dans l'installation des modpacks. Cela ne désactive pas la synchronisation de la version d'AutoModpack avec le serveur. | diff --git a/docs/.translated/fr_fr/configuration/server-config.mdx b/docs/.translated/fr_fr/configuration/server-config.mdx new file mode 100644 index 000000000..d9f597138 --- /dev/null +++ b/docs/.translated/fr_fr/configuration/server-config.mdx @@ -0,0 +1,29 @@ +### Fichier de Configuration Serveur +`~/automodpack/automodpack-server.json` + +| Nom | Valeur par Défaut | Description | +|-------------------------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `DO_NOT_CHANGE_IT` | `` | Numéro de version du fichier utilisé pour la conversion automatique des anciennes versions de configuration vers les nouvelles lors de la mise à jour d'AutoModpack. | +| `modpackName` | `""` | Le nom du modpack du serveur, s'affiche pendant le téléchargement du modpack et c'est ainsi que le répertoire du modpack est nommé dans `~/automodpack/modpacks/`. | +| `modpackHost` | `true` | Démarre le serveur d'hébergement du modpack. | +| `generateModpackOnStart` | `true` | Regénère automatiquement les métadonnées du modpack au démarrage du serveur. | +| `syncedFiles` | `"/mods/*.jar", "/kubejs/**", "!/kubejs/server_scripts/**", "/emotes/*"` | Une liste de *chemins relatifs* depuis le dossier racine du serveur Minecraft qui seront **synchronisés avec le modpack**. Utilisez des jokers comme `*` pour inclure plusieurs fichiers de ce répertoire (ex: `/mods/*.jar`). Ou utilisez `**` (double étoile) pour inclure récursivement tous les fichiers et sous-dossiers d'un répertoire (ex: `/config/**`). Préfixez un chemin avec `!` pour l'**exclure** de la synchronisation. **Note :** Ceci ne **copie pas** les fichiers ; cela définit seulement ce qui sera disponible côté client sous `~/.minecraft/`. | +| `allowEditsInFiles` | `"/options.txt", "/config/**"` | Une liste de fichiers que les clients sont autorisés à modifier. En d'autres termes, des fichiers qui sont téléchargés une seule fois puis ignorés lors des mises à jour. La configuration fonctionne exactement de la même manière que `syncedFiles`. | +| `autoExcludeServerSideMods` | `true` | Exclut automatiquement les mods côté serveur du modpack. (Ne fonctionne que si le développeur du mod a spécifié le type d'environnement dans les métadonnées du mod) | +| `autoExcludeUnnecessaryFiles` | `true` | Ignore automatiquement les fichiers qui sont : vides, cachés, temporaires, désactivés ou de sauvegarde. | +| `requireAutoModpackOnClient` | `true` | Indique si ce mod est optionnel ou non pour que les clients rejoignent le serveur. | +| `nagUnModdedClients` | `true` | Si `true`, les clients sans AutoModpack recevront un message de rappel dans le chat à leur connexion. Pour fonctionner, `requireAutoModpackOnClient` doit être `false`. | +| `nagMessage` | `"This server provides dedicated modpack through AutoModpack!"` | Le message qui sera affiché aux clients sans AutoModpack. Pour fonctionner, `nagUnModdedClients` doit être `true`. | +| `nagClickableMessage` | `"Click here to get the AutoModpack!"` | La partie cliquable du message qui sera affichée aux clients sans AutoModpack. Pour fonctionner, `nagUnModdedClients` doit être `true`. | +| `nagClickableLink` | `"https://modrinth.com/project/automodpack"` | Le lien qui sera ouvert lorsque le message est cliqué. Pour fonctionner, `nagUnModdedClients` doit être `true`. | +| `bindAddress` | `""` | L'adresse à laquelle le serveur d'hébergement du modpack se lie. Laissez ce champ vide pour déterminer automatiquement une adresse locale (typiquement `0.0.0.0` ou `::0`). Lorsque `bindPort` est défini sur `-1`, cette valeur est **ignorée** et l'hôte du modpack sera lié à la même adresse que le serveur Minecraft, comme spécifié dans le fichier `server.properties`. | +| `bindPort` | `-1` | Le numéro de port sur lequel le serveur d'hébergement du modpack écoute. Si défini sur `-1`, le modpack sera hébergé directement sur le port de votre serveur Minecraft. | +| `addressToSend` | `""` | L'adresse de l'hôte du modpack qui sera utilisée par les clients pour télécharger le modpack. Si vide, les clients utiliseront la même adresse que celle utilisée pour se connecter au serveur Minecraft. (N'incluez **pas** le port ici, utilisez `portToSend` à la place) | +| `portToSend` | `-1` | Le numéro de port qui est envoyé avec `addressToSend`. Si défini sur `-1`, les clients utiliseront le même port que celui utilisé pour se connecter au serveur Minecraft. | +| `disableInternalTLS` | `false` | Désactive la gestion TLS interne. Si activé, vous devez gérer le TLS de manière externe, par ex. sur un reverse proxy. En utilisant cette option, vous devez utiliser un `bindPort` différent de `-1` et vous devriez envisager de définir `bindAddress` sur une adresse de loopback (ex: `127.0.0.1`), afin que le trafic non chiffré entre l'hôte du modpack et le reverse proxy ne fuite pas. | +| `updateIpsOnEveryStart` | `false` | Met à jour `addressToSend` à chaque démarrage du serveur. Peut être utile si vous avez une adresse IP dynamique. (Utilisez-le uniquement si vous en avez vraiment besoin !) | +| `bandwidthLimit` | `0` | Limite de téléversement en Mbps à laquelle le serveur d'hébergement du modpack est restreint. (La valeur doit être un entier, `0` - signifie illimité) | +| `validateSecrets` | `true` | Fait en sorte que l'hôte du modpack valide et autorise les tentatives de téléchargement du modpack à l'aide de secrets uniques. | +| `secretLifetime` | `336` | Durée en heures pendant laquelle le secret d'un joueur reste valide. | +| `selfUpdater` | `false` | Active/désactive toutes les mises à jour d'AutoModpack. Cela n'affecte pas l'activité du mod dans l'installation des modpacks. | +| `acceptedLoaders` | `""` | Permet aux joueurs de différents modloaders de se connecter à votre serveur. (À utiliser avec prudence, la plupart des mods ne fonctionnent que sur un seul loader) | \ No newline at end of file diff --git a/docs/.translated/fr_fr/configuration/troubleshooting.mdx b/docs/.translated/fr_fr/configuration/troubleshooting.mdx new file mode 100644 index 000000000..28592c062 --- /dev/null +++ b/docs/.translated/fr_fr/configuration/troubleshooting.mdx @@ -0,0 +1,6 @@ +## Dépannage des problèmes de configuration +Lorsque vous avez fini de modifier les fichiers de configuration, assurez-vous de les recharger en exécutant la commande `automodpack config reload` ou en redémarrant le serveur/jeu. + +Si vous ne trouvez pas les fichiers de configuration, assurez-vous que le client/serveur a été démarré au moins une fois, afin que les fichiers soient générés. + +Si les valeurs sont restaurées par défaut, cela peut signifier que votre fichier de configuration est malformé. Assurez-vous d'utiliser un éditeur avec un analyseur JSON intégré, ou vérifiez-le dans un outil en ligne, par ex. https://jsonformatter.org/json-parser. diff --git a/docs/.translated/fr_fr/faq.mdx b/docs/.translated/fr_fr/faq.mdx new file mode 100644 index 000000000..4735ef4a2 --- /dev/null +++ b/docs/.translated/fr_fr/faq.mdx @@ -0,0 +1,49 @@ +### Est-ce un mod côté serveur ? +Non, c'est les deux. Vous devez l'installer à la fois sur le serveur et sur le client. + +### Comment puis-je ajouter des mods uniquement client au modpack ? (ex: le serveur crash avec un certain mod mais je le veux pour les clients) +Jetez un œil à la [page de création de modpack](techinicals/modpack-creation). + +### Comment restreindre l'accès à mon modpack ? +Activez `validateSecrets` dans la [config](configuration/server-config), activez `online-mode` dans le fichier server.properties et activez la whitelist ou bannissez quelqu'un. + +### Est-ce que cela fonctionne en LAN (monde solo avec l'option pour que d'autres joueurs rejoignent) ? +Oui. N'oubliez pas de générer le modpack via la commande /`automodpack generate` et de démarrer l'hébergement du modpack avec /`automodpack host start`. + +### Est-ce que cela fonctionne avec un monde solo partagé via Essential, World Host, e4mc ? +Peu de chance, la plupart de ces types de mods ne transfèrent que les paquets Minecraft. Ces mods devraient prendre en charge le protocole d'AutoModpack ou simplement relayer tous les paquets TCP au lieu de se limiter au protocole Minecraft. + +### Puis-je utiliser des mods hors-modpack sur le client ? +Oui, vous pouvez ajouter n'importe quel mod que vous souhaitez utiliser en parallèle du modpack téléchargé en plaçant simplement le mod dans le dossier mods standard. + +### Comment puis-je supprimer des fichiers du modpack ? +Supprimez simplement le fichier du serveur, ou excluez-le de la synchronisation, lisez la section sur `syncedFiles` dans la [config](configuration/server-config). + +### Puis-je retirer/désactiver les fichiers/mods hors-modpack pour les joueurs ? +Pas encore, mais cela pourrait arriver dans le futur. + +### Dois-je ouvrir un port sur mon routeur ? +Non, ce n'est pas nécessaire. Par défaut, AutoModpack s'injecte dans les E/S réseau de Minecraft, ce qui réutilise le port de votre serveur Minecraft. (ex: 25565) + +Si vous voulez utiliser un port différent, désactivez `hostModpackOnMinecraftPort` et modifiez `hostPort` dans la [config](configuration/server-config). + +### Que se passe-t-il quand je mets à jour la version d'AutoModpack sur le serveur ? +Le client essaie toujours de se synchroniser avec la version d'AutoModpack du serveur. Il se met à jour ou se rétrograde à la version du serveur si celle-ci est trouvée sur Modrinth. + +### Pourquoi le chemin d'hébergement du modpack est-il si long ? +Il est prévu d'implémenter la possibilité d'ajouter plus d'un seul modpack, le modpack `main`. + +### Quelles versions de Minecraft sont supportées ? +Toutes les versions que vous voyez dans la [dernière version](https://github.com/Skidamek/AutoModpack/releases/latest). + +### Mon launcher est-il supporté ? +Jetez un œil à la [page de compatibilité](compatibility/launchers) pour plus d'informations sur les launchers supportés. + +### Est-ce que ce mod met à jour les mods de mon modpack aux dernières versions ? +Non, c'est hors du champ d'application de ce projet. Ce mod ne fait que synchroniser le modpack du serveur avec les clients. Tous vos mods sur le serveur devront toujours être mis à jour manuellement. AutoModpack s'assure simplement que les versions du client correspondent à celles du serveur. + +### J'ai trouvé un bug, que dois-je faire ? +Si vous avez trouvé un bug, veuillez le signaler sur le [tracker de bugs](https://github.com/Skidamek/AutoModpack/issues). + +### J'ai trouvé une faille de sécurité, que dois-je faire ? +Veuillez la signaler en privé à l'auteur sur [Discord](https://discordapp.com/users/464522287618457631), nous essaierons de la résoudre dès que possible. \ No newline at end of file diff --git a/docs/.translated/fr_fr/quick-start.mdx b/docs/.translated/fr_fr/quick-start.mdx new file mode 100644 index 000000000..c267ad965 --- /dev/null +++ b/docs/.translated/fr_fr/quick-start.mdx @@ -0,0 +1,36 @@ +Alors comme ça vous voulez commencer à utiliser AutoModpack ? Super ! C'est parti. + +## Installation + +1. **Télécharger AutoModpack** : Obtenez la dernière version d'AutoModpack pour votre version de Minecraft depuis [Modrinth](https://modrinth.com/mod/automodpack) ou [CurseForge](https://www.curseforge.com/minecraft/mc-mods/automodpack). +2. **Installer AutoModpack** : Placez le mod téléchargé dans le dossier `mods` de votre instance Minecraft. +3. **Démarrer votre serveur** : Lancez votre serveur Minecraft avec AutoModpack installé. Cela générera les métadonnées initiales du modpack. + +Vous êtes maintenant, dans la plupart des cas, prêt à démarrer. À ce stade, il est recommandé d'essayer de vous connecter à votre serveur avec uniquement AutoModpack d'installé sur le client pour voir si tout fonctionne. + +## Première Connexion +Lors de la première connexion, il vous sera demandé de vérifier l'empreinte du certificat du serveur. C'est une mesure de sécurité pour s'assurer que vous vous connectez au bon serveur et non à un serveur malveillant. En savoir plus sur la [certificate verification](technicals/certificate). +Après une vérification réussie, AutoModpack vous demandera de confirmer l'installation du modpack. Confirmez et le modpack sera téléchargé et installé automatiquement. + +Maintenant, redémarrez votre jeu et le modpack de votre serveur sera chargé. Vous devriez pouvoir vous connecter à nouveau à votre serveur, mais cette fois-ci en apparaissant dans l'overworld ! + + +Si vous ne voyez pas les mods de votre modpack dans le dossier mods, ne vous inquiétez pas. Les mods ne seront pas installés dans votre dossier mods standard, ils seront installés dans le dossier `~/.minecraft/automodpack/modapcks/{your-modpack}/mods/` à la place. Il y a de [bonnes raisons pour ça](technicals/file-structure). + + +## Dépannage +Si vous rencontrez des problèmes à ce stade, voici quelques étapes de dépannage courantes : +- Assurez-vous d'utiliser la même version d'AutoModpack sur le serveur et le client. +- Assurez-vous que votre serveur est en cours d'exécution et accessible sans AutoModpack. +- Vérifiez les logs et la console du serveur, il pourrait y avoir des indices sur ce qui n'a pas fonctionné. +- Lisez la [page faq](faq) pour les questions et réponses courantes. + +Si vous rencontrez toujours des problèmes, rejoignez notre [serveur Discord](https://discord.gg/hS6aMyeA9P) et créez une publication dans le salon `#support`, nous essaierons de vous aider ! + +## Prochaines Étapes + +Maintenant que vous avez tout installé et fait fonctionner AutoModpack, vous pouvez commencer à personnaliser votre modpack. Voici quelques choses que vous pouvez faire ensuite : + +- Lisez la [page de création de modpack](technicals/modpack-creation) pour apprendre à gérer votre modpack. +- Lisez la [page de configuration](configuration/server-config) pour apprendre à configurer AutoModpack selon vos besoins. +``` \ No newline at end of file diff --git a/docs/.translated/fr_fr/technicals/_meta.json b/docs/.translated/fr_fr/technicals/_meta.json new file mode 100644 index 000000000..69aabdfc4 --- /dev/null +++ b/docs/.translated/fr_fr/technicals/_meta.json @@ -0,0 +1,22 @@ +{ + "connection.mdx": { + "name": "Connection", + "icon": null + }, + "certificate.mdx": { + "name": "Gestion des certificats", + "icon": null + }, + "modpack-creation.mdx": { + "name": "Création du modpack", + "icon": null + }, + "file-structure.mdx": { + "name": "Structure des fichiers", + "icon": null + }, + "modpack-hosting.mdx": { + "name": "Hebergement du modpack", + "icon": null + } +} diff --git a/docs/.translated/fr_fr/technicals/certificate.mdx b/docs/.translated/fr_fr/technicals/certificate.mdx new file mode 100644 index 000000000..e60a753bd --- /dev/null +++ b/docs/.translated/fr_fr/technicals/certificate.mdx @@ -0,0 +1,74 @@ +### Comment vérifier l'empreinte du certificat ? +Pour vérifier, il suffit de **copier l’empreinte depuis la console de votre serveur dans le jeu.** Il s’agit d’une vérification unique : vous n’aurez pas à la refaire après la première connexion. Ce processus permet de prévenir les menaces de sécurité comme les attaques de type [Man-in-the-middle](https://fr.wikipedia.org/wiki/Attaque_de_l%27homme_du_milieu). L’empreinte est la même pour tous les joueurs de votre serveur et elle ne change jamais. Il est recommandé de la partager avec les joueurs à l’avance. + +Si vous ne trouvez pas l’empreinte dans la console, vous pouvez la récupérer à tout moment avec la commande `/automodpack host fingerprint` [commande](../commands/commands). + +Cependant, ne la considérez pas comme un mot de passe pour le modpack : ce n’en est pas un, et ce n’est pas non plus un secret. C’est une partie publique et vérifiable du certificat du serveur, **n’importe qui pourrait télécharger** votre modpack sans connaître cette empreinte, par exemple en contournant cette vérification avec `I AM INCREDIBLY STUPID`. (ne faites pas ça) + +Pour fournir le modpack uniquement aux joueurs autorisés/liste blanche, utilisez l’option `validateSecrets` dans la [configuration du serveur](../configuration/server-config) (activée par défaut). + + +Si vous ne souhaitez pas que les joueurs valident manuellement le certificat et que vous possédez un nom de domaine (requis), vous pouvez fournir votre propre certificat signé par une autorité de certification (CA). + +### Comment fournir votre propre certificat signé par une CA ? + +Vous pouvez utiliser des outils comme [Certbot](https://eff-certbot.readthedocs.io/en/stable/install.html). + +Une fois le certificat obtenu, sur le serveur dans le dossier `~/automodpack/.private/`, remplacez les fichiers `cert.crt` (avec le certificat complet en chaîne) et `key.pem` ([la clé doit être au format PKCS#8 (PEM)](https://netty.io/wiki/sslcontextbuilder-and-private-key.html)) – attention : l’interception de ces fichiers pourrait permettre l’usurpation de votre serveur, [en savoir plus](https://security.stackexchange.com/a/16694). +Si vous hébergez le modpack sur un sous-domaine ou domaine différent de celui de votre serveur Minecraft, assurez-vous que votre certificat couvre bien les deux. + +### Petit tutoriel pour obtenir un certificat avec Certbot + +Installez Certbot sur votre PC ou serveur, puis exécutez la commande suivante et suivez les instructions fournies par Certbot pour obtenir un certificat pour votre domaine : + +```bash +# certbot certonly --manual --preferred-challenges dns -d -d + + +✅ Si vous hébergez le modpack sur **le même port que le serveur Minecraft**, les domaines sont souvent identiques → dans ce cas, **le second `-d` n’est pas nécessaire**. + +> ⚠️ **Attention** : ne copiez-collez jamais une commande trouvée au hasard sur Internet. +> Lisez toujours la documentation de l’outil que vous utilisez ! + +Une fois le certificat obtenu : + +* `fullchain.pem` → renommez-le en `cert.crt` +* `privkey.pem` → renommez-le en `key.pem` + +Placez-les dans `~/automodpack/.private/` + +--- + +### Mais pourquoi ai-je besoin de tout ça ? C’est juste un modpack pour mes amis ! + +Si quelqu’un peut prendre le contrôle de la connexion Automodpack, +il pourrait **installer n’importe quoi sur votre PC (ou celui de vos amis)**. + +Minecraft **n’est pas sandboxé**, et les mods peuvent **exécuter n’importe quel code**. +Donc injecter du code malveillant, même si vous n’êtes pas une cible spécifique, est un énorme risque : + +* vol de mots de passe +* vol de comptes +* suppression de fichiers importants (comme votre dossier de mèmes de chats) + +➡️ **Voilà pourquoi la sécurité est essentielle**, même dans un petit contexte entre amis. + +--- + +### Hmm... ok, mais personne ne connaît mon serveur à part mes amis, pourquoi devrais-je m’en soucier ? + +Même si vous pensez que votre serveur est privé, **ce n’est probablement pas le cas**. +Des scanners de serveurs Minecraft analysent **tout Internet** pour détecter les serveurs accessibles. + +Si votre serveur est vulnérable et que vous ne vérifiez pas le certificat, vous devenez une cible potentielle. + +🔐 De plus, rien n’empêche une attaque via d’autres moyens : + +* accès SSH +* panneau d’administration de l’hébergeur + +👉 **En tant qu’administrateur**, prenez ces mesures sérieusement : + +* mots de passe robustes +* authentification à deux facteurs +* mises à jour régulières de votre logiciel serveur diff --git a/docs/.translated/fr_fr/technicals/connection.mdx b/docs/.translated/fr_fr/technicals/connection.mdx new file mode 100644 index 000000000..5ab855b00 --- /dev/null +++ b/docs/.translated/fr_fr/technicals/connection.mdx @@ -0,0 +1,35 @@ +### Chiffrement + +La connexion pour le téléchargement du modpack est sécurisée à l'aide de TLS 1.3. + +C'est la même norme de sécurité que celle utilisée par HTTPS, le protocole que vous utilisez tout le temps pour naviguer sur le web (même en ce moment \!). + +TLS dispose d'une méthode de vérification de l'identité du serveur à l'aide d'un certificat, ce qui est crucial pour prévenir des attaques telles que [Man-in-the-middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). + +C'est pourquoi AutoModpack vous demande de vérifier l'empreinte du certificat du serveur lors de la première connexion. Lisez [Comment vérifier l'empreinte du certificat](certificate) pour plus de détails. + +### Téléchargements Directs + +AutoModpack utilise des liens de téléchargement direct depuis les API de Modrinth et CurseForge pour télécharger la plupart des fichiers de votre modpack. +Cela signifie que les auteurs des mods sont crédités pour chaque téléchargement. + +Cependant, si un fichier que vous fournissez dans le modpack n'est pas disponible sur Modrinth ou CurseForge, AutoModpack le téléchargera (également directement) mais depuis votre serveur. + +### Compression + +Pour accélérer le téléchargement, AutoModpack compresse les fichiers du modpack à l'aide de l'algorithme de compression [Zstandard](https://facebook.github.io/zstd/). +Cet algorithme est très rapide et offre un excellent taux de compression, ce qui signifie que les fichiers du modpack sont plus petits et plus rapides à télécharger. +C'est particulièrement utile pour les modpacks plus volumineux ou les connexions Internet plus lentes. +Cependant, cela ne s'applique qu'aux fichiers téléchargés depuis votre serveur. + +### Autorisation + +\ +Ne confondez pas cela avec la [certificate fingerprint verification](certificate), qui est utilisée pour vérifier l'identité du serveur. +\ + +AutoModpack utilise un mécanisme d'autorisation simple pour empêcher l'accès non autorisé à votre modpack. +Lorsque vous vous connectez au serveur, en arrière-plan, AutoModpack génère un secret unique et aléatoire pour chaque joueur. Ce secret est ensuite envoyé au joueur et utilisé pour l'autoriser à télécharger les fichiers du modpack. +Chaque fois que vous vous reconnectez au serveur, l'ancien secret est invalidé et un nouveau est généré. +Cela empêche l'accès non autorisé aux fichiers de votre modpack et garantit que seuls les joueurs sur liste blanche et non bannis peuvent télécharger le modpack. +Si vous ne souhaitez pas utiliser cette fonctionnalité, vous pouvez la désactiver (`validateSecrets`) dans la [server config](../configuration/server-config). \ No newline at end of file diff --git a/docs/.translated/fr_fr/technicals/file-structure.mdx b/docs/.translated/fr_fr/technicals/file-structure.mdx new file mode 100644 index 000000000..ca7e4c979 --- /dev/null +++ b/docs/.translated/fr_fr/technicals/file-structure.mdx @@ -0,0 +1,24 @@ +Tous les fichiers d'AutoModpack sont conservés dans le dossier `~/automodpack/`. + +### Serveur + +Le modpack est généré à partir des fichiers se trouvant dans `~/automodpack/host-modpack/main/` et/ou `syncedFiles` (lisez la [config](https://github.com/Skidamek/AutoModpack/blob/main/docs/configuration/server-config)) ce qui se traduit par le dossier `~/.minecraft/` (dossier racine de l'instance minecraft) sur le client. + +La génération du modpack signifie la création de `~/automodpack/host-modpack/automodpack-content.json` qui contient les métadonnées de chaque fichier du modpack. Vous **ne devriez PAS** toucher ce fichier manuellement, modifiez plutôt la configuration. + +### Client + +Tous les modpacks téléchargés sont conservés dans `~/automodpack/modpacks/`. + +Tous les fichiers du modpack sélectionné sont copiés dans `~/.minecraft/` à l'exception des **mods** (avec quelques exceptions, en raison des limitations du mod loader). + +S'il les détecte, AutoModpack essaie également de se débarrasser de la plupart, sinon de la totalité, des mods dupliqués de votre dossier mods standard en faveur du dossier mods d'AutoModpack. +\ +Cela ne devrait pas causer de crashs, mais si vous remarquez qu'AutoModpack supprime une dépendance causant un crash du jeu, veuillez le signaler \! +\ + +Les mods sont séparés pour plusieurs raisons. Une telle approche atténue les inconvénients courants liés au placement de tous les mods du modpack dans le dossier mods standard, tels que : + + - **Crashs dus aux conflits de mods** : Cela ne les résoudra pas, mais cela donne au moins au propriétaire du serveur la possibilité de supprimer ou de corriger à distance les mods en conflit sans intervention manuelle du côté client. + - **Débogage** : Il est plus facile de voir quels mods font partie du modpack et lesquels n'en font pas partie. Comme les clients peuvent ajouter leurs propres mods au dossier mods standard, il est plus facile de déboguer lorsque quelque chose se casse ou entre en conflit. + - **Redémarrages** : Si tous les mods du modpack étaient placés dans le dossier mods standard, il faudrait un redémarrage pour mettre à jour les mods du modpack. Maintenant, cela peut être fait de manière transparente au démarrage sans aucun redémarrage \! \ No newline at end of file diff --git a/docs/.translated/fr_fr/technicals/modpack-creation.mdx b/docs/.translated/fr_fr/technicals/modpack-creation.mdx new file mode 100644 index 000000000..ff49f89cd --- /dev/null +++ b/docs/.translated/fr_fr/technicals/modpack-creation.mdx @@ -0,0 +1,17 @@ +**Oui, vous pouvez ajouter *n'importe quoi* à votre modpack.** + +#### Deux manières d'ajouter du contenu au modpack. + + - Pour réutiliser des fichiers déjà existants sur le serveur, utilisez `syncedFiles`. Pour en savoir plus, lisez la [config](https://github.com/Skidamek/AutoModpack/blob/main/docs/configuration/server-config). Par exemple, avec la configuration par défaut, cela crée un modpack contenant *chaque* mod (fichier se terminant par .jar) du dossier `~/mods/` du serveur. + + - Pour ajouter plus de fichiers au modpack, utilisez le répertoire séparé `~/automodpack/host-modpack/main/`. + Par exemple, pour ajouter plus de mods, créez un dossier `mods` et placez-y les mods, ce qui donnera `~/automodpack/host-modpack/main/mods/`**`votre-mod.jar`**. + Ou pour ajouter des packs de ressources, de manière analogue, créez un dossier `resourcepacks` et placez-y les packs de ressources, ce qui donnera `~/automodpack/host-modpack/main/resourcepacks/`**`votre-packderessources.zip`**. + +\ +Ne placez pas de fichiers de cache dans le modpack, comme le répertoire `.connector` d'un connecteur. Il n'est pas censé être fourni dans le modpack et cela casse les mises à jour transparentes/sans redémarrage. +\ + +Ces deux méthodes se traduisent par le répertoire `~/.minecraft/` du côté client (répertoire racine de l'instance Minecraft). + +N'oubliez pas de regénérer le modpack en utilisant `/automodpack generate` (voir les [commands](https://github.com/Skidamek/AutoModpack/blob/main/docs/commands/commands)) \ No newline at end of file diff --git a/docs/.translated/fr_fr/technicals/modpack-hosting.mdx b/docs/.translated/fr_fr/technicals/modpack-hosting.mdx new file mode 100644 index 000000000..0c8bfeb61 --- /dev/null +++ b/docs/.translated/fr_fr/technicals/modpack-hosting.mdx @@ -0,0 +1,2 @@ +Par défaut, AutoModpack héberge votre modpack sur le port de votre serveur Minecraft (par ex. 25565). Cela signifie que vous n'avez pas besoin d'ouvrir d'autre port sur votre routeur/pare-feu. +Si vous souhaitez utiliser un port différent, modifiez `bindPort` dans la [config](https://github.com/Skidamek/AutoModpack/blob/main/docs/configuration/server-config). \ No newline at end of file diff --git a/docs/.translated/pl_pl/_homepage.mdx b/docs/.translated/pl_pl/_homepage.mdx new file mode 100644 index 000000000..0adcf7818 --- /dev/null +++ b/docs/.translated/pl_pl/_homepage.mdx @@ -0,0 +1,7 @@ +Witaj w dokumentacji AutoModpack'a! + +Jeśli jesteś nowy do AutoModpack'a, zalecamy rozpoczęcie od [Przewodnika Szybkiego Startu](docs/quick-start), aby zapoznać się z podstawami korzystania z AutoModpack'a. + +Jeśli szukasz bardziej szczegółowych informacji, znajdziesz je w sekcji `👨‍💻 Szczegóły Techniczne`. + +Masz pytania lub potrzebujesz pomocy? Dołącz na nasz [serwer Discord](https://discord.gg/hS6aMyeA9P). \ No newline at end of file diff --git a/docs/_homepage.mdx b/docs/_homepage.mdx new file mode 100644 index 000000000..d2945a29e --- /dev/null +++ b/docs/_homepage.mdx @@ -0,0 +1,9 @@ +Welcome to the AutoModpack documentation! + +If you are new to AutoModpack, we recommend starting with the [Quick Start Guide](docs/quick-start) to get familiar with the basics of using AutoModpack. + +If you are looking for more detailed information, you can find it in the `👨‍💻 Technical Details` section. + +Got any questions or need help? Join our [Discord server](https://discord.gg/hS6aMyeA9P). + +Found this project useful? Consider supporting its ongoing development and maintenance by donating to the author on [Ko-fi](https://ko-fi.com/skidam). diff --git a/docs/_meta.json b/docs/_meta.json new file mode 100644 index 000000000..d9751bf7f --- /dev/null +++ b/docs/_meta.json @@ -0,0 +1,34 @@ +{ + "quick-start.mdx": { + "name": "🚀 Quick Start", + "icon": null + }, + "usage": { + "name": "Usage", + "icon": null + }, + "configuration": { + "name": "\uD83D\uDEE0\uFE0F Configuration", + "icon": null + }, + "commands": { + "name": "⌨\uFE0F Commands", + "icon": null + }, + "examples": { + "name": "\uD83D\uDCF7 Examples", + "icon": null + }, + "technicals": { + "name": "\uD83D\uDC68\u200D\uD83D\uDCBB Technical Details", + "icon": null + }, + "compatibility": { + "name": "\uD83D\uDCDA Compatibility", + "icon": null + }, + "faq.mdx": { + "name": "❔ FAQ", + "icon": null + } +} \ No newline at end of file diff --git a/docs/commands/_meta.json b/docs/commands/_meta.json new file mode 100644 index 000000000..cd9c084df --- /dev/null +++ b/docs/commands/_meta.json @@ -0,0 +1,6 @@ +{ + "commands.mdx": { + "name": "Commands", + "icon": null + } +} diff --git a/docs/commands/commands.mdx b/docs/commands/commands.mdx new file mode 100644 index 000000000..579e83233 --- /dev/null +++ b/docs/commands/commands.mdx @@ -0,0 +1,11 @@ +`/amp` is an alias for `/automodpack`. + +- `/automodpack` - Status of automodpack and general help. +- `/automodpack generate` - Generate modpack. +- `/automodpack host` - Status of modpack hosting. +- `/automodpack host start` - Start modpack hosting. +- `/automodpack host stop` - Stop modpack hosting. +- `/automodpack host restart` - Restart modpack hosting. +- `/automodpack host connections` - Lists all currently active modpack host connections. +- `/automodpack host fingerprint` - Get the [certificate fingerprint](../technicals/certificate) of the modpack host. +- `/automodpack config reload` - Reload config files. \ No newline at end of file diff --git a/docs/compatibility/_meta.json b/docs/compatibility/_meta.json new file mode 100644 index 000000000..d3e204510 --- /dev/null +++ b/docs/compatibility/_meta.json @@ -0,0 +1,14 @@ +{ + "launchers.mdx": { + "name": "Launchers compatibility", + "icon": null + }, + "mods.mdx": { + "name": "Modifications compatibility", + "icon": null + }, + "proxies.mdx": { + "name": "Proxies compatibility", + "icon": null + } +} diff --git a/docs/compatibility/launchers.mdx b/docs/compatibility/launchers.mdx new file mode 100644 index 000000000..33cea4460 --- /dev/null +++ b/docs/compatibility/launchers.mdx @@ -0,0 +1,15 @@ +Most of the launchers will work without any issues, but some modified custom clients won't work. Here is a list of known launchers and their compatibility with AutoModpack: + +| Launcher Name | Compatibility | Notes | +|---------------------------|---------------|----------------------------------------------------------------------------------------------------------------| +| Vanilla official Launcher | ✅ | Supported | +| Prism/MultiMC Launcher | ✅ | Prism is recommended - Perfect support, with additional features like modloader version synchronization | +| Modrinth Launcher | ✅ | Supported | +| CurseForge | ✅ | Supported | +| GDLauncher | ✅ | Supported | +| ATLauncher | ✅ | Supported | +| PojavLauncher (Android) | ⚠️ | Currently broken, worked on previous versions, [read more](https://github.com/Skidamek/AutoModpack/issues/379) | +| FCL (Android) | ⚠️ | Currently broken, worked on previous versions, [read more](https://github.com/Skidamek/AutoModpack/issues/379) | +| Feather Client | ❌ | Unsupported - breaks modpack loading | +| Lunar Client | ❌ | Unsupported - breaks modpack loading | +| PCL2 | ❌ | Unsupported - breaks modpack loading | diff --git a/docs/compatibility/mods.mdx b/docs/compatibility/mods.mdx new file mode 100644 index 000000000..853c0d5a6 --- /dev/null +++ b/docs/compatibility/mods.mdx @@ -0,0 +1,6 @@ +AutoModpack should work with all minecraft modifications (it would be a bit bad modpack updater if it didn't). However, there are some exceptions and limitations that you should be aware of: + +- Majrusz's Mods: Requires a modified Majrusz Library to work with AutoModpack. [Github Issue](https://github.com/Skidamek/AutoModpack/issues/268). Or `forceCopyFilesToStandardLocation` in server config. +- [CITResewnNeoPatcher](https://modrinth.com/mod/cit-resewn-neopatcher): Requires to specify fabric version of CITResewn in `forceCopyFilesToStandardLocation` in server config, like (`/mods/citresewn-1.2.1+1.21.jar`). +- [ModSets](https://modrinth.com/mod/mod-sets): It's currently broken due to similarities in mod loading modification process. +- [Cesium](https://modrinth.com/mod/cesium): Cesium is currently incompatible due to wrong way of zstd packaging on AutoModpack side. It will be fixed soon. [GitHub Issue](https://github.com/Skidamek/AutoModpack/issues/384) \ No newline at end of file diff --git a/docs/compatibility/proxies.mdx b/docs/compatibility/proxies.mdx new file mode 100644 index 000000000..12b17a994 --- /dev/null +++ b/docs/compatibility/proxies.mdx @@ -0,0 +1,14 @@ +Most minecraft proxies won't work with AutoModpack due to early login stage packets. However Gate Lite is supported and works well with AutoModpack. Here is a list of known proxies and their compatibility: + +| Proxy Name | Compatibility | Notes | +|---------------------------------------------------|---------------|-------------| +| [Gate Lite](https://gate.minekube.com/guide/lite) | ✅ | Supported | +| Gate | ❌ | Unsupported | +| Velocity | ❌ | Unsupported | +| Waterfall | ❌ | Unsupported | +| BungeeCord | ❌ | Unsupported | + +When using Gate Lite, it's crucial to correctly configure `portToSend`. By default, clients attempt to connect to the modpack host using the same port they used to connect to your Minecraft server. However, when using a proxy like Gate, this port differs from your actual Minecraft server's port, preventing clients from connecting to download the modpack. + +Therefore, if your modpack is hosted with `bindPort` set to `-1`, `portToSend` must be set to the port from which your Minecraft server is accessible from (typically, this will be the same port on which Minecraft server listens). +Similarly, if `bindPort` is set to a specific port, `portToSend` must be set to the port from which modpack host is accessible from (typically, this will be the same as `bindPort`). \ No newline at end of file diff --git a/docs/configuration/_meta.json b/docs/configuration/_meta.json new file mode 100644 index 000000000..aed4f3058 --- /dev/null +++ b/docs/configuration/_meta.json @@ -0,0 +1,14 @@ +{ + "server-config.mdx": { + "name": "Server Configuration", + "icon": null + }, + "client-config.mdx": { + "name": "Client Configuration", + "icon": null + }, + "troubleshooting.mdx": { + "name": "Troubleshooting", + "icon": null + } +} diff --git a/docs/configuration/client-config.mdx b/docs/configuration/client-config.mdx new file mode 100644 index 000000000..ce86efb50 --- /dev/null +++ b/docs/configuration/client-config.mdx @@ -0,0 +1,10 @@ +### Client Config File + +`/automodpack/automodpack-client.json` + +| Name | Default Value | Description | +|---------------------|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `DO_NOT_CHANGE_IT` | `` | File version number used for auto conversion old config versions to new ones with automodpack update. | +| `selectedModpack` | | The main folder of the modpack that you want to play. Typing the name of the modpack here will cause it to be loaded. | +| `installedModpacks` | | A list of modpacks that are installed on the client. | +| `selfUpdater` | `false` | Turn on/off automodpack self-updates. This does not affect the mod's activity in installing modpacks. This does not disable AutoModpack version syncing with server | diff --git a/docs/configuration/server-config.mdx b/docs/configuration/server-config.mdx new file mode 100644 index 000000000..5cb096b1d --- /dev/null +++ b/docs/configuration/server-config.mdx @@ -0,0 +1,30 @@ +### Server Config File +`~/automodpack/automodpack-server.json` + +| Name | Default Value | Description | +|------------------------------------|----------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `DO_NOT_CHANGE_IT` | `` | File version number used for auto conversion old config versions to new ones with automodpack update. | +| `modpackName` | `""` | The name of the server modpack, shows while downloading modpack and that's how modpack directory gets called inside `~/automodpack/modpacks/`. | +| `modpackHost` | `true` | Starts modpack host server. | +| `generateModpackOnStart` | `true` | Automatically regenerate modpack metadata when the server starts. | +| `syncedFiles` | `["/mods/*.jar", "/kubejs/**", "!/kubejs/server_scripts/**", "/emotes/*"]` | A list of *relative paths* from the root folder of the Minecraft server that will be **synced to the modpack**. Use wildcards like `*` to include multiple files from this directory (e.g., `/mods/*.jar`). Or use `**` (double star) to recursively include all files and subdirectories from a folder (e.g., `/config/**`). Prefix a path with `!` to **exclude** it from syncing. **Note:** This does **not** copy the files; it only defines what will be available on the client side under `~/.minecraft/`. | +| `allowEditsInFiles` | `["/options.txt", "/config/**"]` | A list of files that clients are allowed to edit. In other words, files that are downloaded only one time and then ignored from updating. Configuration works exactly the same way `syncedFiles` does. | +| `forceCopyFilesToStandardLocation` | `[]` | A list of files that client will be forced to load from standard directory. By default most mods are loaded from separate automodpack directory, this list specifies files which will be copied to e.g. standard mods folder. **This will break seamless updates!** Use only when you have really good reason for it. Configuration works exactly the same way `syncedFiles` does. | +| `autoExcludeServerSideMods` | `true` | Automatically excludes server-side mods from the modpack. (Works only if mod developer specified environment type in mod metadata) | +| `autoExcludeUnnecessaryFiles` | `true` | Auto skip files which are: empty, hidden, temporary, disabled or backup. | +| `requireAutoModpackOnClient` | `true` | Whether or not this mod is optional for clients to join server. | +| `nagUnModdedClients` | `true` | If `true` clients without AutoModpack will be nagged with a chat message on join. To work requires `requireAutoModpackOnClient` to be `false`. | +| `nagMessage` | `"This server provides dedicated modpack through AutoModpack!"` | The message that will be displayed to clients without AutoModpack. To work requires `nagUnModdedClients` to be `true`. | +| `nagClickableMessage` | `"Click here to get the AutoModpack!"` | The clickable part of the message that will be displayed to clients without AutoModpack. To work requires `nagUnModdedClients` to be `true`. | +| `nagClickableLink` | `"https://modrinth.com/project/automodpack"` | The link that will be opened when the message is clicked. To work requires `nagUnModdedClients` to be `true`. | +| `bindAddress` | `""` | The address to which the modpack host server binds. Leave this empty to automatically determine a local address (typically `0.0.0.0` or `::0`). When `bindPort` is set to `-1`, this value is **ignored** and the modpack host will be bound to the same address as the Minecraft server, as specified in the `server.properties` file. | +| `bindPort` | `-1` | The port number on which the modpack host server listens. If set to `-1`, the modpack will be hosted directly on the port of your Minecraft server. | +| `addressToSend` | `""` | The address to the modpack host which will be used by clients to download the modpack. If empty, clients will use the same address they used to connect to the Minecraft server. (Do **not** include the port there, use `portToSend` instead) | +| `portToSend` | `-1` | The port number that is sent alongside the `addressToSend`. If set to `-1`, clients will use the same port they used to connect to the Minecraft server. | +| `disableInternalTLS` | `false` | Disables internal TLS management. If enabled, you must manage TLS externally, e.g. on a reverse proxy. When using this option, you have to use different `bindPort` than `-1` and you should consider setting `bindAddress` to a loopback address (e.g. `127.0.0.1`), so the unencrypted traffic between the modpack host and the reverse proxy isn't leaked. | +| `updateIpsOnEveryStart` | `false` | Updates `addressToSend` on every server start. Might be useful if you have dynamic IP address. (Use it only if you really need it!) | +| `bandwidthLimit` | `0` | Upload limit in Mbps that modpack host server is restricted to. (Value has to be an Integer, `0` - means unlimited) | +| `validateSecrets` | `true` | Makes modpack host validate and authorize modpack download attempts using unique secrets. | +| `secretLifetime` | `336` | Time in hours that a player's secret remains valid. | +| `selfUpdater` | `false` | Turn on/off all automodpack updates. This does not affect the mod's activity in installing modpacks. | +| `acceptedLoaders` | `[""]` | Allows players from different modloaders to connect to your server. (Use with caution, most mods work only on one loader) | diff --git a/docs/configuration/troubleshooting.mdx b/docs/configuration/troubleshooting.mdx new file mode 100644 index 000000000..d0c8b88a4 --- /dev/null +++ b/docs/configuration/troubleshooting.mdx @@ -0,0 +1,6 @@ +## Troubleshooting Config Issues +When finished editing configuration files, make sure to reload them by executing command `automodpack config reload` or restart the server/game. + +If you can't find the config files, make sure the client/server was started at least once, so that the files are generated. + +If values get restored to default it might mean that your config file is malformed make sure to use editor with JSON parser build-in. Or check in some online one e.g. https://jsonformatter.org/json-parser. diff --git a/docs/faq.mdx b/docs/faq.mdx new file mode 100644 index 000000000..48e7f5dae --- /dev/null +++ b/docs/faq.mdx @@ -0,0 +1,49 @@ +### Is it server side mod? +No, it's both. You need to have it installed on server as well as on client. + +### How do i add client only mods to the modpack? (e.g. server crashes with some mod but i want it for clients) +Take a look at [modpack creation page](techinicals/modpack-creation). + +### How to restrict access to my modpack? +Enable `validateSecrets` in the [config](configuration/server-config), turn on `online-mode` in the server.properties and enable whitelist or ban someone. + +### Does it work on lan (single-player world with option for other players to join)? +Yes. Just remember to generate modpack via command /`automodpack generate` and start modpack host /`automodpack host start`. + +### Does it work with single-player world shared via essential, world host, e4mc? +Likely no, most of these type of mods forward only minecraft packets. These mods would need to support automodpack protocol or just relay all tcp packets instead of limiting to minecraft protocol. + +### Can I use non modpack mods on client? +Yes, you can add any mod you want to use alongside downloaded modpack by just placing the mod into the standard mods folder. + +### How can I delete files from modpack? +Just delete file from server, or exclude it from sync, read about `syncedFiles` in [config](configuration/server-config) + +### Can I remove/disable non modpack files/mods from player use? +Not yet, it may come in the future. + +### Do I have to open any port on my router? +No, you don't need to. By default AutoModpack injects into minecraft networking I/O which reuses your minecraft server port. (e.g. 25565) + +If you want to use different port. Disable `hostModpackOnMinecraftPort` and change `hostPort` in [config](configuration/server-config). + +### What happens when I update AutoModpack version on server? +Client always try to sync to the server's version of AutoModpack. It updates or downgrades itself to the server's version if such is found on the Modrinth. + +### Why is the host modpack path so long? +There are plans to implement ability of adding more than just one, `main` modpack. + +### Which minecraft versions are supported? +All of the versions you see in the [latest release](https://github.com/Skidamek/AutoModpack/releases/latest). + +### Is my launcher supported? +Take a look at the [compatibility page](compatibility/launchers) for more information about supported launchers. + +### Does this mod updates my modpack mods to the latest versions? +No, it's out of scope for this project. This mod only synchronizes server modpack to the clients. All your mods on the server would have to still be updated manually. AutoModpack just makes sure client versions matches the server ones. + +### I found a bug, what should I do? +If you found a bug, please report it on the [issue tracker](https://github.com/Skidamek/AutoModpack/issues). + +### I found a security vulnerability, what should I do? +Please report it privately to the author on [Discord](https://discordapp.com/users/464522287618457631), we will try to resolve it ASAP. \ No newline at end of file diff --git a/docs/quick-start.mdx b/docs/quick-start.mdx new file mode 100644 index 000000000..f1f490499 --- /dev/null +++ b/docs/quick-start.mdx @@ -0,0 +1,35 @@ +So you want to start using AutoModpack? Great! Let's get you started. + +## Installation + +1. **Download AutoModpack**: Get the latest version of AutoModpack for your minecraft version from [Modrinth](https://modrinth.com/mod/automodpack) or [CurseForge](https://www.curseforge.com/minecraft/mc-mods/automodpack). +2. **Install AutoModpack**: Place the downloaded mod into your `mods` folder of your minecraft instance. +3. **Start your server**: Launch your minecraft server with AutoModpack installed. This will generate the initial modpack metadata. + +Now you are in most cases ready to go, at this point, its recommended to try connecting to your server with just the automodpack installed on the client and see if everything works. + +## First Connection +On first connection you will be prompted to verify the server's certificate fingerprint. This is a security measure to ensure that you are connecting to the correct server and not a malicious one. Read more about [certificate verification](technicals/certificate). +After successful verification, AutoModpack will asks you to confirm the modpack installation. Confirm and modpack should be downloaded and installed automatically. + +Now restart your game and your servers' modpack should be loaded and you should be able to connect to your server again but this time spawning in the overworld! + + +If you don't see your modpack mods in the mods folder, don't worry. Mods won't be installed to your standard mods folder, they will be installed in the `~/.minecraft/automodpack/modapcks/{your-modpack}/mods/` folder instead. There are some [good reasons for that](technicals/file-structure). + + +## Troubleshooting +If you encounter any issues at this point, here are some common troubleshooting steps: +- Make sure you are using the same version of AutoModpack on both server and client. +- Ensure that your server is running and accessible without AutoModpack. +- Check the server logs there might be some nudge about what went wrong. +- Read the [faq page](faq) for common questions and answers. + +If you are still having issues, join our [Discord server](https://discord.gg/hS6aMyeA9P) and create a post in the `#support` channel, we will try to help! + +## Next Steps + +Now that you have AutoModpack installed and working, you can start customizing your modpack. Here are some things you can do next: + +- Read the [modpack creation page](technicals/modpack-creation) to learn how to manage your modpack. +- Read the [configuration page](configuration/server-config) to learn how to configure AutoModpack to your needs. diff --git a/docs/sinytra-wiki.json b/docs/sinytra-wiki.json new file mode 100644 index 000000000..6f1d73b11 --- /dev/null +++ b/docs/sinytra-wiki.json @@ -0,0 +1,7 @@ +{ + "id": "automodpack", + "platforms": { + "modrinth": "automodpack", + "curseforge": "automodpack" + } +} \ No newline at end of file diff --git a/docs/technicals/_meta.json b/docs/technicals/_meta.json new file mode 100644 index 000000000..8d68a11b8 --- /dev/null +++ b/docs/technicals/_meta.json @@ -0,0 +1,22 @@ +{ + "connection.mdx": { + "name": "Connection", + "icon": null + }, + "certificate.mdx": { + "name": "Certificate Handling", + "icon": null + }, + "modpack-creation.mdx": { + "name": "Modpack Creation", + "icon": null + }, + "file-structure.mdx": { + "name": "File Structure", + "icon": null + }, + "modpack-hosting.mdx": { + "name": "Modpack Hosting", + "icon": null + } +} diff --git a/docs/technicals/certificate.mdx b/docs/technicals/certificate.mdx new file mode 100644 index 000000000..ecde1d062 --- /dev/null +++ b/docs/technicals/certificate.mdx @@ -0,0 +1,45 @@ +### How to verify the certificate fingerprint? +To verify, simply **copy the fingerprint from your server console to the game.** This is a one-time verification, meaning you won't need to repeat it after the initial connection. This process helps prevent security threats like [Man-in-the-middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). The fingerprint is the same for everyone on your server and it never changes, its recommended to share it with players ahead of time. + +If you can't find the fingerprint in the console, you can retrieve it at any time using the `/automodpack host fingerprint` [command](../commands/commands). + +However please do not think of it like a password to the modpack, its not a password or any secret, its a public verifiable piece of server certificate, **anyone could download** your modpack without previous knowledge of such fingerprint e.g. by bypassing this check with `I AM INCREDIBLY STUPID`. (don't do it) + +To provide modpack for only authorized/whitelisted players, use `validateSecrets` option in the [server config](../configuration/server-config) (its enabled by default). + + +If you don't want players to explicitly verify the certificate manually and you own a domain (required), you can provide your own CA signed certificate. + +### How to provide your own CA signed certificate? + +You can use tools like [Certbot](https://eff-certbot.readthedocs.io/en/stable/install.html). + +After obtaining the certificate, on the server in the `~/automodpack/.private/` directory, replace the `cert.crt` (with the full chain certificate) and `key.pem` files ([key has to be in PKCS#8 (PEM) format](https://netty.io/wiki/sslcontextbuilder-and-private-key.html)) - here be cautious as interception of these files may result in impersonation of the server, [read more](https://security.stackexchange.com/a/16694). +If you're hosting modpack on different sub/domain than your minecraft server, make sure that your certificate verifies both of the sub/domains. + +### Little tutorial on how to obtain a certificate using Certbot + +Install Certbot on your pc or server, then run the example command and follow further certbot instructions to obtain a certificate for your domain: + +```bash +# certbot certonly --manual --preferred-challenges dns -d -d +``` +If you're hosting modpack on the same port as your minecraft server, in most cases these domains will match, if so you don't need to provide the second domain. + + +Never copy-paste random commands from the internet, always read the documentation of the tool you're using! + + +After obtaining the certificate, the files you need are `fullchain.pem` (the full chain certificate, copy and rename to `cert.crt`) and `privkey.pem` (the private key, copy and rename to `key.pem`). + +### Wait but why do I need all this? Its just a modpack for my friends! + +If someone could easily take control over the automodpack connection, they could download on your (or your friends) computers anything they want. +Minecraft isn't sandboxed in any way and mods **can run any arbitrary code** so if someone could easily inject some malicious piece of code to any automodpack modpack no matter who the victim is, that would be a huge win for them anyway, they could steal passwords from your browser, accounts to various services or even delete your very important folder with funny cat memes, there are many possibilities. +That's why i believe it's important to have some security measures. + +### Hmm... ok but nobody knows about my server besides my friends, why should I care? + +Even if you think that nobody knows about your server, it may not be true. There are many ways how someone could find out about your server. +For example there are many minecraft server scanners which scan the entire internet for minecraft servers, and you could be a victim if your server would be found vulnerable and we wouldn't verify the certificate. +However nothing we do here stops someone from taking control over your server in different ways, (e.g. gaining access to it via ssh or your server hosting panel) that's why it's very important that you as a server owner take your security seriously and use strong passwords, enable two-factor authentication and keep your server software up to date. diff --git a/docs/technicals/connection.mdx b/docs/technicals/connection.mdx new file mode 100644 index 000000000..3ca995fb3 --- /dev/null +++ b/docs/technicals/connection.mdx @@ -0,0 +1,35 @@ +### Encryption + +Modpack download connection is secured using TLS 1.3. + +This is the same security standard used by HTTPS, the protocol which you're using all the time to browse the web (even now!). + +TLS has method of verifying the server's identity using a certificate which is crucial to prevent attacks such as [Man-in-the-middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack). + +That's why AutoModpack requires you to verify the server's certificate fingerprint when connecting to the server for the first time. Read [how to verify the certificate fingerprint](certificate) for more details. + +### Direct Downloads + +AutoModpack uses direct download links from Modrinth and CurseForge APIs to download most of your modpack files. +This means that the mod authors get credit for every download. + +However if file you are providing in the modpack is not available on Modrinth or CurseForge, AutoModpack will download it (also directly) but from your server. + +### Compression + +To speed up the download, AutoModpack compresses the modpack files using [Zstandard](https://facebook.github.io/zstd/) compression algorithm. +This algorithm is very fast and provides great compression ratio, which means that the modpack files are smaller and faster to download. +This is especially useful for larger modpacks or slower internet connections. +However this only applies to files downloaded from your server. + +### Authorization + + +Do not confuse this with [certificate fingerprint verification](certificate), which is used to verify the server's identity. + + +AutoModpack uses a simple authorization mechanism to prevent unauthorized access to your modpack. +When you connect to the server, in the background AutoModpack generates a random unique secret for each player. This secret is then send to the player and used to authorize the player to download the modpack files. +Every time you reconnect to the server, the old secret is invalidated and a new one is generated. +This prevents unauthorized access to your modpack files and ensures that only whitelisted and not banned players can download the modpack. +If you don't want to use this feature, you can disable it (`validateSecrets`) in the [server config](../configuration/server-config). diff --git a/docs/technicals/file-structure.mdx b/docs/technicals/file-structure.mdx new file mode 100644 index 000000000..d22282b7e --- /dev/null +++ b/docs/technicals/file-structure.mdx @@ -0,0 +1,21 @@ +All of the AutoModpack files are kept inside `~/automodpack/` folder. + +### Server +Modpack is generated from files inside `~/automodpack/host-modpack/main/` and/or `syncedFiles` (read [config](../configuration/server-config)) which translates to `~/.minecraft/` (root minecraft instance) folder on client. + +Modpack generation means creation of `~/automodpack/host-modpack/automodpack-content.json` which contains metadata of every single file of the modapck. You **should NOT** touch this file manually, edit config instead. + +### Client +All of downloaded modpacks are kept inside `~/automodpack/modpacks/`. + +All of the selected modpack files are copied to `~/.minecraft/` besides **mods** (with some exceptions, due to mod loader limitations) + +If detected, AutoModpack also tries to get rid of most of if not all of duplicated mods from your standard mods folder in favor of AutoModpack's mods folder. + +It shouldn't cause any crashes, but if you notice that automodpack removes some dependency causing game to crash, please report it! + + +Mods are separated for reasons. Such approach mitigates common drawbacks of placing all modpack mods into the standard mods folder, like: +- **Mod conflict crashes**: It won't resolve them, but it atleast gives the server owner ability to remotely remove or fix conflicting mods without manual intervention on the client side. +- **Debugging**: Its easier to see what mods are part of the modpack and what are not. Since clients can add their own mods to the standard mods folder, it's easier to debug when something breaks or conflicts. +- **Reboots**: If all of the modpack mods were placed into the standard mods folder, it would require a reboot to update the modpack mods. Now it can be done seamlessly on boot without any restart! \ No newline at end of file diff --git a/docs/technicals/modpack-creation.mdx b/docs/technicals/modpack-creation.mdx new file mode 100644 index 000000000..a95f58ae9 --- /dev/null +++ b/docs/technicals/modpack-creation.mdx @@ -0,0 +1,17 @@ +**Yes, you can add *anything* to your modpack.** + +#### Two ways of adding content to the modpack. + +- To re-use already existing files on server use `syncedFiles` read more in [config](../configuration/server-config). As an example with default config it creates modpack containing *every* mod (file ending with .jar) from server `~/mods/` folder. + +- To add more files to modpack use separate directory `~/automodpack/host-modpack/main/`. +For example to add more mods create folder `mods` and place there mods so that will be `~/automodpack/host-modpack/main/mods/`**`your-mod.jar`**. +Or to add resourcepacks analogically create folder `resourcepacks` and place there resourcepacks so that will be `~/automodpack/host-modpack/main/resourcepacks/`**`your-resourcepack.zip`**. + + +Do not place in the modpack cache files, like connector's `.connector` directory, its not supposed to be provided within modpack and it break seamless/reboot-less updates. + + +Both of these methods translate to the `~/.minecraft/` on client side (root directory of minecraft instance). + +Remember to regenerate the modpack using `/automodpack generate` (see [commands](../commands/commands)) \ No newline at end of file diff --git a/docs/technicals/modpack-hosting.mdx b/docs/technicals/modpack-hosting.mdx new file mode 100644 index 000000000..5e019b673 --- /dev/null +++ b/docs/technicals/modpack-hosting.mdx @@ -0,0 +1,2 @@ +By default AutoModpack hosts your modpack on your minecraft server port (e.g. 25565). This means that you don't need to open any other port on your router/firewall. +If you want to use a different port, change `bindPort` in [config](../configuration/server-config). diff --git a/gradle.properties b/gradle.properties index 8076bac0c..34af6929e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,21 +1,16 @@ org.gradle.jvmargs = -Xmx8G # Run clean task before building if doesn't work -org.gradle.parallel = false +org.gradle.parallel = true org.gradle.caching = true -org.gradle.caching.debug = false org.gradle.configureondemand = true -fabric_versions = 1.18.2, 1.19.2, 1.19.4, 1.20.1, 1.20.4, 1.20.6, 1.21.1, 1.21.3, 1.21.4 -neoforge_versions = 1.20.4, 1.20.6, 1.21.1, 1.21.3, 1.21.4 -forge_versions = 1.18.2, 1.19.2, 1.19.4, 1.20.1 - core_modules = core, fabric-core, fabric-15, fabric-16, forge-fml40, forge-fml47, neoforge-fml2, neoforge-fml4 -loader_fabric = 0.15.11 -mixin_extras = 0.5.0-rc.2 +deps.fabric-loader = 0.15.11 +deps.mixin-extras = 0.5.0-rc.2 -mod_id = automodpack +mod.id = automodpack mod_name = AutoModpack -mod_version = 4.0.0-beta36 -mod_group = pl.skidam.automodpack -mod_description = Enjoy a seamless modpack installation process and effortless updates with a user-friendly solution that simplifies management, making your gaming experience a breeze. +mod_version = 4.0.0-beta38 +mod.group = pl.skidam.automodpack +mod.description = Enjoy a seamless modpack installation process and effortless updates with a user-friendly solution that simplifies management, making your gaming experience a breeze. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cea7a793a..ff23a68d7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java index 9137ccd74..f5471d0e5 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java @@ -52,19 +52,22 @@ private void updateAll() { selectedModpackDir = optionalSelectedModpackDir.get(); InetSocketAddress selectedModpackAddress = null; InetSocketAddress selectedServerAddress = null; + boolean requiresMagic = true; // Default to true if (!clientConfig.selectedModpack.isBlank() && clientConfig.installedModpacks.containsKey(clientConfig.selectedModpack)) { var entry = clientConfig.installedModpacks.get(clientConfig.selectedModpack); selectedModpackAddress = entry.hostAddress; selectedServerAddress = entry.serverAddress; + requiresMagic = entry.requiresMagic; } // Only selfupdate if no modpack is selected if (selectedModpackAddress == null) { SelfUpdater.update(); + CustomFileUtils.deleteDummyFiles(Path.of(System.getProperty("user.dir")), null); } else { Secrets.Secret secret = SecretsStore.getClientSecret(clientConfig.selectedModpack); - Jsons.ModpackAddresses modpackAddresses = new Jsons.ModpackAddresses(selectedModpackAddress, selectedServerAddress); + Jsons.ModpackAddresses modpackAddresses = new Jsons.ModpackAddresses(selectedModpackAddress, selectedServerAddress, requiresMagic); var optionalLatestModpackContent = ModpackUtils.requestServerModpackContent(modpackAddresses, secret, false); var latestModpackContent = ConfigTools.loadModpackContent(selectedModpackDir.resolve(hostModpackContentFile.getFileName())); @@ -115,24 +118,20 @@ private void loadConfigs() { // load client config if (clientConfigOverride == null) { - var clientConfigVersion = ConfigTools.loadCheck(clientConfigFile, Jsons.VersionConfigField.class); + var clientConfigVersion = ConfigTools.softLoad(clientConfigFile, Jsons.VersionConfigField.class); if (clientConfigVersion != null) { - // Update the configs schemes to not crash the game if loaded with old config! if (clientConfigVersion.DO_NOT_CHANGE_IT == 1) { + // Update the configs schemes to not crash the game if loaded with old config! var clientConfigV1 = ConfigTools.load(clientConfigFile, Jsons.ClientConfigFieldsV1.class); - // update to v2 - just delete the installedModpacks - if (clientConfigV1 != null) { - clientConfigV1.installedModpacks = null; - clientConfigV1.DO_NOT_CHANGE_IT = 2; + if (clientConfigV1 != null) { // update to V2 - just delete the installedModpacks clientConfigVersion.DO_NOT_CHANGE_IT = 2; + clientConfigV1.DO_NOT_CHANGE_IT = 2; + clientConfigV1.installedModpacks = null; } + ConfigTools.save(clientConfigFile, clientConfigV1); LOGGER.info("Updated client config version to {}", clientConfigVersion.DO_NOT_CHANGE_IT); } - -// if (clientConfigVersion.DO_NOT_CHANGE_IT == 2) { -// // Noice! -// } } clientConfig = ConfigTools.load(clientConfigFile, Jsons.ClientConfigFieldsV2.class); @@ -144,8 +143,38 @@ private void loadConfigs() { clientConfig = ConfigTools.load(clientConfigOverride, Jsons.ClientConfigFieldsV2.class); } + var serverConfigVersion = ConfigTools.softLoad(serverConfigFile, Jsons.VersionConfigField.class); + if (serverConfigVersion != null) { + if (serverConfigVersion.DO_NOT_CHANGE_IT == 1) { + // Update the configs schemes to make this update not as breaking as it could be + var serverConfigV1 = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV1.class); + var serverConfigV2 = ConfigTools.softLoad(serverConfigFile, Jsons.ServerConfigFieldsV2.class); + if (serverConfigV1 != null && serverConfigV2 != null) { + serverConfigVersion.DO_NOT_CHANGE_IT = 2; + serverConfigV2.DO_NOT_CHANGE_IT = 2; + + if (serverConfigV1.hostIp.isBlank()) { + serverConfigV2.addressToSend = ""; + } else { + serverConfigV2.addressToSend = AddressHelpers.parse(serverConfigV1.hostIp).getHostString(); + } + + if (serverConfigV1.hostModpackOnMinecraftPort) { + serverConfigV2.bindPort = -1; + serverConfigV2.portToSend = -1; + } else { + serverConfigV2.bindPort = serverConfigV1.hostPort; + serverConfigV2.portToSend = serverConfigV1.hostPort; + } + } + + ConfigTools.save(serverConfigFile, serverConfigV2); + LOGGER.info("Updated server config version to {}", serverConfigVersion.DO_NOT_CHANGE_IT); + } + } + // load server config - serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFields.class); + serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV2.class); if (serverConfig != null) { // Add current loader to the list diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/SelfUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/SelfUpdater.java index 9a961a71d..889efee8b 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/SelfUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/SelfUpdater.java @@ -83,21 +83,26 @@ public static boolean update(Jsons.ModpackContentFields serverModpackContent) { continue; } - boolean currentBeta = AM_VERSION.contains("-beta"); - boolean remoteBeta = fileVersion.contains("-beta"); + boolean currentIsBeta = AM_VERSION.contains("-beta"); + boolean remoteIsBeta = fileVersion.contains("-beta"); String[] currentVersionSplit = AM_VERSION.split("-beta"); String[] remoteVersionSplit = fileVersion.split("-beta"); + int remoteBeta = -1; + if (remoteIsBeta) { + remoteBeta = Integer.parseInt(remoteVersionSplit[1]); + } + // Removes '-betaX' if exists // Removes '.' - dots - to then parse it as number String OUR_VERSION = currentVersionSplit[0].replace(".", ""); - String LATEST_VERSION = remoteVersionSplit[0].replace(".", ""); + String REMOTE_VERSION = remoteVersionSplit[0].replace(".", ""); // Compare versions as numbers if (!gettingServerVersion) { try { - if (Integer.parseInt(OUR_VERSION) > Integer.parseInt(LATEST_VERSION)) { + if (Integer.parseInt(OUR_VERSION) > Integer.parseInt(REMOTE_VERSION)) { message = "You are using pre-released or beta version of AutoModpack: " + AM_VERSION + " latest stable version is: " + automodpack.fileVersion(); break; // Break, checked version is lower than installed, meaning that higher version doesn't exist. } @@ -105,19 +110,19 @@ public static boolean update(Jsons.ModpackContentFields serverModpackContent) { LOGGER.error("Failed to parse version numbers: " + e); } - if (currentBeta && remoteBeta) { + if (currentIsBeta && remoteIsBeta) { if (Integer.parseInt(currentVersionSplit[1]) > Integer.parseInt(remoteVersionSplit[1])) { message = "You are using pre-released or beta version of AutoModpack: " + AM_VERSION + " latest stable version is: " + automodpack.fileVersion(); break; // Break, checked version is lower than installed, meaning that higher version doesn't exist. } } - if (!currentBeta && remoteBeta) { + if (!currentIsBeta && remoteIsBeta) { message = "You are using stable version of AutoModpack: " + AM_VERSION + " latest pre-released or beta version is: " + automodpack.fileVersion(); continue; } - if (currentBeta && !remoteBeta) { + if (currentIsBeta && !remoteIsBeta) { message = "You are using pre-released or beta version of AutoModpack: " + AM_VERSION + " latest stable version is: " + automodpack.fileVersion(); continue; } @@ -143,14 +148,41 @@ public static boolean update(Jsons.ModpackContentFields serverModpackContent) { return false; } + public static boolean validUpdate(ModrinthAPI automodpack) { + String[] remoteVersionSplit = automodpack.fileVersion().split("-beta"); + + int remoteBeta = -1; + boolean remoteIsBeta = false; + if (remoteVersionSplit.length > 1) { + remoteIsBeta = true; + remoteBeta = Integer.parseInt(remoteVersionSplit[1]); + } + + // Removes '-betaX' if exists + // Removes '.' - dots - to then parse it as number + String REMOTE_VERSION = remoteVersionSplit[0].replace(".", ""); + + // Don't allow downgrades pass 4.0.0-beta38 + if (Integer.parseInt(REMOTE_VERSION) >= 400 && (!remoteIsBeta || remoteBeta >= 38)) { + return true; + } + + LOGGER.error("Downgrading AutoModpack to version {} is strongly discouraged and disabled from auto-server-syncing. To protect against potential security vulnerabilities, please use a newer version.", automodpack.fileVersion()); + return false; + } + public static void installModVersion(ModrinthAPI automodpack) { + if (!validUpdate(automodpack)) { + return; + } + Path automodpackUpdateJar = automodpackDir.resolve(automodpack.fileName()); Path newAutomodpackJar; try { DownloadManager downloadManager = new DownloadManager(); - new ScreenManager().download(downloadManager, "AutoModapck " + automodpack.fileVersion()); + new ScreenManager().download(downloadManager, "AutoModpack " + automodpack.fileVersion()); // Download it downloadManager.download( diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java index 0087785fa..1fdb63a78 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUpdater.java @@ -15,6 +15,7 @@ import java.net.SocketTimeoutException; import java.nio.file.*; import java.util.*; +import java.util.stream.Collectors; import java.util.stream.Stream; import static pl.skidam.automodpack_core.GlobalVariables.*; @@ -518,8 +519,13 @@ private boolean applyModpack() throws Exception { boolean needsRestart2 = ModpackUtils.fixNestedMods(conflictingNestedMods, standardModList); Set ignoredFiles = ModpackUtils.getIgnoredFiles(conflictingNestedMods, workaroundMods); + Set forceCopyFiles = modpackContent.list.stream() + .filter(item -> item.forceCopy) + .map(item -> item.file) + .collect(Collectors.toSet()); + // Remove duplicate mods - ModpackUtils.RemoveDupeModsResult removeDupeModsResult = ModpackUtils.removeDupeMods(modpackDir, standardModList, modpackModList, ignoredFiles, workaroundMods); + ModpackUtils.RemoveDupeModsResult removeDupeModsResult = ModpackUtils.removeDupeMods(modpackDir, standardModList, modpackModList, ignoredFiles, workaroundMods, forceCopyFiles); boolean needsRestart3 = removeDupeModsResult.requiresRestart(); // Remove rest of mods not for standard mods directory @@ -533,16 +539,20 @@ private Set getFilesNotToCopy(Set filesNotToCopy = new HashSet<>(); // Make list of files which we do not copy to the running directory - for (Jsons.ModpackContentFields.ModpackContentItem modpackContentItem : modpackContentItems) { + for (Jsons.ModpackContentFields.ModpackContentItem item : modpackContentItems) { + if (item.forceCopy) { + continue; + } + // We only want to copy editable file if its downloaded first time // So we add to ignored any other editable file - if (modpackContentItem.editable && !newDownloadedFiles.contains(modpackContentItem.file)) { - filesNotToCopy.add(modpackContentItem.file); + if (item.editable && !newDownloadedFiles.contains(item.file)) { + filesNotToCopy.add(item.file); } // We only want to copy mods which need a workaround - if (modpackContentItem.type.equals("mod") && !workaroundMods.contains(modpackContentItem.file)) { - filesNotToCopy.add(modpackContentItem.file); + if (item.type.equals("mod") && !workaroundMods.contains(item.file)) { + filesNotToCopy.add(item.file); } } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java index 6b91cf8ff..c909efa09 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/client/ModpackUtils.java @@ -225,8 +225,7 @@ public record RemoveDupeModsResult(boolean requiresRestart, Set modsToKeep // Returns true if removed any mod from standard mods folder // If the client mod is a duplicate of what modpack contains then it removes it from client so that you dont need to restart game just when you launched it and modpack get updated - basically having these mods separately allows for seamless updates // If you have client mods which require specific mod which is also a duplicate of what modpack contains it should stay - public static RemoveDupeModsResult removeDupeMods(Path modpackDir, Collection standardModList, Collection modpackModList, Set ignoredMods, Set workaroundMods) throws IOException { - + public static RemoveDupeModsResult removeDupeMods(Path modpackDir, Collection standardModList, Collection modpackModList, Set ignoredMods, Set workaroundMods, Set forceCopyFiles) throws IOException { var dupeMods = ModpackUtils.getDupeMods(modpackDir, ignoredMods, standardModList, modpackModList); if (dupeMods.isEmpty()) { @@ -260,12 +259,14 @@ public static RemoveDupeModsResult removeDupeMods(Path modpackDir, Collection providesIDs = modpackMod.providesIDs(); List IDs = new ArrayList<>(providesIDs); IDs.add(modId); boolean isDependent = IDs.stream().anyMatch(idsToKeep::contains); - boolean isWorkaround = workaroundMods.contains(CustomFileUtils.formatPath(standardModPath, MODS_DIR.getParent())); + boolean isWorkaround = workaroundMods.contains(formatedPath); + boolean isForceCopy = forceCopyFiles.contains(formatedPath); if (isDependent) { Path newStandardModPath = standardModPath.getParent().resolve(modpackModPath.getFileName()); @@ -279,7 +280,7 @@ public static RemoveDupeModsResult removeDupeMods(Path modpackDir, Collection getModInfosFromFingerPrints(Map hashes) { + private static CurseForgeAPI parseJsonObject(JsonObject JSONObject, Map hashes) { if (JSONObject == null) { LOGGER.error("CurseForgeAPI Can't parse null object"); return null; diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/platforms/ModrinthAPI.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/platforms/ModrinthAPI.java index 2aa98d1d1..bbaf5b50b 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/platforms/ModrinthAPI.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/platforms/ModrinthAPI.java @@ -125,32 +125,7 @@ public static List getModsInfosFromListOfSHA1(List listOfSh return modrinthAPIList; } - // https://docs.modrinth.com/#tag/version-files - public static ModrinthAPI getModInfoFromSHA1(String sha1) { - if (sha1 == null || sha1.isEmpty()) { - return null; - } - - String requestUrl = BASE_URL + "/version_file/" + sha1 + "?algorithm=sha1"; - requestUrl = requestUrl.replaceAll("\"", "%22"); // so important! - - try { - JsonObject JSONObject = Json.fromUrl(requestUrl); - return parseJsonObject(JSONObject, List.of(sha1)); - } catch (IndexOutOfBoundsException e) { - LOGGER.warn("Something gone wrong while getting info from Modrinth API: {}", requestUrl); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - -// public static void main(String[] args) { -// var ww = getModsInfosFromListOfSHA1(List.of("2ff512a70c437c20523de01ea95b6fc9b164a5c0")); -// ww.forEach(System.out::println); -// } - - public static ModrinthAPI parseJsonObject(JsonObject JSONObject, List listOfSha1) { + private static ModrinthAPI parseJsonObject(JsonObject JSONObject, List listOfSha1) { if (JSONObject == null) { return null; } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/DownloadManager.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/DownloadManager.java index 6db5cc58b..e063d6edb 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/DownloadManager.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/DownloadManager.java @@ -230,8 +230,13 @@ public long getTotalBytesRemaining() { return bytesToDownload - bytesDownloaded; } - public float getTotalPercentageOfFileSizeDownloaded() { - return (float) bytesDownloaded / bytesToDownload * 100; + public int getTotalPercentageOfFileSizeDownloaded() { + if (bytesDownloaded == 0 || bytesToDownload == 0) { + return 0; + } + + int percentage = (int) (bytesDownloaded * 100 / bytesToDownload); + return Math.max(0, Math.min(100, percentage)); } public String getStage() { diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/FetchManager.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/FetchManager.java index 04f22b4e1..3d19baf6d 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/FetchManager.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/FetchManager.java @@ -40,7 +40,7 @@ public void fetch() { List mo = new ArrayList<>(); for (Map.Entry entry : fetchDatas.entrySet()) { FetchData fetchData = entry.getValue().fetchData(); - if (fetchData.murmur != null) { + if (fetchData.murmur != null && !fetchData.murmur.isBlank()) { cf.put(fetchData.sha1, fetchData.murmur); } diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SpeedMeter.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SpeedMeter.java index 8289164ab..8867e461e 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SpeedMeter.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/utils/SpeedMeter.java @@ -6,7 +6,7 @@ public class SpeedMeter { private final DownloadManager downloadManager; private final ConcurrentSkipListMap bytesDownloadedPerSec = new ConcurrentSkipListMap<>(); - private static final int MAX_ENTRIES = 5; + private static final int MAX_ENTRIES = 3; public SpeedMeter(DownloadManager downloadManager) { this.downloadManager = downloadManager; @@ -26,20 +26,18 @@ public synchronized void addDownloadedBytes(long newBytes) { } /** - * Get the download speed in bytes per second. + * Get the average download speed in bytes per second from the last few seconds. */ - public synchronized long getCurrentSpeedInBytes() { - long lastTimeBucket = System.currentTimeMillis() / 1000 * 1000 - 1000; + public long getAverageSpeedOfLastFewSeconds(int seconds) { + long totalBytes = 0; + int count = 0; - Long value = -1L; - - if (bytesDownloadedPerSec.containsKey(lastTimeBucket)) { - value = bytesDownloadedPerSec.get(lastTimeBucket); - } else if (bytesDownloadedPerSec.containsKey(lastTimeBucket - 1000)) { - value = bytesDownloadedPerSec.get(lastTimeBucket - 1000); + for (Long bytes : bytesDownloadedPerSec.values()) { + totalBytes += bytes; + count++; } - return value != null ? value : -1; + return count >= seconds ? totalBytes / count : -1; } /** @@ -47,7 +45,7 @@ public synchronized long getCurrentSpeedInBytes() { */ public long getETAInSeconds() { long totalBytesRemaining = downloadManager.getTotalBytesRemaining(); - long speed = getCurrentSpeedInBytes(); + long speed = getAverageSpeedOfLastFewSeconds(3); if (speed <= 0) { return -1; @@ -70,13 +68,18 @@ public static String formatDownloadSpeedToMbps(long currentSpeedInBytes) { } /** - * Format ETA into HH:MM:SS. + * Format ETA into MM:SS format or HH:MM:SS format. */ public static String formatETAToSeconds(long seconds) { - if (seconds < 0) { + seconds++; // Increment by 1 to avoid showing 00:00:00 for 0 seconds + if (seconds < 1) { return "-1"; } + if (seconds < 3600) { + return String.format("%02d:%02d", seconds / 60, seconds % 60); + } + return String.format("%02d:%02d:%02d", seconds / 3600, (seconds % 3600) / 60, seconds % 60); } } diff --git a/loader/fabric/15/gradle.properties b/loader/fabric/15/gradle.properties index 83f11cd8c..146492225 100644 --- a/loader/fabric/15/gradle.properties +++ b/loader/fabric/15/gradle.properties @@ -1,4 +1 @@ -minecraft_version=1.20.1 -yarn_mappings=1.20.1+build.10 -loom.platform=fabric -loader_fabric=0.15.11 \ No newline at end of file +deps.fabric=0.15.11 \ No newline at end of file diff --git a/loader/fabric/16/gradle.properties b/loader/fabric/16/gradle.properties index 117c56d7a..5ebca380c 100644 --- a/loader/fabric/16/gradle.properties +++ b/loader/fabric/16/gradle.properties @@ -1,4 +1 @@ -minecraft_version=1.20.1 -yarn_mappings=1.20.1+build.10 -loom.platform=fabric -loader_fabric=0.16.9 \ No newline at end of file +deps.fabric=0.16.14 \ No newline at end of file diff --git a/loader/fabric/core/gradle.properties b/loader/fabric/core/gradle.properties index 83f11cd8c..146492225 100644 --- a/loader/fabric/core/gradle.properties +++ b/loader/fabric/core/gradle.properties @@ -1,4 +1 @@ -minecraft_version=1.20.1 -yarn_mappings=1.20.1+build.10 -loom.platform=fabric -loader_fabric=0.15.11 \ No newline at end of file +deps.fabric=0.15.11 \ No newline at end of file diff --git a/loader/fabric/core/src/main/resources/fabric.mod.json b/loader/fabric/core/src/main/resources/fabric.mod.json index d52bd437a..591e99aa8 100644 --- a/loader/fabric/core/src/main/resources/fabric.mod.json +++ b/loader/fabric/core/src/main/resources/fabric.mod.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "id": "automodpack-bootstrap", + "id": "automodpack_bootstrap", "version": "1.0.0", "name": "AutoModpack bootstrap", "description": "", diff --git a/loader/forge/fml40/gradle.properties b/loader/forge/fml40/gradle.properties index adf61db65..b6ad2295f 100644 --- a/loader/forge/fml40/gradle.properties +++ b/loader/forge/fml40/gradle.properties @@ -1,4 +1 @@ -minecraft_version=1.18.2 -yarn_mappings=1.18.2+build.4 -loom.platform=forge -loader_forge=40.2.10 \ No newline at end of file +deps.forge=1.18.2-40.3.10 \ No newline at end of file diff --git a/loader/forge/fml40/src/main/resources/META-INF/mods.toml b/loader/forge/fml40/src/main/resources/META-INF/mods.toml index 9ba75c843..a8fef7558 100644 --- a/loader/forge/fml40/src/main/resources/META-INF/mods.toml +++ b/loader/forge/fml40/src/main/resources/META-INF/mods.toml @@ -3,7 +3,7 @@ loaderVersion = "[1,)" license = "LGPLv3" [[mods]] -modId = "automodpack-bootstrap" +modId = "automodpack_bootstrap" version = "1.0.0" displayName = "AutoModpack bootstrap" displayURL = "https://modrinth.com/mod/automodpack" diff --git a/loader/forge/fml47/gradle.properties b/loader/forge/fml47/gradle.properties index 5371a7bc7..bde194594 100644 --- a/loader/forge/fml47/gradle.properties +++ b/loader/forge/fml47/gradle.properties @@ -1,4 +1 @@ -minecraft_version=1.20.1 -yarn_mappings=1.20.1+build.10 -loom.platform=forge -loader_forge=47.1.3 \ No newline at end of file +deps.forge=1.20.1-47.1.3 diff --git a/loader/forge/fml47/src/main/resources/META-INF/mods.toml b/loader/forge/fml47/src/main/resources/META-INF/mods.toml index 9ba75c843..a8fef7558 100644 --- a/loader/forge/fml47/src/main/resources/META-INF/mods.toml +++ b/loader/forge/fml47/src/main/resources/META-INF/mods.toml @@ -3,7 +3,7 @@ loaderVersion = "[1,)" license = "LGPLv3" [[mods]] -modId = "automodpack-bootstrap" +modId = "automodpack_bootstrap" version = "1.0.0" displayName = "AutoModpack bootstrap" displayURL = "https://modrinth.com/mod/automodpack" diff --git a/loader/loader-core.gradle.kts b/loader/loader-core.gradle.kts index 8b88d1d45..60824d979 100644 --- a/loader/loader-core.gradle.kts +++ b/loader/loader-core.gradle.kts @@ -3,9 +3,9 @@ plugins { } base { - archivesName = property("mod_id") as String + "-" + project.name + archivesName = property("mod.id") as String + "-" + project.name version = property("mod_version") as String - group = property("mod_group") as String + group = property("mod.group") as String } repositories { @@ -17,15 +17,14 @@ dependencies { // our needed dependencies implementation("com.google.code.gson:gson:2.10.1") - implementation("org.apache.logging.log4j:log4j-core:2.20.0") + implementation("org.apache.logging.log4j:log4j-core:2.19.0") implementation("org.tomlj:tomlj:1.1.1") } -java { - // leave it on java 17 to be compatible with older versions and we dont really need 21 there anyway +java { // leave it on java 17 to be compatible with older versions and we dont really need 21 there anyway sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 - + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) withSourcesJar() } diff --git a/loader/loader-fabric-core.gradle.kts b/loader/loader-fabric-core.gradle.kts index 273276445..8f0a1c3a0 100644 --- a/loader/loader-fabric-core.gradle.kts +++ b/loader/loader-fabric-core.gradle.kts @@ -2,13 +2,13 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java - id("com.github.johnrengelman.shadow") + id("com.gradleup.shadow") } base { - archivesName = property("mod_id") as String + "-" + project.name + archivesName = property("mod.id") as String + "-" + project.name version = property("mod_version") as String - group = property("mod_group") as String + group = property("mod.group") as String } repositories { @@ -23,14 +23,14 @@ dependencies { compileOnly(project(":loader-fabric-16")) compileOnly("com.google.code.gson:gson:2.10.1") - compileOnly("org.apache.logging.log4j:log4j-core:2.20.0") + compileOnly("org.apache.logging.log4j:log4j-core:2.8.1") implementation("org.tomlj:tomlj:1.1.1") implementation("org.bouncycastle:bcpkix-jdk18on:1.80") implementation("com.github.luben:zstd-jni:1.5.7-3") - implementation("org.apache.httpcomponents.client5:httpclient5:5.4.4") + implementation("org.apache.httpcomponents.client5:httpclient5:5.5") - compileOnly("net.fabricmc:fabric-loader:${property("loader_fabric")}") + compileOnly("net.fabricmc:fabric-loader:${property("deps.fabric")}") } configurations { @@ -82,7 +82,7 @@ tasks.named("shadowJar") { java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 - + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) withSourcesJar() } diff --git a/loader/loader-fabric.gradle.kts b/loader/loader-fabric.gradle.kts index 50d47b0dc..8c58c3c38 100644 --- a/loader/loader-fabric.gradle.kts +++ b/loader/loader-fabric.gradle.kts @@ -1,21 +1,11 @@ -import net.fabricmc.loom.task.RemapJarTask - plugins { - id("dev.architectury.loom") - id("com.github.johnrengelman.shadow") -} - -val loader = property("loom.platform") as String -var mcVer = (property("minecraft_version") as String).replace(".", "").toInt() -// make from 3 char release 4 char release e.g. 1.21 -> 1.21.0 == 1210 -if (mcVer < 1000) { - mcVer *= 10 + java } base { - archivesName = property("mod_id") as String + "-" + project.name + archivesName = property("mod.id") as String + "-" + project.name version = property("mod_version") as String - group = property("mod_group") as String + group = property("mod.group") as String } repositories { @@ -28,27 +18,20 @@ dependencies { compileOnly(project(":core")) compileOnly(project(":loader-core")) - minecraft("com.mojang:minecraft:${property("minecraft_version")}") - mappings(loom.officialMojangMappings()) // We dont really use minecraft code there so we can use mojang mappings - compileOnly("com.google.code.gson:gson:2.10.1") compileOnly("org.apache.logging.log4j:log4j-core:2.20.0") implementation("org.tomlj:tomlj:1.1.1") - modImplementation("net.fabricmc:fabric-loader:${property("loader_fabric")}") + implementation("net.fabricmc:fabric-loader:${property("deps.fabric")}") } java { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 - + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) withSourcesJar() } tasks.withType { options.encoding = "UTF-8" } - -tasks.named("remapJar") { - isEnabled = false -} \ No newline at end of file diff --git a/loader/loader-forge.gradle.kts b/loader/loader-forge.gradle.kts index f4de4a140..a6399dfbd 100644 --- a/loader/loader-forge.gradle.kts +++ b/loader/loader-forge.gradle.kts @@ -1,51 +1,44 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import net.fabricmc.loom.task.RemapJarTask plugins { - id("dev.architectury.loom") - id("com.github.johnrengelman.shadow") -} - -val loader = property("loom.platform") as String -var mcVer = (property("minecraft_version") as String).replace(".", "").toInt() -// make from 3 char release 4 char release e.g. 1.21 -> 1.21.0 == 1210 -if (mcVer < 1000) { - mcVer *= 10 + java + id("net.neoforged.moddev.legacyforge") + id("com.gradleup.shadow") } base { - archivesName = property("mod_id") as String + "-" + project.name + archivesName = property("mod.id") as String + "-" + project.name version = property("mod_version") as String - group = property("mod_group") as String + group = property("mod.group") as String } -repositories { - mavenCentral() - maven { url = uri("https://maven.fabricmc.net/") } - maven { url = uri("https://maven.neoforged.net/releases") } - maven { url = uri("https://files.minecraftforge.net/maven/") } - maven { url = uri("https://libraries.minecraft.net/") } +legacyForge { + version = property("deps.forge") as String } dependencies { compileOnly(project(":core")) compileOnly(project(":loader-core")) - minecraft("com.mojang:minecraft:${property("minecraft_version")}") - mappings(loom.officialMojangMappings()) // We dont really use minecraft code there so we can use mojang mappings - compileOnly("com.google.code.gson:gson:2.10.1") - compileOnly("org.apache.logging.log4j:log4j-core:2.20.0") + compileOnly("org.apache.logging.log4j:log4j-core:2.8.1") implementation("org.tomlj:tomlj:1.1.1") implementation("org.bouncycastle:bcpkix-jdk18on:1.80") implementation("com.github.luben:zstd-jni:1.5.7-3") - implementation("org.apache.httpcomponents.client5:httpclient5:5.4.4") + implementation("org.apache.httpcomponents.client5:httpclient5:5.5") +} - if (project.name.contains("neoforge")) { - "neoForge"("net.neoforged:neoforge:${property("loader_neoforge")}") - } else { - "forge"("net.minecraftforge:forge:${property("minecraft_version")}-${property("loader_forge")}") +tasks { + processResources { + exclude("**/fabric.mod.json", "**/automodpack.accesswidener") + } + + register("buildAndCollect") { + group = "build" + from(jar.map { it.archiveFile }) + into(rootProject.layout.buildDirectory.file("libs/${project.property("mod_version")}")) + dependsOn("build") } } @@ -92,14 +85,9 @@ tasks.named("shadowJar") { } java { - if (mcVer >= 1206) { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 - } else { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + toolchain.languageVersion.set(JavaLanguageVersion.of(17)) withSourcesJar() } @@ -107,15 +95,6 @@ tasks.withType { options.encoding = "UTF-8" } -tasks.named("remapJar") { - isEnabled = false - -} - -tasks.named("jar") { - isEnabled = false -} - tasks.named("assemble") { dependsOn("shadowJar") } \ No newline at end of file diff --git a/loader/loader-neoforge.gradle.kts b/loader/loader-neoforge.gradle.kts new file mode 100644 index 000000000..955b9c902 --- /dev/null +++ b/loader/loader-neoforge.gradle.kts @@ -0,0 +1,100 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +plugins { + java + id("net.neoforged.moddev") + id("com.gradleup.shadow") +} + +base { + archivesName = property("mod.id") as String + "-" + project.name + version = property("mod_version") as String + group = property("mod.group") as String +} + +neoForge { + version = property("deps.neoforge") as String +} + +dependencies { + compileOnly(project(":core")) + compileOnly(project(":loader-core")) + + compileOnly("com.google.code.gson:gson:2.10.1") + compileOnly("org.apache.logging.log4j:log4j-core:2.8.1") + + implementation("org.tomlj:tomlj:1.1.1") + implementation("org.bouncycastle:bcpkix-jdk18on:1.80") + implementation("com.github.luben:zstd-jni:1.5.7-3") + implementation("org.apache.httpcomponents.client5:httpclient5:5.5") +} + +tasks { + processResources { + exclude("**/fabric.mod.json", "**/automodpack.accesswidener") + } + + register("buildAndCollect") { + group = "build" + from(jar.map { it.archiveFile }) + into(rootProject.layout.buildDirectory.file("libs/${project.property("mod_version")}")) + dependsOn("build") + } +} + +configurations { + create("shadowImplementation") { + extendsFrom(configurations.getByName("implementation")) + isCanBeResolved = true + } +} + +tasks.named("shadowJar") { + archiveClassifier.set("") + + from(project(":core").sourceSets.main.get().output) + from(project(":loader-core").sourceSets.main.get().output) + + // Include the tomlj dependency in the shadow jar + configurations = listOf(project.configurations.getByName("shadowImplementation")) + + val reloc = "am_libs" + relocate("org.antlr", "${reloc}.org.antlr") + relocate("org.tomlj", "${reloc}.org.tomlj") + relocate("org.apache.hc", "${reloc}.org.apache.hc") + relocate("org.checkerframework", "${reloc}.org.checkerframework") + relocate("org.slf4j", "${reloc}.org.slf4j") +// relocate("com.github.luben", "${reloc}.com.github.luben") // cant relocate - natives + relocate("org.bouncycastle", "${reloc}.org.bouncycastle") + + if (project.name.contains("neoforge")) { + relocate("pl.skidam.automodpack_loader_core_neoforge", "pl.skidam.automodpack_loader_core") + } else { + relocate("pl.skidam.automodpack_loader_core_forge", "pl.skidam.automodpack_loader_core") + } + + exclude("pl/skidam/automodpack_loader_core/loader/LoaderManager.class") + exclude("pl/skidam/automodpack_loader_core/mods/ModpackLoader.class") + exclude("log4j2.xml") + + manifest { + attributes["AutoModpack-Version"] = version + } + + mergeServiceFiles() +} + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + toolchain.languageVersion.set(JavaLanguageVersion.of(21)) + withSourcesJar() +} + +tasks.withType { + options.encoding = "UTF-8" +} + +tasks.named("assemble") { + dependsOn("shadowJar") +} \ No newline at end of file diff --git a/loader/neoforge/fml2/gradle.properties b/loader/neoforge/fml2/gradle.properties index b55507b93..5cf92ca53 100644 --- a/loader/neoforge/fml2/gradle.properties +++ b/loader/neoforge/fml2/gradle.properties @@ -1,4 +1 @@ -minecraft_version=1.20.4 -yarn_mappings=1.20.4+build.3 -loom.platform=neoforge -loader_neoforge=20.4.237 \ No newline at end of file +deps.neoforge=20.4.248 \ No newline at end of file diff --git a/loader/neoforge/fml2/src/main/resources/META-INF/mods.toml b/loader/neoforge/fml2/src/main/resources/META-INF/mods.toml index 9ba75c843..a8fef7558 100644 --- a/loader/neoforge/fml2/src/main/resources/META-INF/mods.toml +++ b/loader/neoforge/fml2/src/main/resources/META-INF/mods.toml @@ -3,7 +3,7 @@ loaderVersion = "[1,)" license = "LGPLv3" [[mods]] -modId = "automodpack-bootstrap" +modId = "automodpack_bootstrap" version = "1.0.0" displayName = "AutoModpack bootstrap" displayURL = "https://modrinth.com/mod/automodpack" diff --git a/loader/neoforge/fml4/gradle.properties b/loader/neoforge/fml4/gradle.properties index 0574b0042..cc919d069 100644 --- a/loader/neoforge/fml4/gradle.properties +++ b/loader/neoforge/fml4/gradle.properties @@ -1,4 +1 @@ -minecraft_version=1.21.1 -yarn_mappings=1.21.1+build.3 -loom.platform=neoforge -loader_neoforge=21.1.6 \ No newline at end of file +deps.neoforge=21.1.182 \ No newline at end of file diff --git a/loader/neoforge/fml4/src/main/resources/META-INF/neoforge.mods.toml b/loader/neoforge/fml4/src/main/resources/META-INF/neoforge.mods.toml index 9ba75c843..a8fef7558 100644 --- a/loader/neoforge/fml4/src/main/resources/META-INF/neoforge.mods.toml +++ b/loader/neoforge/fml4/src/main/resources/META-INF/neoforge.mods.toml @@ -3,7 +3,7 @@ loaderVersion = "[1,)" license = "LGPLv3" [[mods]] -modId = "automodpack-bootstrap" +modId = "automodpack_bootstrap" version = "1.0.0" displayName = "AutoModpack bootstrap" displayURL = "https://modrinth.com/mod/automodpack" diff --git a/settings.gradle.kts b/settings.gradle.kts index cf90ae829..15dfb351f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,23 +1,27 @@ pluginManagement { repositories { + mavenLocal() mavenCentral() gradlePluginPortal() - maven { url = uri("https://maven.architectury.dev/") } - maven { url = uri("https://maven.fabricmc.net/") } - maven { url = uri("https://maven.neoforged.net/releases") } - maven { url = uri("https://files.minecraftforge.net/maven/") } - mavenLocal() + maven("https://maven.architectury.dev/") { name = "Architectury" } + maven("https://maven.fabricmc.net/") { name = "Fabric" } + maven("https://maven.neoforged.net/releases/") { name = "NeoForged" } + maven("https://maven.kikugie.dev/snapshots") { name = "KikuGie" } } } plugins { - id("com.github.johnrengelman.shadow") version "8.1.1" apply false - id("dev.architectury.loom") version "1.9-SNAPSHOT" apply false // with 1.10 wait for remap fixes on neo/forge - id("dev.kikugie.stonecutter") version "0.6" + // For some reason, this plugin is crucial - do not remove + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" + id("dev.kikugie.stonecutter") version "0.7+" } include(":core") +fun getProperty(key: String): String? { + return settings.extra[key] as? String +} + val coreModules = getProperty("core_modules")!!.split(',').map { it.trim() } coreModules.forEach { module -> @@ -30,36 +34,29 @@ coreModules.forEach { module -> "core" -> project.buildFileName = "../loader-core.gradle.kts" "fabric-core" -> project.buildFileName = "../../loader-fabric-core.gradle.kts" "fabric-15", "fabric-16" -> project.buildFileName = "../../loader-fabric.gradle.kts" - "forge-fml40", "forge-fml47", "neoforge-fml2", "neoforge-fml4" -> project.buildFileName = "../../loader-forge.gradle.kts" + "forge-fml40", "forge-fml47" -> project.buildFileName = "../../loader-forge.gradle.kts" + "neoforge-fml2", "neoforge-fml4" -> project.buildFileName = "../../loader-neoforge.gradle.kts" } } -fun getProperty(key: String): String? { - return settings.extra[key] as? String -} - -fun getVersions(key: String): Set { - return getProperty(key)!!.split(',').map { it.trim() }.toSet() -} - -val versions = mapOf( - "forge" to getVersions("forge_versions"), - "fabric" to getVersions("fabric_versions"), - "neoforge" to getVersions("neoforge_versions") -) - -val sharedVersions = versions.map { entry -> - val loader = entry.key - entry.value.map { "$it-$loader" } -}.flatten().toSet() - stonecutter { - kotlinController = true - centralScript = "build.gradle.kts" - - shared { - versions(sharedVersions) + create(rootProject) { + fun match(version: String, vararg loaders: String) = loaders + .forEach { vers("$version-$it", version).buildscript = "build.$it.gradle.kts" } + + // Configure your targets here! + match("1.21.6", "fabric", "neoforge") + match("1.21.5", "fabric", "neoforge") + match("1.21.4", "fabric", "neoforge") + match("1.21.3", "fabric", "neoforge") + match("1.21.1", "fabric", "neoforge") + match("1.20.6", "fabric", "neoforge") + match("1.20.4", "fabric", "neoforge") + match("1.20.1", "fabric", "forge") + match("1.19.4", "fabric", "forge") + match("1.19.2", "fabric", "forge") + match("1.18.2", "fabric", "forge") } - - create(rootProject) } + +rootProject.name = "AutoModpack" \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java b/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java index 62fdff775..08b2e45cb 100644 --- a/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java +++ b/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java @@ -1,28 +1,22 @@ package pl.skidam.automodpack.client; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.util.Util; import pl.skidam.automodpack.client.ui.*; import pl.skidam.automodpack_loader_core.client.Changelogs; import pl.skidam.automodpack_loader_core.client.ModpackUpdater; import pl.skidam.automodpack_loader_core.screen.ScreenService; import pl.skidam.automodpack_loader_core.utils.DownloadManager; import pl.skidam.automodpack_loader_core.utils.FetchManager; -import pl.skidam.automodpack_loader_core.utils.SelectionManager; import pl.skidam.automodpack_loader_core.utils.UpdateType; import java.nio.file.Path; import java.util.Optional; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.TitleScreen; public class ScreenImpl implements ScreenService { - @Override - public void downloadselection(Object... args) { - Screens.downloadselection(args[0], args[1]); - } - @Override public void download(Object... args) { Screens.download(args[0], args[1]); @@ -45,7 +39,7 @@ public void restart(Object... args) { @Override public void danger(Object... args) { - Screens.danger(args[0], args[1], args[2]); + Screens.danger(args[0], args[1]); } @Override @@ -81,17 +75,14 @@ public Optional getScreen() { private static class Screens { private static Screen getScreen() { - return MinecraftClient.getInstance().currentScreen; + return Minecraft.getInstance().screen; } public static void setScreen(Screen screen) { // required for forge to handle it properly - Util.getMainWorkerExecutor().execute(() -> MinecraftClient.getInstance().execute(() -> MinecraftClient.getInstance().setScreen(screen))); - - } - public static void downloadselection(Object parent, Object modpackUpdaterInstance) { - Screens.setScreen(new DownloadSelectionScreen((Screen) parent, (ModpackUpdater) modpackUpdaterInstance)); + Util.backgroundExecutor().execute(() -> Minecraft.getInstance().execute(() -> Minecraft.getInstance().setScreen(screen))); } + public static void download(Object downloadManager, Object header) { Screens.setScreen(new DownloadScreen((DownloadManager) downloadManager, (String) header)); } @@ -103,20 +94,23 @@ public static void fetch(Object fetchManager) { public static void changelog(Object parent, Object modpackDir, Object changelog) { Screens.setScreen(new ChangelogScreen((Screen) parent, (Path) modpackDir, (Changelogs) changelog)); } + public static void restart(Object modpackDir, Object updateType, Object changelogs) { Screens.setScreen(new RestartScreen((Path) modpackDir, (UpdateType) updateType, (Changelogs) changelogs)); } - //only updated danger screen for selection Manager - public static void danger(Object parent, Object modpackUpdaterInstance, Object selectionManagerInstance) { - Screens.setScreen(new DangerScreen((Screen) parent, (ModpackUpdater) modpackUpdaterInstance, (SelectionManager) selectionManagerInstance)); + + public static void danger(Object parent, Object modpackUpdaterInstance) { + Screens.setScreen(new DangerScreen((Screen) parent, (ModpackUpdater) modpackUpdaterInstance)); } - // changed error Screen to ne Errors + public static void error(String... errors) { Screens.setScreen(new ErrorScreen(errors)); } + public static void title() { Screens.setScreen(new TitleScreen()); } + public static void menu() { // Screens.setScreen(new MenuScreen()); } diff --git a/src/main/java/pl/skidam/automodpack/client/audio/AudioManager.java b/src/main/java/pl/skidam/automodpack/client/audio/AudioManager.java index ea478e461..631ea2985 100644 --- a/src/main/java/pl/skidam/automodpack/client/audio/AudioManager.java +++ b/src/main/java/pl/skidam/automodpack/client/audio/AudioManager.java @@ -1,44 +1,43 @@ package pl.skidam.automodpack.client.audio; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.sound.SoundManager; -import net.minecraft.sound.SoundEvent; -import net.minecraft.util.Identifier; import java.util.function.Supplier; -import pl.skidam.automodpack.init.Common; +/*? if >=1.19.3 && !forge {*/ +import net.minecraft.core.registries.BuiltInRegistries; +/*?}*/ +import pl.skidam.automodpack.init.Common; +import net.minecraft.client.Minecraft; +import net.minecraft.client.sounds.SoundManager; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; /*? if neoforge {*/ import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.registries.DeferredRegister; import static pl.skidam.automodpack_core.GlobalVariables.MOD_ID; -/*?} elif forge {*/ +/*?} else if forge {*/ /*import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import static pl.skidam.automodpack_core.GlobalVariables.MOD_ID; *//*?} else {*/ /*/^? if >=1.19.3 {^/ -import net.minecraft.registry.Registry; -/^?} else {^/ -/^import net.minecraft.util.registry.Registry; +import net.minecraft.core.Registry; + /^?} else {^/ +/^import net.minecraft.core.Registry; ^//^?}^/ *//*?}*/ -/*? if >=1.19.3 && !forge {*/ -import net.minecraft.registry.Registries; -/*?}*/ - public class AudioManager { private static CustomSoundInstance SOUND_INSTANCE; private static SoundManager soundManager; private static boolean playing = false; - private static final Identifier WAITING_MUSIC_ID = Common.id("waiting_music"); + private static final ResourceLocation WAITING_MUSIC_ID = Common.id("waiting_music"); -/*? if >=1.19.3 {*/ - public static final SoundEvent WAITING_MUSIC_EVENT = SoundEvent.of(WAITING_MUSIC_ID); -/*?} else {*/ + /*? if >= 1.19.3 {*/ + public static final SoundEvent WAITING_MUSIC_EVENT = SoundEvent.createVariableRangeEvent(WAITING_MUSIC_ID); + /*?} else {*/ /*private static final SoundEvent WAITING_MUSIC_EVENT = new SoundEvent(WAITING_MUSIC_ID); *//*?}*/ @@ -54,23 +53,23 @@ public class AudioManager { /*? if neoforge {*/ public AudioManager(IEventBus eventBus) { - DeferredRegister SOUND_REGISTER = DeferredRegister.create(Registries.SOUND_EVENT, MOD_ID); + DeferredRegister SOUND_REGISTER = DeferredRegister.create(BuiltInRegistries.SOUND_EVENT, MOD_ID); SOUND_REGISTER.register(eventBus); WAITING_MUSIC = SOUND_REGISTER.register(WAITING_MUSIC_ID.getPath(),()-> WAITING_MUSIC_EVENT); } /*?}*/ -/*? if fabric {*/ + /*? if fabric {*/ /*public AudioManager() { SoundEvent waiting_music = register(); WAITING_MUSIC = () -> waiting_music; } private SoundEvent register() { - Identifier id = Common.id("waiting_music"); + ResourceLocation id = Common.id("waiting_music"); /^? if >=1.19.3 {^/ - Registry register = Registries.SOUND_EVENT; -/^?} else {^/ + Registry register = BuiltInRegistries.SOUND_EVENT; + /^?} else {^/ /^Registry register = Registry.SOUND_EVENT; ^//^?}^/ @@ -85,7 +84,7 @@ public static void playMusic() { SOUND_INSTANCE = new CustomSoundInstance(WAITING_MUSIC); } - getSoundManager().stopAll(); + getSoundManager().stop(); getSoundManager().play(SOUND_INSTANCE); playing = true; } @@ -93,13 +92,13 @@ public static void playMusic() { public static void stopMusic() { if (!playing || SOUND_INSTANCE == null) return; - getSoundManager().stopAll(); + getSoundManager().stop(); playing = false; } private static SoundManager getSoundManager() { if(soundManager == null) { - soundManager = MinecraftClient.getInstance().getSoundManager(); + soundManager = Minecraft.getInstance().getSoundManager(); } return soundManager; } diff --git a/src/main/java/pl/skidam/automodpack/client/audio/CustomSoundInstance.java b/src/main/java/pl/skidam/automodpack/client/audio/CustomSoundInstance.java index 6ea9ea881..5f871c7fd 100644 --- a/src/main/java/pl/skidam/automodpack/client/audio/CustomSoundInstance.java +++ b/src/main/java/pl/skidam/automodpack/client/audio/CustomSoundInstance.java @@ -1,26 +1,24 @@ package pl.skidam.automodpack.client.audio; -import net.minecraft.client.sound.AbstractSoundInstance; -import net.minecraft.sound.SoundCategory; -import net.minecraft.sound.SoundEvent; - import java.util.function.Supplier; - +import net.minecraft.client.resources.sounds.AbstractSoundInstance; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; /*? if >=1.19.1 {*/ -import net.minecraft.util.math.random.Random; +import net.minecraft.util.RandomSource; /*?}*/ public class CustomSoundInstance extends AbstractSoundInstance { public CustomSoundInstance(Supplier event) { /*? if >=1.21.2 {*/ - /*super(event.get().id(), SoundCategory.MASTER, Random.create()); - *//*?} elif >=1.19.1 {*/ - super(event.get().getId(), SoundCategory.MASTER, Random.create()); - /*?} else {*/ - /*super(event.get().getId(), SoundCategory.MASTER); + super(event.get().location(), SoundSource.MUSIC, RandomSource.create()); + /*?} else if >=1.19.1 {*/ + /*super(event.get().getLocation(), SoundSource.MUSIC, RandomSource.create()); + *//*?} else {*/ + /*super(event.get().getLocation(), SoundSource.MUSIC); *//*?}*/ - this.attenuationType = AttenuationType.NONE; + this.attenuation = Attenuation.NONE; } @Override @@ -34,7 +32,7 @@ public float getPitch() { } @Override - public boolean isRepeatable() { + public boolean isLooping() { return true; } } \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/ChangelogScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/ChangelogScreen.java index f0d63e985..a20a6fc1c 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/ChangelogScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/ChangelogScreen.java @@ -1,9 +1,5 @@ package pl.skidam.automodpack.client.ui; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.util.Util; import pl.skidam.automodpack_loader_core.client.Changelogs; import pl.skidam.automodpack.client.audio.AudioManager; import pl.skidam.automodpack.client.ui.versioned.VersionedText; @@ -18,6 +14,12 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import net.minecraft.Util; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.screens.Screen; public class ChangelogScreen extends VersionedScreen { private final Screen parent; @@ -25,9 +27,9 @@ public class ChangelogScreen extends VersionedScreen { private final Changelogs changelogs; private static Map formattedChanges; private ListEntryWidget listEntryWidget; - private TextFieldWidget searchField; - private ButtonWidget backButton; - private ButtonWidget openMainPageButton; + private EditBox searchField; + private Button backButton; + private Button openMainPageButton; public ChangelogScreen(Screen parent, Path modpackDir, Changelogs changelogs) { super(VersionedText.literal("ChangelogScreen")); @@ -48,37 +50,37 @@ protected void init() { initWidgets(); - this.addDrawableChild(this.listEntryWidget); - this.addDrawableChild(this.searchField); - this.addDrawableChild(this.backButton); - this.addDrawableChild(this.openMainPageButton); + this.addRenderableWidget(this.listEntryWidget); + this.addRenderableWidget(this.searchField); + this.addRenderableWidget(this.backButton); + this.addRenderableWidget(this.openMainPageButton); this.setInitialFocus(this.searchField); } private void initWidgets() { - this.listEntryWidget = new ListEntryWidget(formattedChanges, this.client, this.width, this.height, 48, this.height - 50, 20); // 38 + this.listEntryWidget = new ListEntryWidget(formattedChanges, this.minecraft, this.width, this.height, 48, this.height - 50, 20); // 38 - this.searchField = new TextFieldWidget(this.textRenderer, this.width / 2 - 100, 20, 200, 20, + this.searchField = new EditBox(this.font, this.width / 2 - 100, 20, 200, 20, VersionedText.literal("") ); - this.searchField.setChangedListener((textField) -> updateChangelogs()); // Update the changelogs display based on the search query + this.searchField.setResponder((textField) -> updateChangelogs()); // Update the changelogs display based on the search query this.backButton = buttonWidget(this.width / 2 - 140, this.height - 30, 140, 20, VersionedText.translatable("automodpack.back"), - button -> this.client.setScreen(this.parent) + button -> this.minecraft.setScreen(this.parent) ); this.openMainPageButton = buttonWidget(this.width / 2 + 20, this.height - 30, 140, 20, VersionedText.translatable("automodpack.changelog.openPage"), button -> { - ListEntry selectedEntry = listEntryWidget.getSelectedOrNull(); + ListEntry selectedEntry = listEntryWidget.getSelected(); if (selectedEntry == null) { return; } String mainPageUrl = selectedEntry.getMainPageUrl(); - Util.getOperatingSystem().open(mainPageUrl); + Util.getPlatform().openUri(mainPageUrl); } ); @@ -86,9 +88,9 @@ private void initWidgets() { @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { - this.listEntryWidget.render(matrices, mouseX, mouseY, delta); + this.listEntryWidget.render(matrices.getContext(), mouseX, mouseY, delta); - ListEntry selectedEntry = listEntryWidget.getSelectedOrNull(); + ListEntry selectedEntry = listEntryWidget.getSelected(); if (selectedEntry != null) { this.openMainPageButton.active = selectedEntry.getMainPageUrl() != null; } else { @@ -109,37 +111,24 @@ private void drawSummaryOfChanges(VersionedMatrices matrices) { modpackContent = ConfigTools.loadModpackContent(optionalModpackContentFile.get()); } - int modsAdded = 0; - int modsRemoved = 0; if (modpackContent == null) return; - for (var changelog : changelogs.changesAddedList.entrySet()) { - String fileType = ModpackContentTools.getFileType(changelog.getKey(), modpackContent); - if (fileType.equals("mod")) { - modsAdded++; - } - } - - for (var changelog : changelogs.changesDeletedList.entrySet()) { - String fileType = ModpackContentTools.getFileType(changelog.getKey(), modpackContent); - if (fileType.equals("mod")) { - modsRemoved++; - } - } + int filesAdded = changelogs.changesAddedList.size(); + int filesRemoved = changelogs.changesDeletedList.size(); - String summary = "Mods + " + modsAdded + " | - " + modsRemoved; + String summary = "+ " + filesAdded + " | - " + filesRemoved; - drawCenteredTextWithShadow(matrices, textRenderer, VersionedText.literal(summary), this.width / 2, 5, 16777215); + drawCenteredTextWithShadow(matrices, font, VersionedText.literal(summary), this.width / 2, 5, TextColors.WHITE); } private void updateChangelogs() { // If the search field is empty, reset the changelogs to the original list - if (this.searchField.getText().isEmpty()) { + if (this.searchField.getValue().isEmpty()) { formattedChanges = reFormatChanges(); } else { // Filter the changelogs based on the search query using a case-insensitive search Map filteredChangelogs = new HashMap<>(); for (Map.Entry changelog : reFormatChanges().entrySet()) { - if (changelog.getKey().toLowerCase().contains(this.searchField.getText().toLowerCase())) { + if (changelog.getKey().toLowerCase().contains(this.searchField.getValue().toLowerCase())) { filteredChangelogs.put(changelog.getKey(), changelog.getValue()); } } @@ -148,17 +137,17 @@ private void updateChangelogs() { // remove method is only available in 1.17+ /*? if >=1.17 {*/ - this.remove(this.listEntryWidget); - this.remove(this.backButton); - this.remove(this.openMainPageButton); + this.removeWidget(this.listEntryWidget); + this.removeWidget(this.backButton); + this.removeWidget(this.openMainPageButton); /*?}*/ - this.listEntryWidget = new ListEntryWidget(formattedChanges, this.client, this.width, this.height, 48, this.height - 50, 20); // 38 + this.listEntryWidget = new ListEntryWidget(formattedChanges, this.minecraft, this.width, this.height, 48, this.height - 50, 20); // 38 - this.addDrawableChild(this.listEntryWidget); - this.addDrawableChild(this.searchField); - this.addDrawableChild(this.backButton); - this.addDrawableChild(this.openMainPageButton); + this.addRenderableWidget(this.listEntryWidget); + this.addRenderableWidget(this.searchField); + this.addRenderableWidget(this.backButton); + this.addRenderableWidget(this.openMainPageButton); } private Map reFormatChanges() { @@ -182,8 +171,8 @@ private Map reFormatChanges() { @Override public boolean shouldCloseOnEsc() { - assert this.client != null; - this.client.setScreen(this.parent); + assert this.minecraft != null; + this.minecraft.setScreen(this.parent); return false; } } diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java index 6495ec7b0..b2ac9e950 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DangerScreen.java @@ -1,32 +1,23 @@ package pl.skidam.automodpack.client.ui; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.util.Formatting; -import net.minecraft.util.Util; import pl.skidam.automodpack_loader_core.client.ModpackUpdater; +import net.minecraft.ChatFormatting; +import net.minecraft.Util; +import net.minecraft.client.gui.screens.Screen; import pl.skidam.automodpack.client.audio.AudioManager; -import java.nio.file.Files; -import java.nio.file.Path; -import pl.skidam.automodpack_core.config.ConfigTools; -import pl.skidam.automodpack_core.config.Jsons; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; import pl.skidam.automodpack.client.ui.versioned.VersionedText; -import pl.skidam.automodpack_loader_core.client.ModpackUtils; - -import pl.skidam.automodpack_loader_core.utils.SelectionManager; public class DangerScreen extends VersionedScreen { private final Screen parent; private final ModpackUpdater modpackUpdaterInstance; - private final SelectionManager selectionManagerInstance; - public DangerScreen(Screen parent, ModpackUpdater modpackUpdaterInstance, SelectionManager selectionManagerInstance) { + public DangerScreen(Screen parent, ModpackUpdater modpackUpdaterInstance) { super(VersionedText.literal("DangerScreen")); this.parent = parent; this.modpackUpdaterInstance = modpackUpdaterInstance; - this.selectionManagerInstance = selectionManagerInstance; if (AudioManager.isMusicPlaying()) { AudioManager.stopMusic(); @@ -36,39 +27,22 @@ public DangerScreen(Screen parent, ModpackUpdater modpackUpdaterInstance, Select @Override protected void init() { super.init(); - assert this.client != null; + assert this.minecraft != null; - this.addDrawableChild(buttonWidget(this.width / 2 - 115, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.cancel"), button -> { - this.client.setScreen(parent); + this.addRenderableWidget(buttonWidget(this.width / 2 - 115, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.cancel"), button -> { + this.minecraft.setScreen(parent); })); - if (selectionManagerInstance != null) { - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.selection").formatted(Formatting.BOLD), button -> { - this.client.setScreen(new DownloadSelectionScreen(parent, modpackUpdaterInstance)); - })); - } else { - this.addDrawableChild(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.confirm").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); - })); - } - Path serverConfigPath = ModpackUtils.getMinecraftPath().resolve("mods/automodpack/automodpack-server.json"); - if (Files.exists(serverConfigPath)) { - Jsons.ServerConfigFields serverConfig = ConfigTools.load(serverConfigPath, Jsons.ServerConfigFields.class); - - if (serverConfig != null && serverConfig.enableFullServerPack) { - this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 100, 160, 20, VersionedText.literal("automodpack.danger.fullserverpack").formatted(Formatting.RED), button -> { - SelectionManager.setSelectedPack("fullserver"); - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); - })); - } - } + this.addRenderableWidget(buttonWidget(this.width / 2 + 15, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.danger.confirm").withStyle(ChatFormatting.BOLD), button -> { + Util.backgroundExecutor().execute(modpackUpdaterInstance::startUpdate); + })); } @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.danger").formatted(Formatting.BOLD), this.width / 2, this.height / 2 - 60, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.danger.description"), this.width / 2, this.height / 2 - 35, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.danger.secDescription"), this.width / 2, this.height / 2 - 25, 16777215); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.danger").withStyle(ChatFormatting.BOLD), this.width / 2, this.height / 2 - 60, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.danger.description"), this.width / 2, this.height / 2 - 35, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.danger.secDescription"), this.width / 2, this.height / 2 - 25, TextColors.WHITE); } @Override diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadScreen.java index 33062112f..399869c81 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadScreen.java @@ -1,14 +1,14 @@ package pl.skidam.automodpack.client.ui; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import net.minecraft.util.Identifier; -import net.minecraft.util.Util; import pl.skidam.automodpack.init.Common; import pl.skidam.automodpack_loader_core.screen.ScreenManager; import pl.skidam.automodpack_loader_core.utils.DownloadManager; +import net.minecraft.ChatFormatting; +import net.minecraft.Util; +import net.minecraft.client.gui.components.Button; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; import pl.skidam.automodpack.client.audio.AudioManager; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; @@ -17,22 +17,19 @@ public class DownloadScreen extends VersionedScreen { - private static final Identifier PROGRESS_BAR_EMPTY_TEXTURE = Common.id("gui/progress-bar-empty.png"); - private static final Identifier PROGRESS_BAR_FULL_TEXTURE = Common.id("gui/progress-bar-full.png"); + private static final ResourceLocation PROGRESS_BAR_EMPTY_TEXTURE = Common.id("gui/progress-bar-empty.png"); + private static final ResourceLocation PROGRESS_BAR_FULL_TEXTURE = Common.id("gui/progress-bar-full.png"); private static final int PROGRESS_BAR_WIDTH = 250; private static final int PROGRESS_BAR_HEIGHT = 20; private final DownloadManager downloadManager; private final String header; private static long ticks = 0; - private ButtonWidget cancelButton; + private Button cancelButton; - // Temp save for the last download values -// private final Map mapOfFileStats = new HashMap<>(); // URL, Percentage of download private String lastStage = "-1"; private int lastPercentage = -1; private String lastSpeed = "-1"; private String lastETA = "-1"; - private float lastDownloadedScale = 0.0F; public DownloadScreen(DownloadManager downloadManager, String header) { super(VersionedText.literal("DownloadScreen")); @@ -46,27 +43,13 @@ protected void init() { initWidgets(); - this.addDrawableChild(cancelButton); + this.addRenderableWidget(cancelButton); - Util.getMainWorkerExecutor().execute(() -> { + Util.backgroundExecutor().execute(() -> { while (downloadManager != null && downloadManager.isRunning()) { - -// for (Map.Entry map : ModpackUpdater.downloadManager.downloadsInProgress.entrySet()) { -// mapOfFileStats.put(map.getKey(), ModpackUpdater.downloadManager.getPercentageOfFileSizeDownloaded(map.getKey()) + "%"); -// } -// -// for (Map.Entry map : mapOfFileStats.entrySet()) { -// if (!ModpackUpdater.downloadManager.downloadsInProgress.containsKey(map.getKey())) { -// mapOfFileStats.remove(map.getKey()); -// } -// } - - // TODO make it work better pls lastStage = downloadManager.getStage(); - lastPercentage = (int) downloadManager.getTotalPercentageOfFileSizeDownloaded(); - lastDownloadedScale = (float) (downloadManager.getTotalPercentageOfFileSizeDownloaded() * 0.01); - - lastSpeed = SpeedMeter.formatDownloadSpeedToMbps(downloadManager.getSpeedMeter().getCurrentSpeedInBytes()); + lastPercentage = downloadManager.getTotalPercentageOfFileSizeDownloaded(); + lastSpeed = SpeedMeter.formatDownloadSpeedToMbps(downloadManager.getSpeedMeter().getAverageSpeedOfLastFewSeconds(1)); lastETA = SpeedMeter.formatETAToSeconds(downloadManager.getSpeedMeter().getETAInSeconds()); } }); @@ -81,14 +64,14 @@ private void initWidgets() { ); } - private Text getStage() { + private Component getStage() { if (lastStage.equals("-1")) { return VersionedText.translatable("automodpack.download.calculating"); } return VersionedText.literal(lastStage); } - private Text getPercentage() { + private Component getPercentage() { if (lastPercentage == -1) { return VersionedText.translatable("automodpack.download.calculating"); } @@ -96,14 +79,14 @@ private Text getPercentage() { } - private Text getTotalDownloadSpeed() { + private Component getTotalDownloadSpeed() { if (lastSpeed.equals("-1")) { return VersionedText.translatable("automodpack.download.calculating"); } return VersionedText.literal(lastSpeed); } - private Text getTotalETA() { + private Component getTotalETA() { if (lastETA.equals("-1")) { return VersionedText.translatable("automodpack.download.calculating"); } @@ -111,43 +94,34 @@ private Text getTotalETA() { } private float getDownloadScale() { - return lastDownloadedScale; + return Math.max(0, Math.min(100, lastPercentage)) * 0.01F; // Convert the clamped percentage to a scale between 0.0f and 1.0f } private void drawDownloadingFiles(VersionedMatrices matrices) { float scale = 1.0F; int y = this.height / 2 - 90; - matrices.push(); + matrices.pushPose(); matrices.scale(scale, scale, scale); if (downloadManager != null && !downloadManager.downloadsInProgress.isEmpty()) { - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.download.downloading").formatted(Formatting.BOLD), this.width / 2, y, 16777215); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.download.downloading").withStyle(ChatFormatting.BOLD), this.width / 2, y, TextColors.WHITE); // Use a separate variable for the current y position int currentY = y + 15; synchronized (downloadManager.downloadsInProgress) { for (DownloadManager.DownloadData downloadData : downloadManager.downloadsInProgress.values()) { - String text = downloadData.getFileName(); - -// DownloadManager.DownloadData downloadData = map.getValue(); -// String percentage = mapOfFileStats.get(map.getKey()); -// -// if (percentage != null) { -// text += " " + percentage; -// } - - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.literal(text).formatted(Formatting.GRAY), (int) (this.width / 2 * scale), currentY, 16777215); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.literal(text), (int) ((float) this.width / 2 * scale), currentY, TextColors.GRAY); currentY += 10; } } } else { - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.download.noFiles"), (int) (this.width / 2 * scale), y, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.wait").formatted(Formatting.BOLD), (int) (this.width / 2 * scale), y + 25, 16777215); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.download.noFiles"), (int) ((float) this.width / 2 * scale), y, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.wait").withStyle(ChatFormatting.BOLD), (int) ((float) this.width / 2 * scale), y + 25, TextColors.WHITE); } - matrices.pop(); + matrices.popPose(); } private void checkAndStartMusic() { @@ -167,16 +141,16 @@ private void checkAndStartMusic() { @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { drawDownloadingFiles(matrices); - MutableText titleText = VersionedText.literal(header).formatted(Formatting.BOLD); - drawCenteredTextWithShadow(matrices, this.textRenderer, titleText, this.width / 2, this.height / 2 - 110, 16777215); + MutableComponent titleText = VersionedText.literal(header).withStyle(ChatFormatting.BOLD); + drawCenteredTextWithShadow(matrices, this.font, titleText, this.width / 2, this.height / 2 - 110, TextColors.WHITE); if (downloadManager != null && downloadManager.isRunning()) { - MutableText percentage = (MutableText) this.getPercentage(); - MutableText stage = (MutableText) this.getStage(); - MutableText eta = (MutableText) this.getTotalETA(); - MutableText speed = (MutableText) this.getTotalDownloadSpeed(); - drawCenteredTextWithShadow(matrices, this.textRenderer, stage, this.width / 2, this.height / 2 - 10, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, eta, this.width / 2, this.height / 2 + 10, 16777215); + MutableComponent percentage = (MutableComponent) this.getPercentage(); + MutableComponent stage = (MutableComponent) this.getStage(); + MutableComponent eta = (MutableComponent) this.getTotalETA(); + MutableComponent speed = (MutableComponent) this.getTotalDownloadSpeed(); + drawCenteredTextWithShadow(matrices, this.font, stage, this.width / 2, this.height / 2 - 10, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, eta, this.width / 2, this.height / 2 + 10, TextColors.WHITE); // Render progress bar @@ -186,8 +160,8 @@ public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, drawTexture(PROGRESS_BAR_EMPTY_TEXTURE, matrices, progressX, progressY, 0, 0, PROGRESS_BAR_WIDTH, PROGRESS_BAR_HEIGHT, PROGRESS_BAR_WIDTH, PROGRESS_BAR_HEIGHT); drawTexture(PROGRESS_BAR_FULL_TEXTURE, matrices, progressX, progressY, 0, 0, (int) (PROGRESS_BAR_WIDTH * getDownloadScale()), PROGRESS_BAR_HEIGHT, PROGRESS_BAR_WIDTH, PROGRESS_BAR_HEIGHT); - drawCenteredTextWithShadow(matrices, this.textRenderer, percentage, this.width / 2, this.height / 2 + 36, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, speed, this.width / 2, this.height / 2 + 60, 16777215); + drawCenteredTextWithShadow(matrices, this.font, percentage, this.width / 2, this.height / 2 + 36, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, speed, this.width / 2, this.height / 2 + 60, TextColors.WHITE); checkAndStartMusic(); cancelButton.active = true; @@ -207,11 +181,7 @@ public void cancelDownload() { downloadManager.cancelAllAndShutdown(); } - // TODO delete files that were downloaded - // we will use the same method as to modpacks manager - new ScreenManager().title(); - } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/java/pl/skidam/automodpack/client/ui/ErrorScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/ErrorScreen.java index 52c0b947c..4a6f3f5f9 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/ErrorScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/ErrorScreen.java @@ -1,7 +1,7 @@ package pl.skidam.automodpack.client.ui; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.components.Button; import pl.skidam.automodpack.client.audio.AudioManager; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; @@ -10,7 +10,7 @@ public class ErrorScreen extends VersionedScreen { private final String[] errorMessages; - private ButtonWidget backButton; + private Button backButton; public ErrorScreen(String... errorMessages) { super(VersionedText.literal("ErrorScreen")); @@ -27,21 +27,21 @@ protected void init() { initWidgets(); - this.addDrawableChild(backButton); + this.addRenderableWidget(backButton); } private void initWidgets() { backButton = buttonWidget(this.width / 2 - 100, this.height / 2 + 50, 200, 20, VersionedText.translatable("automodpack.back"), button -> { - assert client != null; - client.setScreen(null); + assert minecraft != null; + minecraft.setScreen(null); }); } @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.literal("[AutoModpack] Error! ").append(VersionedText.translatable("automodpack.error").formatted(Formatting.RED)), this.width / 2, this.height / 2 - 50, 16777215); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.literal("[AutoModpack] Error! ").append(VersionedText.translatable("automodpack.error").withStyle(ChatFormatting.RED)), this.width / 2, this.height / 2 - 50, TextColors.WHITE); for (int i = 0; i < this.errorMessages.length; i++) { - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable(this.errorMessages[i]), this.width / 2, this.height / 2 - 20 + i * 12, 14687790); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable(this.errorMessages[i]), this.width / 2, this.height / 2 - 20 + i * 12, 14687790); } } diff --git a/src/main/java/pl/skidam/automodpack/client/ui/FetchScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/FetchScreen.java index 8b00fcb57..ede95d699 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/FetchScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/FetchScreen.java @@ -1,8 +1,7 @@ package pl.skidam.automodpack.client.ui; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.util.Formatting; - +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.components.Button; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; import pl.skidam.automodpack.client.ui.versioned.VersionedText; @@ -11,7 +10,7 @@ public class FetchScreen extends VersionedScreen { - private ButtonWidget cancelButton; + private Button cancelButton; private final FetchManager fetchManager; public FetchScreen(FetchManager fetchManager) { @@ -25,7 +24,7 @@ protected void init() { initWidgets(); - this.addDrawableChild(cancelButton); + this.addRenderableWidget(cancelButton); } private void initWidgets() { @@ -51,9 +50,9 @@ public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, } // Fetching direct url's from Modrinth and CurseForge. - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.fetch").formatted(Formatting.BOLD), this.width / 2, this.height / 2 - 60, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.wait"), this.width / 2, this.height / 2 - 48, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.fetch.found", getFetchesDone()), this.width / 2, this.height / 2 - 30, 16777215); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.fetch").withStyle(ChatFormatting.BOLD), this.width / 2, this.height / 2 - 60, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.wait"), this.width / 2, this.height / 2 - 48, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.fetch.found", getFetchesDone()), this.width / 2, this.height / 2 - 30, TextColors.WHITE); } @Override diff --git a/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java index a569654ef..88b052e5a 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/RestartScreen.java @@ -1,11 +1,10 @@ package pl.skidam.automodpack.client.ui; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.util.Formatting; import pl.skidam.automodpack.client.audio.AudioManager; import java.nio.file.Path; - +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.components.Button; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; import pl.skidam.automodpack.client.ui.versioned.VersionedText; @@ -17,9 +16,9 @@ public class RestartScreen extends VersionedScreen { private final Path modpackDir; private final UpdateType updateType; private final Changelogs changelogs; - private static ButtonWidget cancelButton; - private static ButtonWidget restartButton; - private static ButtonWidget changelogsButton; + private static Button cancelButton; + private static Button restartButton; + private static Button changelogsButton; public RestartScreen(Path modpackDir, UpdateType updateType, Changelogs changelogs) { super(VersionedText.literal("RestartScreen")); @@ -38,9 +37,9 @@ protected void init() { initWidgets(); - this.addDrawableChild(cancelButton); - this.addDrawableChild(restartButton); - this.addDrawableChild(changelogsButton); + this.addRenderableWidget(cancelButton); + this.addRenderableWidget(restartButton); + this.addRenderableWidget(changelogsButton); if (changelogs == null || changelogs.changesAddedList.isEmpty() && changelogs.changesDeletedList.isEmpty()) { changelogsButton.active = false; @@ -48,12 +47,12 @@ protected void init() { } public void initWidgets() { - assert this.client != null; + assert this.minecraft != null; cancelButton = buttonWidget(this.width / 2 - 155, this.height / 2 + 50, 150, 20, VersionedText.translatable("automodpack.restart.cancel"), button -> { - this.client.setScreen(null); + this.minecraft.setScreen(null); }); - restartButton = buttonWidget(this.width / 2 + 5, this.height / 2 + 50, 150, 20, VersionedText.translatable("automodpack.restart.confirm").formatted(Formatting.BOLD), button -> { + restartButton = buttonWidget(this.width / 2 + 5, this.height / 2 + 50, 150, 20, VersionedText.translatable("automodpack.restart.confirm").withStyle(ChatFormatting.BOLD), button -> { System.exit(0); }); @@ -64,9 +63,9 @@ public void initWidgets() { @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.restart." + updateType.toString()).formatted(Formatting.BOLD), this.width / 2, this.height / 2 - 60, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.restart.description"), this.width / 2, this.height / 2 - 35, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.restart.secDescription"), this.width / 2, this.height / 2 - 25, 16777215); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.restart." + updateType.toString()).withStyle(ChatFormatting.BOLD), this.width / 2, this.height / 2 - 60, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.restart.description"), this.width / 2, this.height / 2 - 35, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.restart.secDescription"), this.width / 2, this.height / 2 - 25, TextColors.WHITE); } @Override diff --git a/src/main/java/pl/skidam/automodpack/client/ui/TextColors.java b/src/main/java/pl/skidam/automodpack/client/ui/TextColors.java new file mode 100644 index 000000000..b164b7d29 --- /dev/null +++ b/src/main/java/pl/skidam/automodpack/client/ui/TextColors.java @@ -0,0 +1,63 @@ +package pl.skidam.automodpack.client.ui; + +@SuppressWarnings("unused") +public class TextColors { + + // Contains constants for commonly used colors in 0xAARRGGBB format. + + /** + * Represents the color white, {@code 0xFFFFFFFF}. + */ + public static final int WHITE = -1; // previously 0xFFFFFF or 16777215 + /** + * Represents the color black, {@code 0xFF000000}. + */ + public static final int BLACK = -16777216; + /** + * Represents the color gray, {@code 0xFF808080}. + */ + public static final int GRAY = -8355712; + public static final int DARK_GRAY = -12566464; + /** + * Represents the color light gray, {@code 0xFFA0A0A0}. + */ + public static final int LIGHT_GRAY = -6250336; + /** + * Represents a variant of the color white, used so that the two alternate with + * each other, {@code 0xFFBABABA}. + */ + public static final int ALTERNATE_WHITE = -4539718; + /** + * Represents the color red, {@code 0xFFFF0000}. + */ + public static final int RED = -65536; + /** + * Represents the color light red, {@code 0xFFDF5050}. + */ + public static final int LIGHT_RED = -2142128; + /** + * Represents the color green, {@code 0xFF00FF00}. + */ + public static final int GREEN = -16711936; + /** + * Represents the color blue, {@code 0xFF0000FF}. + */ + public static final int BLUE = -16776961; + /** + * Represents the color yellow, {@code 0xFFFFFF00}. + */ + public static final int YELLOW = -256; + /** + * Represents the color light yellow, {@code 0xFFFFFF55}. + */ + public static final int LIGHT_YELLOW = -171; + /** + * Represents the color purple, {@code 0xFF500050}. + */ + public static final int PURPLE = -11534256; + /** + * Represents the color cyan, {@code 0xFF57FFE1}. + */ + public static final int CYAN = -11010079; + public static final int LIGHT_PINK = -13108; +} diff --git a/src/main/java/pl/skidam/automodpack/client/ui/ValidationScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/ValidationScreen.java index 7d67c36ed..512f81138 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/ValidationScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/ValidationScreen.java @@ -1,12 +1,11 @@ package pl.skidam.automodpack.client.ui; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.widget.TextFieldWidget; -import net.minecraft.client.toast.SystemToast; -import net.minecraft.client.toast.Toast; -import net.minecraft.util.Formatting; - +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.components.toasts.SystemToast; +import net.minecraft.client.gui.components.toasts.Toast; +import net.minecraft.client.gui.screens.Screen; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; import pl.skidam.automodpack.client.ui.versioned.VersionedText; @@ -18,10 +17,10 @@ public class ValidationScreen extends VersionedScreen { private final Runnable validatedCallback; private final Runnable canceledCallback; private boolean validated = false; - private final Toast failedToast = new SystemToast(SystemToast.Type.PACK_LOAD_FAILURE, VersionedText.translatable("automodpack.validation.failed"), VersionedText.translatable("automodpack.retry")); - private TextFieldWidget textField; - private ButtonWidget backButton; - private ButtonWidget validateButton; + private final Toast failedToast = new SystemToast(SystemToast.SystemToastId.PACK_LOAD_FAILURE, VersionedText.translatable("automodpack.validation.failed"), VersionedText.translatable("automodpack.retry")); + private EditBox textField; + private Button backButton; + private Button validateButton; public ValidationScreen(Screen parent, String serverFingerprint, Runnable validatedCallback, Runnable canceledCallback) { @@ -38,15 +37,15 @@ protected void init() { initWidgets(); - this.addDrawableChild(this.textField); - this.addDrawableChild(this.backButton); - this.addDrawableChild(this.validateButton); + this.addRenderableWidget(this.textField); + this.addRenderableWidget(this.backButton); + this.addRenderableWidget(this.validateButton); this.setInitialFocus(this.textField); } public void initWidgets() { - assert this.client != null; - this.textField = new TextFieldWidget(this.textRenderer, this.width / 2 - 170, this.height / 2 - 20, 340, 20, + assert this.minecraft != null; + this.textField = new EditBox(this.font, this.width / 2 - 170, this.height / 2 - 20, 340, 20, VersionedText.literal("") ); this.textField.setMaxLength(64); // default is 30 which is too little @@ -54,7 +53,7 @@ public void initWidgets() { this.backButton = buttonWidget(this.width / 2 - 155, this.height / 2 + 50, 150, 20, VersionedText.translatable("automodpack.back"), button -> { - this.client.setScreen(parent); + this.minecraft.setScreen(parent); if (!this.validated) { this.canceledCallback.run(); } @@ -63,7 +62,7 @@ public void initWidgets() { this.validateButton = buttonWidget(this.width / 2 + 5, this.height / 2 + 50, 150, 20, VersionedText.translatable("automodpack.validation.run"), - button -> validate(textField.getText())); + button -> validate(textField.getValue())); } private void validate(String input) { @@ -71,28 +70,32 @@ private void validate(String input) { if (input.equals(serverFingerprint) || input.equals("I AM INCREDIBLY STUPID")) { validateButton.active = false; this.validated = true; - if (this.client != null) { - this.client.setScreen(parent); + if (this.minecraft != null) { + this.minecraft.setScreen(parent); } validatedCallback.run(); } else { GlobalVariables.LOGGER.error("Server fingerprint validation failed, try again"); - if (this.client != null) { - this.client.getToastManager().add(failedToast); + if (this.minecraft != null) { + /*? if > 1.21.1 {*/ + this.minecraft.getToastManager().addToast(failedToast); + /*?} else {*/ + /*this.minecraft.getToasts().addToast(failedToast); + *//*?}*/ } } } @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.validation.text").formatted(Formatting.BOLD), - this.width / 2, this.height / 2 - 100, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.validation.description"), - this.width / 2, this.height / 2 - 75, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.validation.secDescription"), - this.width / 2, this.height / 2 - 65, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.validation.thiDescription"), - this.width / 2, this.height / 2 - 55, 16777215); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.validation.text").withStyle(ChatFormatting.BOLD), + this.width / 2, this.height / 2 - 100, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.validation.description"), + this.width / 2, this.height / 2 - 75, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.validation.secDescription"), + this.width / 2, this.height / 2 - 65, TextColors.WHITE); + drawCenteredTextWithShadow(matrices, this.font, VersionedText.translatable("automodpack.validation.thiDescription"), + this.width / 2, this.height / 2 - 55, TextColors.WHITE); } @Override diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedCommandSource.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedCommandSource.java index 2887de7ab..be8a4ff40 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedCommandSource.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedCommandSource.java @@ -1,29 +1,27 @@ package pl.skidam.automodpack.client.ui.versioned; import com.mojang.brigadier.context.CommandContext; -import net.minecraft.entity.Entity; +import net.minecraft.commands.CommandSource; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.CommandOutput; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.Text; -import net.minecraft.util.math.Vec2f; -import net.minecraft.util.math.Vec3d; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec2; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; -public class VersionedCommandSource extends ServerCommandSource { +public class VersionedCommandSource extends CommandSourceStack { - public VersionedCommandSource(CommandOutput output, Vec3d pos, Vec2f rot, ServerWorld world, int level, String name, Text displayName, MinecraftServer server, @Nullable Entity entity) { + public VersionedCommandSource(CommandSource output, Vec3 pos, Vec2 rot, ServerLevel world, int level, String name, Component displayName, MinecraftServer server, @Nullable Entity entity) { super(output, pos, rot, world, level, name, displayName, server, entity); } -/*? if >=1.20 {*/ - public static void sendFeedback(CommandContext context, Text message, boolean broadcastToOps) { - context.getSource().sendFeedback(() -> message, broadcastToOps); - } -/*?} else {*/ - /*public static void sendFeedback(CommandContext context, Text message, boolean broadcastToOps) { - context.getSource().sendFeedback(message, broadcastToOps); + public static void sendFeedback(CommandContext context, Component message, boolean broadcastToOps) { + /*? if >=1.20 {*/ + context.getSource().sendSuccess(() -> message, broadcastToOps); + /*?} else {*/ + /*context.getSource().sendSuccess(message, broadcastToOps); + *//*?}*/ } -*//*?}*/ } diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java index 82dee9503..c7ef8d638 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java @@ -1,30 +1,52 @@ package pl.skidam.automodpack.client.ui.versioned; /*? if >=1.20 {*/ -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.gui.GuiGraphics; /*?} else {*/ -/*import net.minecraft.client.util.math.MatrixStack; +/*import com.mojang.blaze3d.vertex.PoseStack; *//*?}*/ -public class VersionedMatrices extends /*? if >=1.20 >>*/ DrawContext /*? if <1.20 >>*/ /*MatrixStack*/ { +public class VersionedMatrices /*? if <1.20 {*/ /*extends PoseStack *//*?}*/ { /*? if >=1.20 {*/ - public VersionedMatrices(MinecraftClient client, VertexConsumerProvider.Immediate vertexConsumers) { - super(client, vertexConsumers); + private final GuiGraphics context; + + public VersionedMatrices(GuiGraphics context) { + this.context = context; + } + + public GuiGraphics getContext() { + return context; + } + + /*? if >=1.21.6 {*/ + public void pushPose() { + context.pose().pushMatrix(); + } + + public void popPose() { + context.pose().popMatrix(); } - public void push() { - getMatrices().push(); + public void scale(float x, float y, float z) { + context.pose().scale(x, y); + } + /*?} else {*/ + /*public void pushPose() { + context.pose().pushPose(); } - public void pop() { - getMatrices().pop(); + public void popPose() { + context.pose().popPose(); } public void scale(float x, float y, float z) { - getMatrices().scale(x, y, z); + context.pose().scale(x, y, z); } -/*?}*/ + *//*?}*/ +/*?} else {*/ + /*public PoseStack getContext() { + return this; + } +*//*?}*/ } diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java index c5b69ebdc..c7d81330d 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java @@ -1,63 +1,57 @@ package pl.skidam.automodpack.client.ui.versioned; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; - -/*? if <=1.16.5 {*//* -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.widget.ClickableWidget; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; + +/*? if >=1.21.6 {*/ +import net.minecraft.client.renderer.RenderPipelines; +/*?} else if >=1.21.2 {*/ +/*import net.minecraft.client.renderer.RenderType; +import java.util.function.Function; *//*?}*/ /*? if <1.20 {*/ -/*import net.minecraft.client.gui.DrawableHelper; -import net.minecraft.client.util.math.MatrixStack; -import com.mojang.blaze3d.systems.RenderSystem; -*//*?}*/ - -/*? if >=1.20 {*/ -import net.minecraft.client.gui.DrawContext; -import pl.skidam.automodpack.mixin.core.DrawContextAccessor; +/*import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.gui.GuiComponent; +*//*?} else {*/ +import net.minecraft.client.gui.GuiGraphics; /*?}*/ -/*? if >=1.21.2 {*/ -/*import net.minecraft.client.render.RenderLayer; -import java.util.function.Function; -*//*?}*/ - public class VersionedScreen extends Screen { - protected VersionedScreen(Text title) { + protected VersionedScreen(Component title) { super(title); } /*? if <1.20 {*/ /*@Override - public void render(MatrixStack matrix, int mouseX, int mouseY, float delta) { + public void render(PoseStack matrix, int mouseX, int mouseY, float delta) { VersionedMatrices matrices = new VersionedMatrices(); *//*?} else {*/ @Override - public void render(DrawContext matrix, int mouseX, int mouseY, float delta) { - VersionedMatrices matrices = new VersionedMatrices(this.client, ((DrawContextAccessor) matrix).vertexConsumers()); - /*?}*/ + public void render(GuiGraphics matrix, int mouseX, int mouseY, float delta) { + VersionedMatrices matrices = new VersionedMatrices(matrix); + /*?}*/ // Render background /*? if <1.20.2 {*/ - /*super.renderBackground(matrices); + /*super.renderBackground(matrices.getContext()); *//*?} elif <1.20.6 {*/ - /*super.renderBackground(matrices, mouseX, mouseY, delta); + /*super.renderBackground(matrices.getContext(), mouseX, mouseY, delta); *//*?} else {*/ - super.render(matrices, mouseX, mouseY, delta); + super.render(matrix, mouseX, mouseY, delta); /*?}*/ + // Render the rest of our screen versionedRender(matrices, mouseX, mouseY, delta); /*? if <1.20.6 {*/ - /*super.render(matrices, mouseX, mouseY, delta); + /*super.render(matrices.getContext(), mouseX, mouseY, delta); *//*?}*/ } @@ -76,43 +70,45 @@ public void addDrawableChild(T child) { *//*?}*/ /*? if >=1.20 {*/ - public static void drawCenteredTextWithShadow(VersionedMatrices matrices, TextRenderer textRenderer, MutableText text, int centerX, int y, int color) { - matrices.drawCenteredTextWithShadow(textRenderer, text, centerX, y, color); + public static void drawCenteredTextWithShadow(VersionedMatrices matrices, Font textRenderer, MutableComponent text, int centerX, int y, int color) { + matrices.getContext().drawCenteredString(textRenderer, text, centerX, y, color); } /*?} else {*/ - /*public static void drawCenteredTextWithShadow(VersionedMatrices matrices, TextRenderer textRenderer, MutableText text, int centerX, int y, int color) { - textRenderer.drawWithShadow(matrices, text, (float)(centerX - textRenderer.getWidth(text) / 2), (float)y, color); + /*public static void drawCenteredTextWithShadow(VersionedMatrices matrices, Font textRenderer, MutableComponent text, int centerX, int y, int color) { + textRenderer.drawShadow(matrices.getContext(), text, (float)(centerX - textRenderer.width(text) / 2), (float)y, color); } *//*?}*/ /*? if <1.19.3 {*/ - /*public static ButtonWidget buttonWidget(int x, int y, int width, int height, Text message, ButtonWidget.PressAction onPress) { - return new ButtonWidget(x, y, width, height, message, onPress); + /*public static Button buttonWidget(int x, int y, int width, int height, Component message, Button.OnPress onPress) { + return new Button(x, y, width, height, message, onPress); } *//*?} else {*/ - public static ButtonWidget buttonWidget(int x, int y, int width, int height, Text message, ButtonWidget.PressAction onPress) { - return ButtonWidget.builder(message, onPress).position(x, y).size(width, height).build(); + public static Button buttonWidget(int x, int y, int width, int height, Component message, Button.OnPress onPress) { + return Button.builder(message, onPress).pos(x, y).size(width, height).build(); } /*?}*/ /*? if <=1.20 {*/ - /*public static void drawTexture(Identifier textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { + /*public static void drawTexture(ResourceLocation textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { /^? if <=1.16.5 {^/ - /^MinecraftClient.getInstance().getTextureManager().bindTexture(textureID); + /^Minecraft.getInstance().getTextureManager().bindTexture(textureID); ^//^?} else {^/ RenderSystem.setShaderTexture(0, textureID); /^?}^/ - DrawableHelper.drawTexture(matrices, x, y, u, v, width, height, textureWidth, textureHeight); + GuiComponent.blit(matrices.getContext(), x, y, u, v, width, height, textureWidth, textureHeight); } *//*?} else {*/ - public static void drawTexture(Identifier textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { - /*? if >=1.21.2 {*/ - /*Function renderLayers = RenderLayer::getGuiTextured; - matrices.drawTexture(renderLayers, textureID, x, y, u, v, width, height, textureWidth, textureHeight); + public static void drawTexture(ResourceLocation textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { + /*? if >=1.21.6 {*/ + matrices.getContext().blit(RenderPipelines.GUI_TEXTURED, textureID, x, y, u, v, width, height, textureWidth, textureHeight); + /*?} elif >=1.21.2 {*/ + /*Function RenderTypes = RenderType::guiTextured; + matrices.getContext().blit(RenderTypes, textureID, x, y, u, v, width, height, textureWidth, textureHeight); *//*?} else {*/ - matrices.drawTexture(textureID, x, y, u, v, width, height, textureWidth, textureHeight); - /*?}*/ + /*matrices.getContext().blit(textureID, x, y, u, v, width, height, textureWidth, textureHeight); + *//*?}*/ } /*?}*/ } diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java index 9405c473c..102a51b09 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java @@ -1,25 +1,31 @@ package pl.skidam.automodpack.client.ui.versioned; -import net.minecraft.text.*; +import net.minecraft.network.chat.MutableComponent; +/*? if <= 1.19.1 {*/ +/*import net.minecraft.network.chat.TextComponent; +import net.minecraft.network.chat.TranslatableComponent; +*//*?} else {*/ +import net.minecraft.network.chat.Component; +/*?}*/ public class VersionedText { /*? if <=1.19.1 {*/ - /*public static MutableText translatable(String key, Object... args) { - return new TranslatableText(key, args); + /*public static MutableComponent translatable(String key, Object... args) { + return new TranslatableComponent(key, args); } - public static MutableText literal(String string) { - return new LiteralText(string); + public static MutableComponent literal(String string) { + return new TextComponent(string); } *//*?} else {*/ - public static MutableText translatable(String key, Object... args) { - return Text.translatable(key, args); + public static MutableComponent translatable(String key, Object... args) { + return Component.translatable(key, args); } - public static MutableText literal(String string) { - return Text.literal(string); + public static MutableComponent literal(String string) { + return Component.literal(string); } /*?}*/ -} +} \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/widget/Badge.java b/src/main/java/pl/skidam/automodpack/client/ui/widget/Badge.java index 7dffde3c2..d5fcbbb54 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/widget/Badge.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/widget/Badge.java @@ -1,15 +1,16 @@ package pl.skidam.automodpack.client.ui.widget; -import net.minecraft.util.Identifier; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; import pl.skidam.automodpack.init.Common; import static pl.skidam.automodpack_core.GlobalVariables.MOD_ID; +import net.minecraft.resources.ResourceLocation; + public class Badge { - private static final Identifier MODRINTH_ICON = Common.id("gui/platform/logo-modrinth.png"); - private static final Identifier CURSEFORGE_ICON = Common.id("gui/platform/logo-curseforge.png"); + private static final ResourceLocation MODRINTH_ICON = Common.id("gui/platform/logo-modrinth.png"); + private static final ResourceLocation CURSEFORGE_ICON = Common.id("gui/platform/logo-curseforge.png"); private static final int textureSize = 32; public static void renderModrinthBadge(VersionedMatrices matrices, int x, int y) { diff --git a/src/main/java/pl/skidam/automodpack/client/ui/widget/ListEntry.java b/src/main/java/pl/skidam/automodpack/client/ui/widget/ListEntry.java index a1c6172ba..2f9d0ff2d 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/widget/ListEntry.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/widget/ListEntry.java @@ -1,34 +1,34 @@ package pl.skidam.automodpack.client.ui.widget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.ObjectSelectionList; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import pl.skidam.automodpack.client.ui.TextColors; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; -/*? if <1.20 {*/ -/*import net.minecraft.client.util.math.MatrixStack; -*//*?} else {*/ -import net.minecraft.client.gui.DrawContext; -import pl.skidam.automodpack.mixin.core.DrawContextAccessor; -/*?}*/ +/*? if >=1.20 {*/ +import net.minecraft.client.gui.GuiGraphics; +/*?} else {*/ +/*import com.mojang.blaze3d.vertex.PoseStack; +*//*?}*/ -public class ListEntry extends AlwaysSelectedEntryListWidget.Entry { +public class ListEntry extends ObjectSelectionList.Entry { - protected final MinecraftClient client; - private final MutableText text; + protected final Minecraft client; + private final MutableComponent text; private final String mainPageUrl; private final boolean bigFont; - public ListEntry(MutableText text, String mainPageUrl, boolean bigFont, MinecraftClient client) { + public ListEntry(MutableComponent text, String mainPageUrl, boolean bigFont, Minecraft client) { this.text = text; this.mainPageUrl = mainPageUrl; this.client = client; this.bigFont = bigFont; } - public ListEntry(MutableText text, boolean bigFont, MinecraftClient client) { + public ListEntry(MutableComponent text, boolean bigFont, Minecraft client) { this.text = text; this.mainPageUrl = null; this.client = client; @@ -37,20 +37,23 @@ public ListEntry(MutableText text, boolean bigFont, MinecraftClient client) { /*? if >=1.17 {*/ @Override - public Text getNarration() { + public Component getNarration() { return text; } /*?}*/ @Override /*? if <1.20 {*/ - /*public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { - VersionedMatrices versionedMatrices = new VersionedMatrices(); + /*public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + VersionedMatrices versionedMatrices = new VersionedMatrices(); *//*?} else {*/ - public void render(DrawContext context, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { - VersionedMatrices versionedMatrices = new VersionedMatrices(this.client, ((DrawContextAccessor) context).vertexConsumers()); + public void render(GuiGraphics GuiGraphics, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + VersionedMatrices versionedMatrices = new VersionedMatrices(GuiGraphics); /*?}*/ - versionedMatrices.push(); + versionedRender(versionedMatrices, index, y, x, entryWidth, entryHeight, mouseX, mouseY, hovered, tickDelta); + } + public void versionedRender(VersionedMatrices versionedMatrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { + versionedMatrices.pushPose(); int centeredX = x + entryWidth / 2; int centeredY = y + entryHeight / 2; @@ -63,7 +66,7 @@ public void render(DrawContext context, int index, int y, int x, int entryWidth, centeredY = centeredY - 10 / 2; } - VersionedScreen.drawCenteredTextWithShadow(versionedMatrices, client.textRenderer, text, centeredX, centeredY, 16777215); + VersionedScreen.drawCenteredTextWithShadow(versionedMatrices, client.font, text, centeredX, centeredY, TextColors.WHITE); // if (mainPageUrls != null) { // int badgeX = x - 42; @@ -75,10 +78,10 @@ public void render(DrawContext context, int index, int y, int x, int entryWidth, // } // } - versionedMatrices.pop(); + versionedMatrices.popPose(); } - public MutableText getText() { + public MutableComponent getText() { return this.text; } @@ -95,4 +98,4 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { public boolean mouseReleased(double mouseX, double mouseY, int button) { return false; } -} +} \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/widget/ListEntryWidget.java b/src/main/java/pl/skidam/automodpack/client/ui/widget/ListEntryWidget.java index 016c39976..6dcf6bd11 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/widget/ListEntryWidget.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/widget/ListEntryWidget.java @@ -1,25 +1,25 @@ package pl.skidam.automodpack.client.ui.widget; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.widget.AlwaysSelectedEntryListWidget; -import net.minecraft.text.MutableText; -import net.minecraft.util.Formatting; -import net.minecraft.util.math.MathHelper; import pl.skidam.automodpack.client.ui.versioned.VersionedText; import java.util.Map; +import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.ObjectSelectionList; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.Mth; /*? if <1.20 {*/ -/*import net.minecraft.client.util.math.MatrixStack; +/*import com.mojang.blaze3d.vertex.PoseStack; *//*?} elif <1.20.3 {*/ -/*import net.minecraft.client.gui.DrawContext; +/*import net.minecraft.client.gui.GuiGraphics; *//*?}*/ -public class ListEntryWidget extends AlwaysSelectedEntryListWidget { +public class ListEntryWidget extends ObjectSelectionList { private boolean scrolling; - public ListEntryWidget(Map changelogs, MinecraftClient client, int width, int height, int top, int bottom, int itemHeight) { + public ListEntryWidget(Map changelogs, Minecraft client, int width, int height, int top, int bottom, int itemHeight) { /*? if <1.20.3 {*/ /*super(client, width, height, top, bottom, itemHeight); *//*?} else {*/ @@ -30,7 +30,7 @@ public ListEntryWidget(Map changelogs, MinecraftClient client, i this.clearEntries(); if (changelogs == null || changelogs.isEmpty()) { - ListEntry entry = new ListEntry(VersionedText.literal("No changelogs found").formatted(Formatting.BOLD), true, this.client); + ListEntry entry = new ListEntry(VersionedText.literal("No changelogs found").withStyle(ChatFormatting.BOLD), true, this.minecraft); this.addEntry(entry); return; } @@ -39,58 +39,58 @@ public ListEntryWidget(Map changelogs, MinecraftClient client, i String textString = changelog.getKey(); String mainPageUrl = changelog.getValue(); - MutableText text = VersionedText.literal(textString); + MutableComponent text = VersionedText.literal(textString); if (textString.startsWith("+")) { - text = text.formatted(Formatting.GREEN); + text = text.withStyle(ChatFormatting.GREEN); } else if (textString.startsWith("-")) { - text = text.formatted(Formatting.RED); + text = text.withStyle(ChatFormatting.RED); } - ListEntry entry = new ListEntry(text, mainPageUrl, false, this.client); + ListEntry entry = new ListEntry(text, mainPageUrl, false, this.minecraft); this.addEntry(entry); } } /*? if <=1.20.2 {*/ - /*public void render(/^? if <1.20 {^/ /^MatrixStack ^//^?} else {^/ DrawContext /^?}^/ matrices, int mouseX, int mouseY, float delta) { + /*public void render(/^? if <1.20 {^/ /^PoseStack ^//^?} else {^/ GuiGraphics /^?}^/ matrices, int mouseX, int mouseY, float delta) { super.render(matrices, mouseX, mouseY, delta); } *//*?}*/ - /*? if >1.21.3 {*/ - /*public double getScrollAmount() { - return this.getScrollY(); + /*? if >=1.21.4 {*/ + public double getScrollAmount() { + return this.scrollAmount(); } - *//*?}*/ + /*?}*/ public final ListEntry getEntryAtPos(double x, double y) { - int int_5 = MathHelper.floor(y - (double) getTop()) - this.headerHeight + (int) this.getScrollAmount() - 4; + int int_5 = Mth.floor(y - (double) getTop()) - this.headerHeight + (int) this.getScrollAmount() - 4; int index = int_5 / this.itemHeight; - return x < (double) this.getScrollbarX() && x >= (double) getRowLeft() && x <= (double) (getRowLeft() + getRowWidth()) && index >= 0 && int_5 >= 0 && index < this.getEntryCount() ? this.children().get(index) : null; + return x < (double) this.getScrollbarPosition() && x >= (double) getRowLeft() && x <= (double) (getRowLeft() + getRowWidth()) && index >= 0 && int_5 >= 0 && index < this.getItemCount() ? this.children().get(index) : null; } public int getTop() { /*? if <1.20.3 {*/ - /*return this.top; + /*return this.y0; *//*?} else {*/ return this.getY(); /*?}*/ } /*? if <=1.21.3 {*/ - @Override + /*@Override protected void updateScrollingState(double mouseX, double mouseY, int button) { super.updateScrollingState(mouseX, mouseY, button); - this.scrolling = button == 0 && mouseX >= (double) this.getScrollbarX() && mouseX < (double) (this.getScrollbarX() + 6); + this.scrolling = button == 0 && mouseX >= (double) this.getScrollbarPosition() && mouseX < (double) (this.getScrollbarPosition() + 6); } - /*?}*/ + *//*?}*/ @Override public boolean mouseClicked(double mouseX, double mouseY, int button) { /*? if <=1.21.3 {*/ - this.updateScrollingState(mouseX, mouseY, button); - /*?}*/ + /*this.updateScrollingState(mouseX, mouseY, button); + *//*?}*/ if (!this.isMouseOver(mouseX, mouseY)) { return false; } else { @@ -116,7 +116,7 @@ public void setSelected(ListEntry entry) { } } - protected int getScrollbarX() { + protected int getScrollbarPosition() { return this.width - 6; } diff --git a/src/main/java/pl/skidam/automodpack/init/Common.java b/src/main/java/pl/skidam/automodpack/init/Common.java index 0bf2f45af..c875333ae 100644 --- a/src/main/java/pl/skidam/automodpack/init/Common.java +++ b/src/main/java/pl/skidam/automodpack/init/Common.java @@ -1,7 +1,7 @@ package pl.skidam.automodpack.init; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.Identifier; import pl.skidam.automodpack.loader.GameCall; import pl.skidam.automodpack.networking.ModPackets; import pl.skidam.automodpack_core.modpack.ModpackExecutor; @@ -81,11 +81,11 @@ public static void beforeShutdownServer() { fullpacks.shutdownExecutor(); } - public static Identifier id(String path) { + public static ResourceLocation id(String path) { /*? if >1.19.1 {*/ - return Identifier.of(MOD_ID, path); + return ResourceLocation.tryBuild(MOD_ID, path); /*?} else {*/ - /*return new Identifier(MOD_ID, path); + /*return new ResourceLocation(MOD_ID, path); *//*?}*/ } } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/ClientConnectionAccessor.java b/src/main/java/pl/skidam/automodpack/mixin/core/ClientConnectionAccessor.java index a26c445f9..4b03d2637 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/ClientConnectionAccessor.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/ClientConnectionAccessor.java @@ -1,11 +1,11 @@ package pl.skidam.automodpack.mixin.core; import io.netty.channel.Channel; -import net.minecraft.network.ClientConnection; +import net.minecraft.network.Connection; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(ClientConnection.class) +@Mixin(Connection.class) public interface ClientConnectionAccessor { @Accessor("channel") Channel getChannel(); diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/ClientLoginNetworkHandlerAccessor.java b/src/main/java/pl/skidam/automodpack/mixin/core/ClientLoginNetworkHandlerAccessor.java index f217c2b77..4f5486d14 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/ClientLoginNetworkHandlerAccessor.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/ClientLoginNetworkHandlerAccessor.java @@ -1,12 +1,12 @@ package pl.skidam.automodpack.mixin.core; -import net.minecraft.client.network.ClientLoginNetworkHandler; -import net.minecraft.network.ClientConnection; +import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; +import net.minecraft.network.Connection; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(ClientLoginNetworkHandler.class) +@Mixin(ClientHandshakePacketListenerImpl.class) public interface ClientLoginNetworkHandlerAccessor { @Accessor("connection") - ClientConnection getConnection(); + Connection getConnection(); } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/ClientLoginNetworkHandlerMixin.java b/src/main/java/pl/skidam/automodpack/mixin/core/ClientLoginNetworkHandlerMixin.java index 264484667..9afc36c65 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/ClientLoginNetworkHandlerMixin.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/ClientLoginNetworkHandlerMixin.java @@ -1,8 +1,8 @@ package pl.skidam.automodpack.mixin.core; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientLoginNetworkHandler; -import net.minecraft.network.packet.s2c.login.LoginQueryRequestS2CPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; +import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -12,23 +12,23 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import pl.skidam.automodpack.networking.client.ClientLoginNetworkAddon; -@Mixin(value = ClientLoginNetworkHandler.class, priority = 300) +@Mixin(value = ClientHandshakePacketListenerImpl.class, priority = 300) public class ClientLoginNetworkHandlerMixin { - @Shadow @Final private MinecraftClient client; + @Shadow @Final private Minecraft minecraft; @Unique private ClientLoginNetworkAddon autoModpack$addon; @Inject(method = "", at = @At("RETURN")) private void initAddon(CallbackInfo ci) { - this.autoModpack$addon = new ClientLoginNetworkAddon((ClientLoginNetworkHandler) (Object) this, this.client); + this.autoModpack$addon = new ClientLoginNetworkAddon((ClientHandshakePacketListenerImpl) (Object) this, this.minecraft); } @Inject( - method = "onQueryRequest", + method = "handleCustomQuery", at = @At(value = "HEAD"), cancellable = true ) - private void handleQueryRequest(LoginQueryRequestS2CPacket packet, CallbackInfo ci) { + private void handleQueryRequest(ClientboundCustomQueryPacket packet, CallbackInfo ci) { if (this.autoModpack$addon == null) { return; } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/ConnectScreenMixin.java b/src/main/java/pl/skidam/automodpack/mixin/core/ConnectScreenMixin.java index 58d98bf70..691dc615a 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/ConnectScreenMixin.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/ConnectScreenMixin.java @@ -1,8 +1,8 @@ package pl.skidam.automodpack.mixin.core; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ServerAddress; -import net.minecraft.client.network.ServerInfo; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.ConnectScreen; +import net.minecraft.client.multiplayer.resolver.ServerAddress; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -12,27 +12,25 @@ import pl.skidam.automodpack.networking.ModPackets; /*? if >= 1.20.5 {*/ -import net.minecraft.client.network.CookieStorage; +import net.minecraft.client.multiplayer.TransferState; /*?}*/ -/*? if >=1.20.3 {*/ -import net.minecraft.client.gui.screen.multiplayer.ConnectScreen; -/*?} else {*/ -/*import net.minecraft.client.gui.screen.ConnectScreen; - *//*?}*/ +/*? if > 1.19.3 {*/ +import net.minecraft.client.multiplayer.ServerData; +/*?}*/ @Mixin(ConnectScreen.class) public abstract class ConnectScreenMixin { /*? if >= 1.20.5 {*/ - @Inject(method = "connect(Lnet/minecraft/client/MinecraftClient;Lnet/minecraft/client/network/ServerAddress;Lnet/minecraft/client/network/ServerInfo;Lnet/minecraft/client/network/CookieStorage;)V", at = @At("HEAD")) - public void onConnect(MinecraftClient client, ServerAddress address, ServerInfo info, CookieStorage cookieStorage, CallbackInfo ci) { - /*?} else if > 1.19.2 {*/ - /*@Inject(method = "connect(Lnet/minecraft/client/MinecraftClient;Lnet/minecraft/client/network/ServerAddress;Lnet/minecraft/client/network/ServerInfo;)V", at = @At("HEAD")) - public void onConnect(MinecraftClient client, ServerAddress address, ServerInfo info, CallbackInfo ci) { + @Inject(method = "connect", at = @At("HEAD")) + public void onConnect(Minecraft client, ServerAddress address, ServerData info, TransferState cookieStorage, CallbackInfo ci) { + /*?} else if > 1.19.3 {*/ + /*@Inject(method = "connect", at = @At("HEAD")) + public void onConnect(Minecraft client, ServerAddress address, ServerData info, CallbackInfo ci) { *//*?} else {*/ - /*@Inject(method = "connect(Lnet/minecraft/client/MinecraftClient;Lnet/minecraft/client/network/ServerAddress;)V", at = @At("HEAD")) - public void onConnect(MinecraftClient client, ServerAddress address, CallbackInfo ci) { + /*@Inject(method = "connect", at = @At("HEAD")) + public void onConnect(Minecraft client, ServerAddress address, CallbackInfo ci) { *//*?}*/ - ModPackets.setOriginalServerAddress(AddressHelpers.format(address.getAddress(), address.getPort())); + ModPackets.setOriginalServerAddress(AddressHelpers.format(address.getHost(), address.getPort())); } } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/DrawContextAccessor.java b/src/main/java/pl/skidam/automodpack/mixin/core/DrawContextAccessor.java deleted file mode 100644 index f738234f0..000000000 --- a/src/main/java/pl/skidam/automodpack/mixin/core/DrawContextAccessor.java +++ /dev/null @@ -1,21 +0,0 @@ -package pl.skidam.automodpack.mixin.core; - -import org.spongepowered.asm.mixin.Mixin; -/*? if >=1.20 {*/ -import net.minecraft.client.gui.DrawContext; -import org.spongepowered.asm.mixin.gen.Accessor; -import net.minecraft.client.render.VertexConsumerProvider; - -// TODO find better way to do this, its mixin only for 1.20 and above -@Mixin(DrawContext.class) -/*?} else {*/ -/*import pl.skidam.automodpack.init.Common; -@Mixin(Common.class) -*//*?}*/ -public interface DrawContextAccessor { - - /*? if >=1.20 {*/ - @Accessor("vertexConsumers") - VertexConsumerProvider.Immediate vertexConsumers(); - /*?}*/ -} \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/FabricLoginMixin.java b/src/main/java/pl/skidam/automodpack/mixin/core/FabricLoginMixin.java index e218d7849..5f9a19e1f 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/FabricLoginMixin.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/FabricLoginMixin.java @@ -2,7 +2,7 @@ import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import net.fabricmc.fabric.impl.networking.server.ServerLoginNetworkAddon; -import net.minecraft.util.Identifier; +import net.minecraft.resources.ResourceLocation; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Pseudo; import org.spongepowered.asm.mixin.injection.At; @@ -19,7 +19,7 @@ public class FabricLoginMixin { at = @At(value = "INVOKE", target = "Ljava/util/Map;put(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") ) private boolean dontRemoveAutoModpackChannels(Map instance, Object key, Object value) { - if (value instanceof Identifier id) { + if (value instanceof ResourceLocation id) { // If AutoModpack id, return false return LoginNetworkingIDs.getByKey(id) == null; } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/LoginQueryRequestS2CPacketMixin.java b/src/main/java/pl/skidam/automodpack/mixin/core/LoginQueryRequestS2CPacketMixin.java index 132f8e4d2..a429126b2 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/LoginQueryRequestS2CPacketMixin.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/LoginQueryRequestS2CPacketMixin.java @@ -2,10 +2,10 @@ import org.spongepowered.asm.mixin.Mixin; /*? if >=1.20.2 {*/ -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.login.LoginQueryRequestPayload; -import net.minecraft.network.packet.s2c.login.LoginQueryRequestS2CPacket; -import net.minecraft.util.Identifier; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; +import net.minecraft.network.protocol.login.custom.CustomQueryPayload; +import net.minecraft.resources.ResourceLocation; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -16,7 +16,7 @@ import pl.skidam.automodpack_core.GlobalVariables; // TODO find better way to do this, its mixin only for 1.20.2 and above -@Mixin(value = LoginQueryRequestS2CPacket.class, priority = 300) +@Mixin(value = ClientboundCustomQueryPacket.class, priority = 300) /*?} else {*/ /*import pl.skidam.automodpack.init.Common; @Mixin(Common.class) @@ -27,7 +27,7 @@ public class LoginQueryRequestS2CPacketMixin { @Shadow @Final private static int MAX_PAYLOAD_SIZE; @Inject(method = "readPayload", at = @At("HEAD"), cancellable = true) - private static void readPayload(Identifier id, PacketByteBuf buf, CallbackInfoReturnable cir) { + private static void readPayload(ResourceLocation id, FriendlyByteBuf buf, CallbackInfoReturnable cir) { if (id.getNamespace().equals(GlobalVariables.MOD_ID)) { cir.setReturnValue(new LoginRequestPayload(id, PayloadHelper.read(buf, MAX_PAYLOAD_SIZE))); } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/LoginQueryResponseC2SPacketMixin.java b/src/main/java/pl/skidam/automodpack/mixin/core/LoginQueryResponseC2SPacketMixin.java index d59fa759d..b9c4deb84 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/LoginQueryResponseC2SPacketMixin.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/LoginQueryResponseC2SPacketMixin.java @@ -2,10 +2,10 @@ import org.spongepowered.asm.mixin.Mixin; /*? if >=1.20.2 {*/ -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.c2s.login.LoginQueryResponseC2SPacket; -import net.minecraft.network.packet.c2s.login.LoginQueryResponsePayload; -import net.minecraft.util.Identifier; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; +import net.minecraft.network.protocol.login.custom.CustomQueryAnswerPayload; +import net.minecraft.resources.ResourceLocation; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -16,7 +16,7 @@ import pl.skidam.automodpack.networking.client.LoginResponsePayload; // TODO find better way to do this, its mixin only for 1.20.2 and above -@Mixin(value = LoginQueryResponseC2SPacket.class, priority = 300) +@Mixin(value = ServerboundCustomQueryAnswerPacket.class, priority = 300) /*?} else {*/ /*import pl.skidam.automodpack.init.Common; @Mixin(Common.class) @@ -28,8 +28,8 @@ public class LoginQueryResponseC2SPacketMixin { private static int MAX_PAYLOAD_SIZE; @Inject(method = "readPayload", at = @At("HEAD"), cancellable = true) - private static void readResponse(int queryId, PacketByteBuf buf, CallbackInfoReturnable cir) { - Identifier automodpackID = LoginNetworkingIDs.getByValue(queryId); + private static void readResponse(int queryId, FriendlyByteBuf buf, CallbackInfoReturnable cir) { + ResourceLocation automodpackID = LoginNetworkingIDs.getByValue(queryId); if (automodpackID == null) { return; } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/MinecraftServerMixin.java b/src/main/java/pl/skidam/automodpack/mixin/core/MinecraftServerMixin.java index 40663df21..244195c71 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/MinecraftServerMixin.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/MinecraftServerMixin.java @@ -10,17 +10,13 @@ @Mixin(MinecraftServer.class) public class MinecraftServerMixin { - /*? if >=1.19.3 {*/ - @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;createMetadata()Lnet/minecraft/server/ServerMetadata;", ordinal = 0), method = "runServer") -/*?} else {*/ - /*@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;setFavicon(Lnet/minecraft/server/ServerMetadata;)V", ordinal = 0), method = "runServer") -*//*?}*/ + @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;initServer()Z", shift = At.Shift.AFTER), method = "runServer") private void afterSetupServer(CallbackInfo info) { Common.server = (MinecraftServer) (Object) this; Common.afterSetupServer(); } - @Inject(at = @At("HEAD"), method = "shutdown") + @Inject(at = @At("HEAD"), method = "stopServer") private void beforeShutdownServer(CallbackInfo info) { Common.beforeShutdownServer(); } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/MusicTrackerMixin.java b/src/main/java/pl/skidam/automodpack/mixin/core/MusicTrackerMixin.java index 38f39ac66..dd65e1043 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/MusicTrackerMixin.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/MusicTrackerMixin.java @@ -1,31 +1,32 @@ package pl.skidam.automodpack.mixin.core; -/*? if >1.21.3 {*/ -/*import net.minecraft.client.sound.MusicInstance; -*//*?} else {*/ -import net.minecraft.sound.MusicSound; -/*?}*/ -import net.minecraft.client.sound.MusicTracker; +import net.minecraft.client.sounds.MusicManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import pl.skidam.automodpack.client.audio.AudioManager; -@Mixin(MusicTracker.class) +/*? if >=1.21.4 {*/ +import net.minecraft.client.sounds.MusicInfo; +/*?} else {*/ +/*import net.minecraft.sounds.Music; +*//*?}*/ + +@Mixin(MusicManager.class) public class MusicTrackerMixin { @Inject( - method = "play", + method = "startPlaying", at = @At("HEAD"), cancellable = true ) - /*? if >1.21.3 {*/ - /*private void play(MusicInstance music, CallbackInfo ci) { - *//*?} else {*/ - private void play(MusicSound type, CallbackInfo ci) { - /*?}*/ + /*? if >=1.21.4 {*/ + private void play(MusicInfo p_383115_, CallbackInfo ci) { + /*?} else {*/ + /*private void play(Music type, CallbackInfo ci) { + *//*?}*/ if (AudioManager.isMusicPlaying()) { ci.cancel(); } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/PlayerManagerMixin.java b/src/main/java/pl/skidam/automodpack/mixin/core/PlayerManagerMixin.java index 76e62d66d..ebbb4628a 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/PlayerManagerMixin.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/PlayerManagerMixin.java @@ -1,16 +1,13 @@ package pl.skidam.automodpack.mixin.core; import com.mojang.authlib.GameProfile; -import net.minecraft.network.ClientConnection; -import net.minecraft.server.PlayerManager; -/*? if >1.20.3 {*/ -import net.minecraft.server.network.ConnectedClientData; -/*?}*/ -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.Text; -import net.minecraft.text.TextColor; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.network.Connection; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextColor; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.players.PlayerList; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -18,21 +15,25 @@ import pl.skidam.automodpack.client.ui.versioned.VersionedText; import pl.skidam.automodpack.init.Common; -/*? if >1.21.4 {*/ -/*import java.net.URI; -*//*?}*/ +/*? if >1.20.3 {*/ +import net.minecraft.server.network.CommonListenerCookie; +/*?}*/ + +/*? if >=1.21.5 {*/ +import java.net.URI; +/*?}*/ import static pl.skidam.automodpack_core.GlobalVariables.serverConfig; -@Mixin(PlayerManager.class) +@Mixin(PlayerList.class) public class PlayerManagerMixin { /*? if >1.20.3 {*/ - @Inject(at = @At("TAIL"), method = "onPlayerConnect") - private void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, ConnectedClientData clientData, CallbackInfo ci) { + @Inject(at = @At("TAIL"), method = "placeNewPlayer") + private void onPlayerConnect(Connection connection, ServerPlayer player, CommonListenerCookie clientData, CallbackInfo ci) { /*?} else {*/ -/*@Inject(at = @At("TAIL"), method = "onPlayerConnect") -private void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, CallbackInfo ci) { +/*@Inject(at = @At("TAIL"), method = "placeNewPlayer") +private void onPlayerConnect(Connection netManager, ServerPlayer player, CallbackInfo ci) { *//*?}*/ GameProfile profile = player.getGameProfile(); String playerName = profile.getName(); @@ -44,15 +45,15 @@ private void onPlayerConnect(ClientConnection connection, ServerPlayerEntity pla if (serverConfig.nagUnModdedClients && !Common.players.get(playerName)) { // Send chat nag message which is clickable and opens the link - Text nagText = VersionedText.literal(serverConfig.nagMessage).styled(style -> style.withBold(true)); - Text nagClickableText = VersionedText.literal(serverConfig.nagClickableMessage).styled(style -> style.withUnderline(true).withColor(TextColor.fromFormatting(Formatting.BLUE)) - /*? if >1.21.4 {*/ - /*.withClickEvent(new ClickEvent.OpenUrl(URI.create(serverConfig.nagClickableLink)))); - *//*?} else {*/ - .withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, serverConfig.nagClickableLink))); - /*?}*/ - player.sendMessage(nagText, false); - player.sendMessage(nagClickableText, false); + Component nagText = VersionedText.literal(serverConfig.nagMessage).withStyle(style -> style.withBold(true)); + Component nagClickableText = VersionedText.literal(serverConfig.nagClickableMessage).withStyle(style -> style.withUnderlined(true).withColor(TextColor.fromLegacyFormat(ChatFormatting.BLUE)) + /*? if >=1.21.5 {*/ + .withClickEvent(new ClickEvent.OpenUrl(URI.create(serverConfig.nagClickableLink)))); + /*?} else {*/ + /*.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, serverConfig.nagClickableLink))); + *//*?}*/ + player.displayClientMessage(nagText, false); + player.displayClientMessage(nagClickableText, false); } } } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/ServerLoginNetworkHandlerAccessor.java b/src/main/java/pl/skidam/automodpack/mixin/core/ServerLoginNetworkHandlerAccessor.java index fa8c8bef4..99a6dfd8c 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/ServerLoginNetworkHandlerAccessor.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/ServerLoginNetworkHandlerAccessor.java @@ -1,19 +1,23 @@ package pl.skidam.automodpack.mixin.core; import com.mojang.authlib.GameProfile; -import net.minecraft.network.ClientConnection; +import net.minecraft.network.Connection; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginNetworkHandler; +import net.minecraft.server.network.ServerLoginPacketListenerImpl; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(ServerLoginNetworkHandler.class) +@Mixin(ServerLoginPacketListenerImpl.class) public interface ServerLoginNetworkHandlerAccessor { - @Accessor("profile") + /*? if >= 1.20.2 {*/ + @Accessor("authenticatedProfile") + /*?} else {*/ + /*@Accessor("gameProfile") + *//*?}*/ GameProfile getGameProfile(); @Accessor - ClientConnection getConnection(); + Connection getConnection(); @Accessor MinecraftServer getServer(); diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/ServerLoginNetworkHandlerMixin.java b/src/main/java/pl/skidam/automodpack/mixin/core/ServerLoginNetworkHandlerMixin.java index b1f3d1390..89b34384c 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/ServerLoginNetworkHandlerMixin.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/ServerLoginNetworkHandlerMixin.java @@ -1,7 +1,7 @@ package pl.skidam.automodpack.mixin.core; -import net.minecraft.network.packet.c2s.login.LoginQueryResponseC2SPacket; -import net.minecraft.server.network.ServerLoginNetworkHandler; +import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; +import net.minecraft.server.network.ServerLoginPacketListenerImpl; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -9,10 +9,10 @@ import pl.skidam.automodpack.networking.client.LoginResponsePayload; import pl.skidam.automodpack.networking.server.ServerLoginNetworkAddon; -@Mixin(value = ServerLoginNetworkHandler.class, priority = 300) +@Mixin(value = ServerLoginPacketListenerImpl.class, priority = 300) public abstract class ServerLoginNetworkHandlerMixin { - @Shadow private ServerLoginNetworkHandler.State state; + @Shadow private ServerLoginPacketListenerImpl.State state; @Unique private ServerLoginNetworkAddon automodpack$addon; @Inject( @@ -20,15 +20,15 @@ public abstract class ServerLoginNetworkHandlerMixin { at = @At("RETURN") ) private void initAddon(CallbackInfo ci) { - this.automodpack$addon = new ServerLoginNetworkAddon((ServerLoginNetworkHandler) (Object) this); + this.automodpack$addon = new ServerLoginNetworkAddon((ServerLoginPacketListenerImpl) (Object) this); } @Inject( - method = "onQueryResponse", + method = "handleCustomQueryPacket", at = @At("HEAD"), cancellable = true ) - private void handleCustomPayload(LoginQueryResponseC2SPacket packet, CallbackInfo ci) { + private void handleCustomPayload(ServerboundCustomQueryAnswerPacket packet, CallbackInfo ci) { if (this.automodpack$addon == null) { return; } @@ -38,7 +38,7 @@ private void handleCustomPayload(LoginQueryResponseC2SPacket packet, CallbackInf ci.cancel(); // We have handled it, cancel vanilla behavior } else { /*? if >=1.20.2 {*/ - if (packet.response() instanceof LoginResponsePayload response) { + if (packet.payload() instanceof LoginResponsePayload response) { response.data().skipBytes(response.data().readableBytes()); } /*?}*/ @@ -55,7 +55,7 @@ private void sendOurPackets(CallbackInfo ci) { return; } - if (state != ServerLoginNetworkHandler.State.NEGOTIATING && state != ServerLoginNetworkHandler.State./*? if <1.20.2 {*/ /*READY_TO_ACCEPT *//*?} else {*/VERIFYING/*?}*/) { + if (state != ServerLoginPacketListenerImpl.State.NEGOTIATING && state != ServerLoginPacketListenerImpl.State./*? if <1.20.2 {*/ /*READY_TO_ACCEPT *//*?} else {*/VERIFYING/*?}*/) { return; } diff --git a/src/main/java/pl/skidam/automodpack/mixin/core/ServerNetworkIoMixin.java b/src/main/java/pl/skidam/automodpack/mixin/core/ServerNetworkIoMixin.java index 7b0994afe..6de05e01c 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/core/ServerNetworkIoMixin.java +++ b/src/main/java/pl/skidam/automodpack/mixin/core/ServerNetworkIoMixin.java @@ -10,7 +10,7 @@ import static pl.skidam.automodpack_core.GlobalVariables.*; -@Mixin(targets = "net/minecraft/server/ServerNetworkIo$1", priority = 2137) +@Mixin(targets = "net/minecraft/server/network/ServerConnectionListener$1", priority = 2137) public abstract class ServerNetworkIoMixin { @Inject( @@ -18,7 +18,7 @@ public abstract class ServerNetworkIoMixin { at = @At("TAIL") ) private void injectAutoModpackHost(Channel channel, CallbackInfo ci) { - if (!serverConfig.hostModpackOnMinecraftPort) { + if (serverConfig.bindPort != -1) { return; } diff --git a/src/main/java/pl/skidam/automodpack/mixin/dev/TestButton.java b/src/main/java/pl/skidam/automodpack/mixin/dev/TestButton.java index 5a821a87d..40024ef18 100644 --- a/src/main/java/pl/skidam/automodpack/mixin/dev/TestButton.java +++ b/src/main/java/pl/skidam/automodpack/mixin/dev/TestButton.java @@ -1,8 +1,5 @@ package pl.skidam.automodpack.mixin.dev; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.TitleScreen; -import net.minecraft.text.Text; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -14,10 +11,14 @@ import static pl.skidam.automodpack_core.GlobalVariables.LOADER_MANAGER; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.network.chat.Component; + @Mixin(TitleScreen.class) public class TestButton extends Screen { - protected TestButton(Text title) { + protected TestButton(Component title) { super(title); } @@ -33,7 +34,7 @@ private void init(CallbackInfo ci) { } /*? if >=1.17 {*/ - this.addDrawableChild( + this.addRenderableWidget( /*?} else {*//* this.addButton( *//*?}*/ diff --git a/src/main/java/pl/skidam/automodpack/modpack/Commands.java b/src/main/java/pl/skidam/automodpack/modpack/Commands.java index 2e255c12b..c804b1fdb 100644 --- a/src/main/java/pl/skidam/automodpack/modpack/Commands.java +++ b/src/main/java/pl/skidam/automodpack/modpack/Commands.java @@ -4,66 +4,97 @@ import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.context.CommandContext; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.util.Formatting; -import net.minecraft.util.Util; import pl.skidam.automodpack.client.ui.versioned.VersionedCommandSource; import pl.skidam.automodpack.client.ui.versioned.VersionedText; import pl.skidam.automodpack_core.auth.SecretsStore; import pl.skidam.automodpack_core.config.ConfigTools; import pl.skidam.automodpack_core.config.Jsons; - import java.util.Set; - -import static net.minecraft.server.command.CommandManager.literal; +import net.minecraft.ChatFormatting; +import net.minecraft.Util; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.MutableComponent; + +import static net.minecraft.commands.Commands.literal; import static pl.skidam.automodpack_core.GlobalVariables.*; public class Commands { - public static void register(CommandDispatcher dispatcher) { - dispatcher.register( + public static void register(CommandDispatcher dispatcher) { + var automodpackNode = dispatcher.register( literal("automodpack") .executes(Commands::about) .then(literal("generate") - .requires((source) -> source.hasPermissionLevel(3)) + .requires((source) -> source.hasPermission(3)) .executes(Commands::generateModpack) ) .then(literal("host") - .requires((source) -> source.hasPermissionLevel(3)) + .requires((source) -> source.hasPermission(3)) .executes(Commands::modpackHostAbout) .then(literal("start") - .requires((source) -> source.hasPermissionLevel(3)) + .requires((source) -> source.hasPermission(3)) .executes(Commands::startModpackHost) ) .then(literal("stop") - .requires((source) -> source.hasPermissionLevel(3)) + .requires((source) -> source.hasPermission(3)) .executes(Commands::stopModpackHost) ) .then(literal("restart") - .requires((source) -> source.hasPermissionLevel(3)) + .requires((source) -> source.hasPermission(3)) .executes(Commands::restartModpackHost) ) .then(literal("connections") - .requires((source) -> source.hasPermissionLevel(3)) + .requires((source) -> source.hasPermission(3)) .executes(Commands::connections) ) + .then(literal("fingerprint") + .requires((source) -> source.hasPermission(3)) + .executes(Commands::fingerprint) + ) ) .then(literal("config") - .requires((source) -> source.hasPermissionLevel(3)) + .requires((source) -> source.hasPermission(3)) .then(literal("reload") - .requires((source) -> source.hasPermissionLevel(3)) + .requires((source) -> source.hasPermission(3)) .executes(Commands::reload) ) ) ); + + dispatcher.register( + literal("amp") + .executes(Commands::about) + .redirect(automodpackNode) + ); + } + + private static int fingerprint(CommandContext context) { + String fingerprint = hostServer.getCertificateFingerprint(); + if (fingerprint != null) { + MutableComponent fingerprintText = VersionedText.literal(fingerprint).withStyle(style -> style + /*? if >=1.21.5 {*/ + .withHoverEvent(new HoverEvent.ShowText(VersionedText.translatable("chat.copy.click"))) + .withClickEvent(new ClickEvent.CopyToClipboard(fingerprint))); + /*?} else {*/ + /*.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, VersionedText.translatable("chat.copy.click"))) + .withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, fingerprint))); + *//*?}*/ + send(context, "Certificate fingerprint", ChatFormatting.WHITE, fingerprintText, ChatFormatting.YELLOW, false); + } else { + send(context, "Certificate fingerprint is not available. Make sure the server is running with TLS enabled.", ChatFormatting.RED, false); + } + + return Command.SINGLE_SUCCESS; } - private static int connections(CommandContext serverCommandSourceCommandContext) { - Util.getMainWorkerExecutor().execute(() -> { + private static int connections(CommandContext context) { + Util.backgroundExecutor().execute(() -> { var connections = hostServer.getConnections(); var uniqueSecrets = Set.copyOf(connections.values()); - send(serverCommandSourceCommandContext, String.format("Active connections: %d Unique connections: %d ", connections.size(), uniqueSecrets.size()), Formatting.YELLOW, false); + send(context, String.format("Active connections: %d Unique connections: %d ", connections.size(), uniqueSecrets.size()), ChatFormatting.YELLOW, false); for (String secret : uniqueSecrets) { var playerSecretPair = SecretsStore.getHostSecret(secret); @@ -74,65 +105,65 @@ private static int connections(CommandContext serverCommand long connNum = connections.values().stream().filter(secret::equals).count(); - send(serverCommandSourceCommandContext, String.format("Player: %s (%s) is downloading modpack using %d connections", profile.getName(), playerId, connNum), Formatting.GREEN, false); + send(context, String.format("Player: %s (%s) is downloading modpack using %d connections", profile.getName(), playerId, connNum), ChatFormatting.GREEN, false); } }); return Command.SINGLE_SUCCESS; } - private static int reload(CommandContext context) { - Util.getMainWorkerExecutor().execute(() -> { - var tempServerConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFields.class); + private static int reload(CommandContext context) { + Util.backgroundExecutor().execute(() -> { + var tempServerConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV2.class); if (tempServerConfig != null) { serverConfig = tempServerConfig; - send(context, "AutoModpack server config reloaded!", Formatting.GREEN, true); + send(context, "AutoModpack server config reloaded!", ChatFormatting.GREEN, true); } else { - send(context, "Error while reloading config file!", Formatting.RED, true); + send(context, "Error while reloading config file!", ChatFormatting.RED, true); } }); return Command.SINGLE_SUCCESS; } - private static int startModpackHost(CommandContext context) { - Util.getMainWorkerExecutor().execute(() -> { + private static int startModpackHost(CommandContext context) { + Util.backgroundExecutor().execute(() -> { if (!hostServer.isRunning()) { - send(context, "Starting modpack hosting...", Formatting.YELLOW, true); + send(context, "Starting modpack hosting...", ChatFormatting.YELLOW, true); hostServer.start(); if (hostServer.isRunning()) { - send(context, "Modpack hosting started!", Formatting.GREEN, true); + send(context, "Modpack hosting started!", ChatFormatting.GREEN, true); } else { - send(context, "Couldn't start server!", Formatting.RED, true); + send(context, "Couldn't start server!", ChatFormatting.RED, true); } } else { - send(context, "Modpack hosting is already running!", Formatting.RED, false); + send(context, "Modpack hosting is already running!", ChatFormatting.RED, false); } }); return Command.SINGLE_SUCCESS; } - private static int stopModpackHost(CommandContext context) { - Util.getMainWorkerExecutor().execute(() -> { + private static int stopModpackHost(CommandContext context) { + Util.backgroundExecutor().execute(() -> { if (hostServer.isRunning()) { - send(context, "Stopping modpack hosting...", Formatting.RED, true); + send(context, "Stopping modpack hosting...", ChatFormatting.RED, true); if (hostServer.stop()) { - send(context, "Modpack hosting stopped!", Formatting.RED, true); + send(context, "Modpack hosting stopped!", ChatFormatting.RED, true); } else { - send(context, "Couldn't stop server!", Formatting.RED, true); + send(context, "Couldn't stop server!", ChatFormatting.RED, true); } } else { - send(context, "Modpack hosting is not running!", Formatting.RED, false); + send(context, "Modpack hosting is not running!", ChatFormatting.RED, false); } }); return Command.SINGLE_SUCCESS; } - private static int restartModpackHost(CommandContext context) { - Util.getMainWorkerExecutor().execute(() -> { - send(context, "Restarting modpack hosting...", Formatting.YELLOW, true); + private static int restartModpackHost(CommandContext context) { + Util.backgroundExecutor().execute(() -> { + send(context, "Restarting modpack hosting...", ChatFormatting.YELLOW, true); boolean needStop = hostServer.isRunning(); boolean stopped = false; if (needStop) { @@ -140,13 +171,13 @@ private static int restartModpackHost(CommandContext contex } if (needStop && !stopped) { - send(context, "Couldn't restart server!", Formatting.RED, true); + send(context, "Couldn't restart server!", ChatFormatting.RED, true); } else { hostServer.start(); if (hostServer.isRunning()) { - send(context, "Modpack hosting restarted!", Formatting.GREEN, true); + send(context, "Modpack hosting restarted!", ChatFormatting.GREEN, true); } else { - send(context, "Couldn't restart server!", Formatting.RED, true); + send(context, "Couldn't restart server!", ChatFormatting.RED, true); } } }); @@ -154,55 +185,65 @@ private static int restartModpackHost(CommandContext contex return Command.SINGLE_SUCCESS; } - - private static int modpackHostAbout(CommandContext context) { - Formatting statusColor = hostServer.isRunning() ? Formatting.GREEN : Formatting.RED; + private static int modpackHostAbout(CommandContext context) { + ChatFormatting statusColor = hostServer.isRunning() ? ChatFormatting.GREEN : ChatFormatting.RED; String status = hostServer.isRunning() ? "running" : "not running"; - send(context, "Modpack hosting status", Formatting.GREEN, status, statusColor, false); + send(context, "Modpack hosting status", ChatFormatting.GREEN, status, statusColor, false); return Command.SINGLE_SUCCESS; } - private static int about(CommandContext context) { - send(context, "AutoModpack", Formatting.GREEN, AM_VERSION, Formatting.WHITE, false); - send(context, "/automodpack generate", Formatting.YELLOW, false); - send(context, "/automodpack host start/stop/restart/connections", Formatting.YELLOW, false); - send(context, "/automodpack config reload", Formatting.YELLOW, false); + private static int about(CommandContext context) { + send(context, "AutoModpack", ChatFormatting.GREEN, AM_VERSION, ChatFormatting.WHITE, false); + send(context, "/automodpack generate", ChatFormatting.YELLOW, false); + send(context, "/automodpack host start/stop/restart/connections/fingerprint", ChatFormatting.YELLOW, false); + send(context, "/automodpack config reload", ChatFormatting.YELLOW, false); return Command.SINGLE_SUCCESS; } - private static int generateModpack(CommandContext context) { - Util.getMainWorkerExecutor().execute(() -> { + private static int generateModpack(CommandContext context) { + Util.backgroundExecutor().execute(() -> { if (modpackExecutor.isGenerating()) { - send(context, "Modpack is already generating! Please wait!", Formatting.RED, false); + send(context, "Modpack is already generating! Please wait!", ChatFormatting.RED, false); return; } - send(context, "Generating Modpack...", Formatting.YELLOW, true); + send(context, "Generating Modpack...", ChatFormatting.YELLOW, true); long start = System.currentTimeMillis(); if (modpackExecutor.generateNew()) { - send(context, "Modpack generated! took " + (System.currentTimeMillis() - start) + "ms", Formatting.GREEN, true); + send(context, "Modpack generated! took " + (System.currentTimeMillis() - start) + "ms", ChatFormatting.GREEN, true); } else { - send(context, "Modpack generation failed! Check logs for more info.", Formatting.RED, true); + send(context, "Modpack generation failed! Check logs for more info.", ChatFormatting.RED, true); } }); return Command.SINGLE_SUCCESS; } - private static void send(CommandContext context, String msg, Formatting msgColor, boolean broadcast) { + private static void send(CommandContext context, String msg, ChatFormatting msgColor, boolean broadcast) { + VersionedCommandSource.sendFeedback(context, + VersionedText.literal(msg) + .withStyle(msgColor), + broadcast); + } + + private static void send(CommandContext context, String msg, ChatFormatting msgColor, String appendMsg, ChatFormatting appendMsgColor, boolean broadcast) { VersionedCommandSource.sendFeedback(context, VersionedText.literal(msg) - .formatted(msgColor), + .withStyle(msgColor) + .append(VersionedText.literal(" - ") + .withStyle(ChatFormatting.WHITE)) + .append(VersionedText.literal(appendMsg) + .withStyle(appendMsgColor)), broadcast); } - private static void send(CommandContext context, String msg, Formatting msgColor, String appendMsg, Formatting appendMsgColor, boolean broadcast) { + private static void send(CommandContext context, String msg, ChatFormatting msgColor, MutableComponent appendMsg, ChatFormatting appendMsgColor, boolean broadcast) { VersionedCommandSource.sendFeedback(context, VersionedText.literal(msg) - .formatted(msgColor) - .append(VersionedText.literal(" - ") - .formatted(Formatting.WHITE)) - .append(VersionedText.literal(appendMsg) - .formatted(appendMsgColor)), + .withStyle(msgColor) + .append(VersionedText.literal(" - ") + .withStyle(ChatFormatting.WHITE)) + .append(appendMsg + .withStyle(appendMsgColor)), broadcast); } } diff --git a/src/main/java/pl/skidam/automodpack/modpack/GameHelpers.java b/src/main/java/pl/skidam/automodpack/modpack/GameHelpers.java index 1fc9bcd9d..4d8ac6c5d 100644 --- a/src/main/java/pl/skidam/automodpack/modpack/GameHelpers.java +++ b/src/main/java/pl/skidam/automodpack/modpack/GameHelpers.java @@ -1,10 +1,11 @@ package pl.skidam.automodpack.modpack; import com.mojang.authlib.GameProfile; -import net.minecraft.util.UserCache; - import java.net.SocketAddress; import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; + +import net.minecraft.server.players.GameProfileCache; import static pl.skidam.automodpack.init.Common.server; @@ -12,18 +13,23 @@ public class GameHelpers { // Simpler version of `PlayerManager.checkCanJoin` public static boolean isPlayerAuthorized(SocketAddress address, GameProfile profile) { - var playerManager = server.getPlayerManager(); - if (playerManager.getUserBanList().contains(profile)) { - return false; - } - if (!playerManager.isWhitelisted(profile)) { - return false; - } - if (playerManager.getIpBanList().isBanned(address)) { - return false; - } - - return true; + AtomicBoolean isAuthorized = new AtomicBoolean(false); + server.submit(() -> { + var playerManager = server.getPlayerList(); + if (playerManager.getBans().isBanned(profile)) { + return; + } + if (!playerManager.isWhiteListed(profile)) { + return; + } + if (playerManager.getIpBans().isBanned(address)) { + return; + } + + isAuthorized.set(true); + }).join(); + + return isAuthorized.get(); } // Method to get GameProfile from UUID with accounting for a fact that this player may not be on the server right now @@ -32,9 +38,9 @@ public static GameProfile getPlayerProfile(String id) { String playerName = "Player"; // mock name, name matters less than UUID anyway GameProfile profile = new GameProfile(uuid, playerName); - UserCache userCache = server.getUserCache(); + GameProfileCache userCache = server.getProfileCache(); if (userCache != null) { - profile = userCache.getByUuid(uuid).orElse(profile); + profile = userCache.get(uuid).orElse(profile); } return profile; diff --git a/src/main/java/pl/skidam/automodpack/networking/LoginNetworkingIDs.java b/src/main/java/pl/skidam/automodpack/networking/LoginNetworkingIDs.java index 7567b18f9..62490f45d 100644 --- a/src/main/java/pl/skidam/automodpack/networking/LoginNetworkingIDs.java +++ b/src/main/java/pl/skidam/automodpack/networking/LoginNetworkingIDs.java @@ -1,10 +1,11 @@ package pl.skidam.automodpack.networking; -import net.minecraft.util.Identifier; import pl.skidam.automodpack.init.Common; import static pl.skidam.automodpack_core.GlobalVariables.MOD_ID; +import net.minecraft.resources.ResourceLocation; + public enum LoginNetworkingIDs { // AutoModpack login query id's HANDSHAKE(-100), @@ -20,11 +21,11 @@ public int getValue() { return value; } - public static Identifier getIdentifier(LoginNetworkingIDs ID) { + public static ResourceLocation getResourceLocation(LoginNetworkingIDs ID) { return Common.id(ID.toString().toLowerCase()); } - public static Integer getByKey(Identifier key) { + public static Integer getByKey(ResourceLocation key) { if (key.getNamespace().equalsIgnoreCase(MOD_ID)) { for (var ID : LoginNetworkingIDs.values()) { if (ID.name().equalsIgnoreCase(key.getPath())) { @@ -35,10 +36,10 @@ public static Integer getByKey(Identifier key) { return null; } - public static Identifier getByValue(int value) { + public static ResourceLocation getByValue(int value) { for (var ID : LoginNetworkingIDs.values()) { if (ID.getValue() == value) { - return getIdentifier(ID); + return getResourceLocation(ID); } } return null; diff --git a/src/main/java/pl/skidam/automodpack/networking/LoginQueryParser.java b/src/main/java/pl/skidam/automodpack/networking/LoginQueryParser.java index 5ab854890..15d3cd146 100644 --- a/src/main/java/pl/skidam/automodpack/networking/LoginQueryParser.java +++ b/src/main/java/pl/skidam/automodpack/networking/LoginQueryParser.java @@ -1,53 +1,50 @@ package pl.skidam.automodpack.networking; -/*? if <=1.19.2 {*/ -/*import net.minecraft.network.Packet; -*//*?} else {*/ -import net.minecraft.network.packet.Packet; -/*?}*/ -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.c2s.login.LoginQueryResponseC2SPacket; -import net.minecraft.network.packet.s2c.login.LoginQueryRequestS2CPacket; -import net.minecraft.util.Identifier; /*? if >=1.20.2 {*/ import pl.skidam.automodpack.networking.client.LoginResponsePayload; import pl.skidam.automodpack.networking.server.LoginRequestPayload; -import net.minecraft.network.packet.c2s.login.LoginQueryResponsePayload; -import net.minecraft.network.packet.s2c.login.LoginQueryRequestPayload; +import net.minecraft.network.protocol.login.custom.CustomQueryAnswerPayload; +import net.minecraft.network.protocol.login.custom.CustomQueryPayload; /*?}*/ import static pl.skidam.automodpack_core.GlobalVariables.LOGGER; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; +import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; +import net.minecraft.resources.ResourceLocation; + public class LoginQueryParser { public Packet packet; public boolean success = true; public int queryId; - public PacketByteBuf buf; - public Identifier channelName; + public FriendlyByteBuf buf; + public ResourceLocation channelName; public LoginQueryParser(Packet packet) { - if (packet instanceof LoginQueryRequestS2CPacket packetS2C) { + if (packet instanceof ClientboundCustomQueryPacket packetS2C) { this.packet = packetS2C; /*? if <1.20.2 {*/ - /*this.queryId = packetS2C.getQueryId(); - this.buf = packetS2C.getPayload(); - this.channelName = packetS2C.getChannel(); + /*this.queryId = packetS2C.getTransactionId(); + this.buf = packetS2C.getData(); + this.channelName = packetS2C.getIdentifier(); *//*?} else {*/ - this.queryId = packetS2C.queryId(); - LoginQueryRequestPayload payload = packetS2C.payload(); + this.queryId = packetS2C.transactionId(); + CustomQueryPayload payload = packetS2C.payload(); if (payload instanceof LoginRequestPayload loginRequestPayload) { this.buf = loginRequestPayload.data(); this.channelName = loginRequestPayload.id(); } /*?}*/ - } else if (packet instanceof LoginQueryResponseC2SPacket packetC2S) { + } else if (packet instanceof ServerboundCustomQueryAnswerPacket packetC2S) { this.packet = packetC2S; /*? if <1.20.2 {*/ - /*this.queryId = packetC2S.getQueryId(); - this.buf = packetC2S.getResponse(); + /*this.queryId = packetC2S.getTransactionId(); + this.buf = packetC2S.getData(); *//*?} else {*/ - this.queryId = packetC2S.queryId(); - LoginQueryResponsePayload payload = packetC2S.response(); + this.queryId = packetC2S.transactionId(); + CustomQueryAnswerPayload payload = packetC2S.payload(); if (payload instanceof LoginResponsePayload loginRequestPayload) { this.buf = loginRequestPayload.data(); this.channelName = loginRequestPayload.id(); diff --git a/src/main/java/pl/skidam/automodpack/networking/ModPackets.java b/src/main/java/pl/skidam/automodpack/networking/ModPackets.java index db6532de6..f941bd531 100644 --- a/src/main/java/pl/skidam/automodpack/networking/ModPackets.java +++ b/src/main/java/pl/skidam/automodpack/networking/ModPackets.java @@ -1,10 +1,10 @@ package pl.skidam.automodpack.networking; import io.netty.buffer.Unpooled; -import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginNetworkHandler; -import net.minecraft.util.Identifier; +import net.minecraft.server.network.ServerLoginPacketListenerImpl; import pl.skidam.automodpack.networking.client.ClientLoginNetworking; import pl.skidam.automodpack.networking.content.HandshakePacket; import pl.skidam.automodpack.networking.packet.HandshakeC2SPacket; @@ -19,8 +19,8 @@ import static pl.skidam.automodpack_core.GlobalVariables.*; public class ModPackets { - public static final Identifier HANDSHAKE = LoginNetworkingIDs.getIdentifier(LoginNetworkingIDs.HANDSHAKE); - public static final Identifier DATA = LoginNetworkingIDs.getIdentifier(LoginNetworkingIDs.DATA); + public static final ResourceLocation HANDSHAKE = LoginNetworkingIDs.getResourceLocation(LoginNetworkingIDs.HANDSHAKE); + public static final ResourceLocation DATA = LoginNetworkingIDs.getResourceLocation(LoginNetworkingIDs.DATA); private static InetSocketAddress originalServerAddress; @@ -46,14 +46,14 @@ public static void registerS2CPackets() { } // Fires just after client go into login state and before any FML packet is sent. - public static void onReady(ServerLoginNetworkHandler handler, MinecraftServer server, ServerLoginNetworking.LoginSynchronizer synchronizer, PacketSender sender) { + public static void onReady(ServerLoginPacketListenerImpl handler, MinecraftServer server, ServerLoginNetworking.LoginSynchronizer synchronizer, PacketSender sender) { synchronizer.waitFor(server.submit(() -> { - PacketByteBuf buf = new PacketByteBuf(Unpooled.buffer()); + FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer()); HandshakePacket handshakePacket = new HandshakePacket(serverConfig.acceptedLoaders, AM_VERSION, MC_VERSION); String jsonHandshakePacket = handshakePacket.toJson(); - buf.writeString(jsonHandshakePacket, Short.MAX_VALUE); + buf.writeUtf(jsonHandshakePacket, Short.MAX_VALUE); sender.sendPacket(HANDSHAKE, buf); })); } diff --git a/src/main/java/pl/skidam/automodpack/networking/PacketSender.java b/src/main/java/pl/skidam/automodpack/networking/PacketSender.java index 2b105eda5..a1bc268fc 100644 --- a/src/main/java/pl/skidam/automodpack/networking/PacketSender.java +++ b/src/main/java/pl/skidam/automodpack/networking/PacketSender.java @@ -1,10 +1,9 @@ package pl.skidam.automodpack.networking; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.login.LoginQueryRequestS2CPacket; -import net.minecraft.util.Identifier; - import java.util.Objects; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; +import net.minecraft.resources.ResourceLocation; // credits to fabric api public interface PacketSender { @@ -15,14 +14,14 @@ public interface PacketSender { * @param channelName the id of the channel * @param buf the content of the packet */ - LoginQueryRequestS2CPacket createPacket(Identifier channelName, PacketByteBuf buf); + ClientboundCustomQueryPacket createPacket(ResourceLocation channelName, FriendlyByteBuf buf); /** * Sends a packet. * * @param packet the packet */ - void sendPacket(LoginQueryRequestS2CPacket packet); + void sendPacket(ClientboundCustomQueryPacket packet); /** * Sends a packet to a channel. @@ -30,7 +29,7 @@ public interface PacketSender { * @param channel the id of the channel * @param buf the content of the packet */ - default void sendPacket(Identifier channel, PacketByteBuf buf) { + default void sendPacket(ResourceLocation channel, FriendlyByteBuf buf) { Objects.requireNonNull(channel, "Channel cannot be null"); Objects.requireNonNull(buf, "Payload cannot be null"); diff --git a/src/main/java/pl/skidam/automodpack/networking/PayloadHelper.java b/src/main/java/pl/skidam/automodpack/networking/PayloadHelper.java index 9179492cf..b5da6d864 100644 --- a/src/main/java/pl/skidam/automodpack/networking/PayloadHelper.java +++ b/src/main/java/pl/skidam/automodpack/networking/PayloadHelper.java @@ -2,25 +2,25 @@ /*? if >=1.20.2 {*/ import io.netty.buffer.Unpooled; -import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.FriendlyByteBuf; // credits to fabric api public class PayloadHelper { - public static void write(PacketByteBuf byteBuf, PacketByteBuf data) { + public static void write(FriendlyByteBuf byteBuf, FriendlyByteBuf data) { byteBuf.writeBytes(data.copy()); } - public static PacketByteBuf read(PacketByteBuf byteBuf, int maxSize) { + public static FriendlyByteBuf read(FriendlyByteBuf byteBuf, int maxSize) { assertSize(byteBuf, maxSize); - PacketByteBuf newBuf = new PacketByteBuf(Unpooled.buffer()); + FriendlyByteBuf newBuf = new FriendlyByteBuf(Unpooled.buffer()); newBuf.writeBytes(byteBuf.copy()); byteBuf.skipBytes(byteBuf.readableBytes()); return newBuf; } - private static void assertSize(PacketByteBuf buf, int maxSize) { + private static void assertSize(FriendlyByteBuf buf, int maxSize) { int size = buf.readableBytes(); if (size < 0 || size > maxSize) { diff --git a/src/main/java/pl/skidam/automodpack/networking/client/ClientLoginNetworkAddon.java b/src/main/java/pl/skidam/automodpack/networking/client/ClientLoginNetworkAddon.java index 80cda0100..b84b74d9b 100644 --- a/src/main/java/pl/skidam/automodpack/networking/client/ClientLoginNetworkAddon.java +++ b/src/main/java/pl/skidam/automodpack/networking/client/ClientLoginNetworkAddon.java @@ -1,25 +1,25 @@ package pl.skidam.automodpack.networking.client; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientLoginNetworkHandler; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.c2s.login.LoginQueryResponseC2SPacket; -import net.minecraft.network.packet.s2c.login.LoginQueryRequestS2CPacket; -import net.minecraft.util.Identifier; import org.jetbrains.annotations.Nullable; import pl.skidam.automodpack.mixin.core.ClientLoginNetworkHandlerAccessor; import pl.skidam.automodpack.networking.LoginQueryParser; import java.util.concurrent.CompletableFuture; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; +import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; +import net.minecraft.resources.ResourceLocation; import static pl.skidam.automodpack_core.GlobalVariables.LOGGER; // credits to fabric api public class ClientLoginNetworkAddon { - private final ClientLoginNetworkHandler handler; - private final MinecraftClient client; + private final ClientHandshakePacketListenerImpl handler; + private final Minecraft client; - public ClientLoginNetworkAddon(ClientLoginNetworkHandler clientLoginNetworkHandler, MinecraftClient client) { + public ClientLoginNetworkAddon(ClientHandshakePacketListenerImpl clientLoginNetworkHandler, Minecraft client) { this.handler = clientLoginNetworkHandler; this.client = client; } @@ -30,25 +30,25 @@ public ClientLoginNetworkAddon(ClientLoginNetworkHandler clientLoginNetworkHandl * @param packet the packet to handle * @return true if the packet was handled */ - public boolean handlePacket(LoginQueryRequestS2CPacket packet) { + public boolean handlePacket(ClientboundCustomQueryPacket packet) { LoginQueryParser loginQuery = new LoginQueryParser(packet); if (loginQuery.success) return handlePacket(loginQuery.queryId, loginQuery.channelName, loginQuery.buf); return false; } - private boolean handlePacket(int queryId, Identifier channelName, PacketByteBuf payload) { + private boolean handlePacket(int queryId, ResourceLocation channelName, FriendlyByteBuf payload) { @Nullable ClientLoginNetworking.LoginQueryRequestHandler handler = ClientLoginNetworking.getHandler(channelName); if (handler == null) { return false; } - PacketByteBuf buf = new PacketByteBuf(payload.slice()); + FriendlyByteBuf buf = new FriendlyByteBuf(payload.slice()); try { - CompletableFuture<@Nullable PacketByteBuf> future = handler.receive(this.client, this.handler, buf); + CompletableFuture future = handler.receive(this.client, this.handler, buf); future.thenAccept(resultBuf -> { - LoginQueryResponseC2SPacket packet = new LoginQueryResponseC2SPacket(queryId, /*? if <1.20.2 {*/ /*resultBuf *//*?} else {*/ new LoginResponsePayload(channelName, resultBuf) /*?}*/); + ServerboundCustomQueryAnswerPacket packet = new ServerboundCustomQueryAnswerPacket(queryId, /*? if <1.20.2 {*/ /*resultBuf *//*?} else {*/ new LoginResponsePayload(channelName, resultBuf) /*?}*/); ((ClientLoginNetworkHandlerAccessor) this.handler).getConnection().send(packet); }); } catch (Throwable e) { diff --git a/src/main/java/pl/skidam/automodpack/networking/client/ClientLoginNetworking.java b/src/main/java/pl/skidam/automodpack/networking/client/ClientLoginNetworking.java index 40ebfe8f2..401cd6d68 100644 --- a/src/main/java/pl/skidam/automodpack/networking/client/ClientLoginNetworking.java +++ b/src/main/java/pl/skidam/automodpack/networking/client/ClientLoginNetworking.java @@ -1,20 +1,18 @@ package pl.skidam.automodpack.networking.client; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientLoginNetworkHandler; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.Nullable; - import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; // credits to fabric api public class ClientLoginNetworking { - private static final Map handlers = new HashMap<>(); + private static final Map handlers = new HashMap<>(); /** * Registers a handler to a query request channel. @@ -23,14 +21,14 @@ public class ClientLoginNetworking { * @param channelName the id of the channel * @param handler the handler */ - public static void registerGlobalReceiver(Identifier channelName, LoginQueryRequestHandler handler) { + public static void registerGlobalReceiver(ResourceLocation channelName, LoginQueryRequestHandler handler) { Objects.requireNonNull(channelName, "Channel name cannot be null"); Objects.requireNonNull(handler, "Channel handler cannot be null"); handlers.put(channelName, handler); } - public static LoginQueryRequestHandler getHandler(Identifier channelName) { + public static LoginQueryRequestHandler getHandler(ResourceLocation channelName) { return handlers.get(channelName); } @@ -40,7 +38,7 @@ public interface LoginQueryRequestHandler { * Handles an incoming query request from a server. * *

This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}. - * Modification to the game should be {@linkplain net.minecraft.util.thread.ThreadExecutor#submit(Runnable) scheduled} using the provided Minecraft client instance. + * Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft client instance. * *

The return value of this method is a completable future that may be used to delay the login process to the server until a task {@link CompletableFuture#isDone() is done}. * The future should complete in reasonably time to prevent disconnection by the server. @@ -52,6 +50,6 @@ public interface LoginQueryRequestHandler { * @return a completable future which contains the payload to respond to the server with. * If the future contains {@code null}, then the server will be notified that the client did not understand the query. */ - CompletableFuture<@Nullable PacketByteBuf> receive(MinecraftClient client, ClientLoginNetworkHandler handler, PacketByteBuf buf); + CompletableFuture receive(Minecraft client, ClientHandshakePacketListenerImpl handler, FriendlyByteBuf buf); } } diff --git a/src/main/java/pl/skidam/automodpack/networking/client/LoginResponsePayload.java b/src/main/java/pl/skidam/automodpack/networking/client/LoginResponsePayload.java index 785385564..75e76398c 100644 --- a/src/main/java/pl/skidam/automodpack/networking/client/LoginResponsePayload.java +++ b/src/main/java/pl/skidam/automodpack/networking/client/LoginResponsePayload.java @@ -1,18 +1,18 @@ package pl.skidam.automodpack.networking.client; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; /*? if <1.20.2 {*/ -/*public record LoginResponsePayload(Identifier id, PacketByteBuf data) { } +/*public record LoginResponsePayload(ResourceLocation id, FriendlyByteBuf data) { } *//*?} else {*/ -import net.minecraft.network.packet.c2s.login.LoginQueryResponsePayload; +import net.minecraft.network.protocol.login.custom.CustomQueryAnswerPayload; import pl.skidam.automodpack.networking.PayloadHelper; -public record LoginResponsePayload(Identifier id, PacketByteBuf data) implements LoginQueryResponsePayload { +public record LoginResponsePayload(ResourceLocation id, FriendlyByteBuf data) implements CustomQueryAnswerPayload { @Override - public void write(PacketByteBuf buf) { + public void write(FriendlyByteBuf buf) { PayloadHelper.write(buf, data()); } } -/*}*/ \ No newline at end of file +/*?}*/ \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/networking/content/DataPacket.java b/src/main/java/pl/skidam/automodpack/networking/content/DataPacket.java index aa2775d88..913bad6c7 100644 --- a/src/main/java/pl/skidam/automodpack/networking/content/DataPacket.java +++ b/src/main/java/pl/skidam/automodpack/networking/content/DataPacket.java @@ -5,17 +5,19 @@ public class DataPacket { public String address; - public Integer port; + public int port; public String modpackName; public Secrets.Secret secret; public boolean modRequired; + public boolean requiresMagic; - public DataPacket(String address, Integer port, String modpackName, Secrets.Secret secret, boolean modRequired) { + public DataPacket(String address, int port, String modpackName, Secrets.Secret secret, boolean modRequired, boolean requiresMagic) { this.address = address; this.port = port; this.modpackName = modpackName; this.secret = secret; this.modRequired = modRequired; + this.requiresMagic = requiresMagic; } public String toJson() { diff --git a/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java b/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java index a6387064b..25715a3c9 100644 --- a/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java +++ b/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java @@ -1,9 +1,6 @@ package pl.skidam.automodpack.networking.packet; import io.netty.buffer.Unpooled; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientLoginNetworkHandler; -import net.minecraft.network.PacketByteBuf; import pl.skidam.automodpack.mixin.core.ClientConnectionAccessor; import pl.skidam.automodpack.mixin.core.ClientLoginNetworkHandlerAccessor; import pl.skidam.automodpack.networking.ModPackets; @@ -20,23 +17,28 @@ import java.net.InetSocketAddress; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Optional; import java.util.Set; import java.util.concurrent.CompletableFuture; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; +import net.minecraft.network.FriendlyByteBuf; import static pl.skidam.automodpack_core.GlobalVariables.*; import static pl.skidam.automodpack_core.config.ConfigTools.GSON; public class DataC2SPacket { - public static CompletableFuture receive(MinecraftClient minecraftClient, ClientLoginNetworkHandler handler, PacketByteBuf buf) { + public static CompletableFuture receive(Minecraft Minecraft, ClientHandshakePacketListenerImpl handler, FriendlyByteBuf buf) { try { - String serverResponse = buf.readString(Short.MAX_VALUE); - + String serverResponse = buf.readUtf(Short.MAX_VALUE); DataPacket dataPacket = DataPacket.fromJson(serverResponse); + String packetAddress = dataPacket.address; - Integer packetPort = dataPacket.port; + int packetPort = dataPacket.port; String modpackName = dataPacket.modpackName; Secrets.Secret secret = dataPacket.secret; boolean modRequired = dataPacket.modRequired; + boolean requiresMagic = dataPacket.requiresMagic; if (modRequired) { // TODO set screen to refreshed danger screen which will ask user to install modpack with two options @@ -48,28 +50,37 @@ public static CompletableFuture receive(MinecraftClient minecraft ModPackets.setOriginalServerAddress(null); // Reset for next server reconnection if (serverAddress == null) { LOGGER.error("Server address is null! Something gone very wrong! Please report this issue! https://github.com/Skidamek/AutoModpack/issues"); - return CompletableFuture.completedFuture(new PacketByteBuf(Unpooled.buffer())); + return CompletableFuture.completedFuture(new FriendlyByteBuf(Unpooled.buffer())); } // Get actual address of the server client have connected to and format it - InetSocketAddress modpackAddress = (InetSocketAddress) ((ClientLoginNetworkHandlerAccessor) handler).getConnection().getAddress(); - modpackAddress = AddressHelpers.format(modpackAddress.getHostString(), modpackAddress.getPort()); + InetSocketAddress connectedAddress = (InetSocketAddress) ((ClientLoginNetworkHandlerAccessor) handler).getConnection().getRemoteAddress(); + String effectiveHost; + int effectivePort; + // If the packet specifies a non-blank address, use it or else use address from the server client have connected to. if (packetAddress.isBlank()) { - LOGGER.info("Address from connected server: {}:{}", modpackAddress.getHostString(), modpackAddress.getPort()); - } else if (packetPort != null) { - modpackAddress = InetSocketAddress.createUnresolved(packetAddress, packetPort); - LOGGER.info("Received address packet from server! {}:{}", packetAddress, packetPort); + effectiveHost = connectedAddress.getHostString(); } else { - modpackAddress = AddressHelpers.parse(packetAddress); - LOGGER.info("Received address packet from server! {} With attached port: {}", modpackAddress.getHostString(), modpackAddress.getPort()); + effectiveHost = packetAddress; } + if (packetPort == -1) { + effectivePort = connectedAddress.getPort(); + } else { + effectivePort = packetPort; + } + + // Construct the final modpack address + InetSocketAddress modpackAddress = AddressHelpers.format(effectiveHost, effectivePort); + + LOGGER.info("Modpack address: {}:{} Requires to follow magic protocol: {}", modpackAddress.getHostString(), modpackAddress.getPort(), requiresMagic); + Boolean needsDisconnecting = null; - PacketByteBuf response = new PacketByteBuf(Unpooled.buffer()); + FriendlyByteBuf response = new FriendlyByteBuf(Unpooled.buffer()); Path modpackDir = ModpackUtils.getModpackPath(modpackAddress, modpackName); - Jsons.ModpackAddresses modpackAddresses = new Jsons.ModpackAddresses(modpackAddress, serverAddress); + Jsons.ModpackAddresses modpackAddresses = new Jsons.ModpackAddresses(modpackAddress, serverAddress, requiresMagic); var optionalServerModpackContent = ModpackUtils.requestServerModpackContent(modpackAddresses, secret, true); if (optionalServerModpackContent.isPresent()) { @@ -105,18 +116,18 @@ public static CompletableFuture receive(MinecraftClient minecraft SecretsStore.saveClientSecret(clientConfig.selectedModpack, secret); } - response.writeString(String.valueOf(needsDisconnecting), Short.MAX_VALUE); + response.writeUtf(String.valueOf(needsDisconnecting), Short.MAX_VALUE); return CompletableFuture.completedFuture(response); } catch (Exception e) { LOGGER.error("Error while handling data packet", e); - PacketByteBuf response = new PacketByteBuf(Unpooled.buffer()); - response.writeString("null", Short.MAX_VALUE); - return CompletableFuture.completedFuture(new PacketByteBuf(Unpooled.buffer())); + FriendlyByteBuf response = new FriendlyByteBuf(Unpooled.buffer()); + response.writeUtf("null", Short.MAX_VALUE); + return CompletableFuture.completedFuture(new FriendlyByteBuf(Unpooled.buffer())); } } - private static void disconnectImmediately(ClientLoginNetworkHandler clientLoginNetworkHandler) { + private static void disconnectImmediately(ClientHandshakePacketListenerImpl clientLoginNetworkHandler) { ((ClientConnectionAccessor) ((ClientLoginNetworkHandlerAccessor) clientLoginNetworkHandler).getConnection()).getChannel().disconnect(); } } diff --git a/src/main/java/pl/skidam/automodpack/networking/packet/DataS2CPacket.java b/src/main/java/pl/skidam/automodpack/networking/packet/DataS2CPacket.java index e82bd0c44..09cb92d52 100644 --- a/src/main/java/pl/skidam/automodpack/networking/packet/DataS2CPacket.java +++ b/src/main/java/pl/skidam/automodpack/networking/packet/DataS2CPacket.java @@ -1,15 +1,14 @@ package pl.skidam.automodpack.networking.packet; import com.mojang.authlib.GameProfile; -import net.minecraft.network.ClientConnection; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.login.LoginDisconnectS2CPacket; +import net.minecraft.network.Connection; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginNetworkHandler; -import net.minecraft.text.Text; +import net.minecraft.server.network.ServerLoginPacketListenerImpl; import pl.skidam.automodpack.networking.PacketSender; import pl.skidam.automodpack.networking.server.ServerLoginNetworking; -import pl.skidam.automodpack_core.GlobalVariables; import pl.skidam.automodpack.client.ui.versioned.VersionedText; import pl.skidam.automodpack.mixin.core.ServerLoginNetworkHandlerAccessor; @@ -17,7 +16,7 @@ public class DataS2CPacket { - public static void receive(MinecraftServer server, ServerLoginNetworkHandler handler, boolean understood, PacketByteBuf buf, ServerLoginNetworking.LoginSynchronizer loginSynchronizer, PacketSender sender) { + public static void receive(MinecraftServer server, ServerLoginPacketListenerImpl handler, boolean understood, FriendlyByteBuf buf, ServerLoginNetworking.LoginSynchronizer loginSynchronizer, PacketSender sender) { try { GameProfile profile = ((ServerLoginNetworkHandlerAccessor) handler).getGameProfile(); @@ -29,44 +28,40 @@ public static void receive(MinecraftServer server, ServerLoginNetworkHandler han return; } - String clientHasUpdate = buf.readString(Short.MAX_VALUE); + String clientHasUpdate = buf.readUtf(Short.MAX_VALUE); if ("true".equals(clientHasUpdate)) { // disconnect - LOGGER.warn("{} has not installed modpack. Certificate fingerprint to verify: {}", profile.getName(), hostServer.getCertificateFingerprint()); - Text reason = VersionedText.literal("[AutoModpack] Install/Update modpack to join"); - ClientConnection connection = ((ServerLoginNetworkHandlerAccessor) handler).getConnection(); - connection.send(new LoginDisconnectS2CPacket(reason)); + LOGGER.warn("{} has not installed modpack. Certificate fingerprint: {}", profile.getName(), hostServer.getCertificateFingerprint()); + Component reason = VersionedText.literal("[AutoModpack] Install/Update modpack to join"); + Connection connection = ((ServerLoginNetworkHandlerAccessor) handler).getConnection(); + connection.send(new ClientboundLoginDisconnectPacket(reason)); connection.disconnect(reason); } else if ("false".equals(clientHasUpdate)) { LOGGER.info("{} has installed whole modpack", profile.getName()); } else { - Text reason = VersionedText.literal("[AutoModpack] Host server error. Please contact server administrator to check the server logs!"); - ClientConnection connection = ((ServerLoginNetworkHandlerAccessor) handler).getConnection(); - connection.send(new LoginDisconnectS2CPacket(reason)); + Component reason = VersionedText.literal("[AutoModpack] Host server error. Please contact server administrator to check the server logs!"); + Connection connection = ((ServerLoginNetworkHandlerAccessor) handler).getConnection(); + connection.send(new ClientboundLoginDisconnectPacket(reason)); connection.disconnect(reason); LOGGER.error("Host server error. AutoModpack host server is down or server is not configured correctly"); - if (serverConfig.hostModpackOnMinecraftPort) { - LOGGER.warn("You are hosting AutoModpack host server on the minecraft port."); - LOGGER.warn("However client can't access it, try making `hostIp` and `hostLocalIp` blank in the server config."); - LOGGER.warn("If that doesn't work, follow the steps bellow."); - LOGGER.warn(""); + if (serverConfig.bindPort == -1) { + LOGGER.warn("You are hosting AutoModpack host server on the Minecraft port."); } else { - LOGGER.warn("Please check if AutoModpack host server (TCP) port '{}' is forwarded / opened correctly", GlobalVariables.serverConfig.hostPort); - LOGGER.warn(""); + LOGGER.warn("Please check if AutoModpack host server (TCP) port '{}' is forwarded / opened correctly", serverConfig.bindPort); } - LOGGER.warn("Make sure that host IP '{}' and host local IP '{}' are correct in the config file!", GlobalVariables.serverConfig.hostIp, GlobalVariables.serverConfig.hostLocalIp); - LOGGER.warn("host IP should be an ip which are players outside of server network connecting to and host local IP should be an ip which are players inside of server network connecting to"); - LOGGER.warn("It can be Ip or a correctly set domain"); - LOGGER.warn("If you need, change port in config file, forward / open it and restart server"); + LOGGER.warn("Make sure that 'addressToSend' is correctly set in the config file!"); + LOGGER.warn("It can be either an IP address or a domain pointing to your modpack host server."); + LOGGER.warn("If nothing works, try changing the 'bindPort' in the config file, then forward / open it and restart server"); + LOGGER.warn("Note that some hosting providers may proxy this port internally and give you a different address and port to use. In this case, separate the given address with ':', and set the first part as 'addressToSend' and the second part as 'portToSend' in the config file."); - if (serverConfig.reverseProxy) { - LOGGER.error("Turn off reverseProxy in config, if you don't actually use it!"); + if (serverConfig.bindPort != serverConfig.portToSend && serverConfig.bindPort != -1 && serverConfig.portToSend != -1) { + LOGGER.error("bindPort '{}' is different than portToSend '{}'. If you are not using reverse proxy, match them! If you do use reverse proxy, make sure it is setup correctly.", serverConfig.bindPort, serverConfig.portToSend); } - LOGGER.warn("Server certificate fingerprint to verify: {}", hostServer.getCertificateFingerprint()); + LOGGER.warn("Server certificate fingerprint: {}", hostServer.getCertificateFingerprint()); } } catch (Exception e) { LOGGER.error("Error while handling DataS2CPacket", e); diff --git a/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeC2SPacket.java b/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeC2SPacket.java index d4ee10d20..fa6735d06 100644 --- a/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeC2SPacket.java +++ b/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeC2SPacket.java @@ -1,9 +1,6 @@ package pl.skidam.automodpack.networking.packet; import io.netty.buffer.Unpooled; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientLoginNetworkHandler; -import net.minecraft.network.PacketByteBuf; import pl.skidam.automodpack.mixin.core.ClientConnectionAccessor; import pl.skidam.automodpack.mixin.core.ClientLoginNetworkHandlerAccessor; import pl.skidam.automodpack.networking.content.HandshakePacket; @@ -12,27 +9,31 @@ import java.util.List; import java.util.concurrent.CompletableFuture; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl; +import net.minecraft.network.FriendlyByteBuf; import static pl.skidam.automodpack_core.GlobalVariables.*; +import static pl.skidam.automodpack_loader_core.SelfUpdater.validUpdate; public class HandshakeC2SPacket { - public static CompletableFuture receive(MinecraftClient client, ClientLoginNetworkHandler handler, PacketByteBuf buf) { + public static CompletableFuture receive(Minecraft client, ClientHandshakePacketListenerImpl handler, FriendlyByteBuf buf) { try { - String serverResponse = buf.readString(Short.MAX_VALUE); + String serverResponse = buf.readUtf(Short.MAX_VALUE); HandshakePacket serverHandshakePacket = HandshakePacket.fromJson(serverResponse); String loader = LOADER_MANAGER.getPlatformType().toString().toLowerCase(); - PacketByteBuf outBuf = new PacketByteBuf(Unpooled.buffer()); + FriendlyByteBuf outBuf = new FriendlyByteBuf(Unpooled.buffer()); HandshakePacket clientHandshakePacket = new HandshakePacket(List.of(loader), AM_VERSION, MC_VERSION); - outBuf.writeString(clientHandshakePacket.toJson(), Short.MAX_VALUE); + outBuf.writeUtf(clientHandshakePacket.toJson(), Short.MAX_VALUE); if (serverHandshakePacket.equals(clientHandshakePacket) || (serverHandshakePacket.loaders.contains(loader) && serverHandshakePacket.amVersion.equals(AM_VERSION))) { - LOGGER.info("Versions match " + serverHandshakePacket.amVersion); + LOGGER.info("Versions match {}", serverHandshakePacket.amVersion); } else { - LOGGER.warn("Versions mismatch " + serverHandshakePacket.amVersion); + LOGGER.warn("Versions mismatch. Server: {}: Client: {}", serverHandshakePacket.amVersion, AM_VERSION); LOGGER.info("Trying to change automodpack version to the version required by server..."); updateMod(handler, serverHandshakePacket.amVersion, serverHandshakePacket.mcVersion); } @@ -40,11 +41,11 @@ public static CompletableFuture receive(MinecraftClient client, C return CompletableFuture.completedFuture(outBuf); } catch (Exception e) { LOGGER.error("Error while handling HandshakeC2SPacket", e); - return CompletableFuture.completedFuture(new PacketByteBuf(Unpooled.buffer())); + return CompletableFuture.completedFuture(new FriendlyByteBuf(Unpooled.buffer())); } } - private static void updateMod(ClientLoginNetworkHandler handler, String serverAMVersion, String serverMCVersion) { + private static void updateMod(ClientHandshakePacketListenerImpl handler, String serverAMVersion, String serverMCVersion) { if (!serverMCVersion.equals(MC_VERSION)) { return; } @@ -58,8 +59,11 @@ private static void updateMod(ClientLoginNetworkHandler handler, String serverAM return; } - ((ClientConnectionAccessor) ((ClientLoginNetworkHandlerAccessor) handler).getConnection()).getChannel().disconnect(); + if (!validUpdate(automodpack)) { + return; + } + ((ClientConnectionAccessor) ((ClientLoginNetworkHandlerAccessor) handler).getConnection()).getChannel().disconnect(); SelfUpdater.installModVersion(automodpack); } } diff --git a/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeS2CPacket.java b/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeS2CPacket.java index 5f68a5467..d88c49e75 100644 --- a/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeS2CPacket.java +++ b/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeS2CPacket.java @@ -2,12 +2,12 @@ import com.mojang.authlib.GameProfile; import io.netty.buffer.Unpooled; -import net.minecraft.network.ClientConnection; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.login.LoginDisconnectS2CPacket; +import net.minecraft.network.Connection; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.login.ClientboundLoginDisconnectPacket; import net.minecraft.server.*; -import net.minecraft.server.network.ServerLoginNetworkHandler; -import net.minecraft.text.Text; +import net.minecraft.server.network.ServerLoginPacketListenerImpl; import pl.skidam.automodpack.client.ui.versioned.VersionedText; import pl.skidam.automodpack.init.Common; import pl.skidam.automodpack.mixin.core.ServerLoginNetworkHandlerAccessor; @@ -18,7 +18,6 @@ import pl.skidam.automodpack.networking.server.ServerLoginNetworking; import pl.skidam.automodpack_core.auth.Secrets; import pl.skidam.automodpack_core.auth.SecretsStore; -import pl.skidam.automodpack_core.utils.AddressHelpers; import java.nio.charset.StandardCharsets; import java.util.UUID; @@ -28,8 +27,8 @@ public class HandshakeS2CPacket { - public static void receive(MinecraftServer server, ServerLoginNetworkHandler handler, boolean understood, PacketByteBuf buf, ServerLoginNetworking.LoginSynchronizer loginSynchronizer, PacketSender sender) { - ClientConnection connection = ((ServerLoginNetworkHandlerAccessor) handler).getConnection(); + public static void receive(MinecraftServer server, ServerLoginPacketListenerImpl handler, boolean understood, FriendlyByteBuf buf, ServerLoginNetworking.LoginSynchronizer loginSynchronizer, PacketSender sender) { + Connection connection = ((ServerLoginNetworkHandlerAccessor) handler).getConnection(); GameProfile profile = ((ServerLoginNetworkHandlerAccessor) handler).getGameProfile(); String playerName = profile.getName(); @@ -48,11 +47,11 @@ public static void receive(MinecraftServer server, ServerLoginNetworkHandler han profile = new GameProfile(offlineUUID, playerName); } - if (!connection.isEncrypted()) { - LOGGER.warn("Connection is not encrypted for player: {}", playerName); - } +// if (!connection.isEncrypted()) { +// LOGGER.warn("Connection is not encrypted for player: {}", playerName); +// } - if (!GameHelpers.isPlayerAuthorized(connection.getAddress(), profile)) { + if (!GameHelpers.isPlayerAuthorized(connection.getRemoteAddress(), profile)) { return; } @@ -60,22 +59,22 @@ public static void receive(MinecraftServer server, ServerLoginNetworkHandler han Common.players.put(playerName, false); LOGGER.warn("{} has not installed AutoModpack.", playerName); if (serverConfig.requireAutoModpackOnClient) { - Text reason = VersionedText.literal("AutoModpack mod for " + LOADER_MANAGER.getPlatformType().toString().toLowerCase() + " modloader is required to play on this server!"); - connection.send(new LoginDisconnectS2CPacket(reason)); + Component reason = VersionedText.literal("AutoModpack mod for " + LOADER_MANAGER.getPlatformType().toString().toLowerCase() + " modloader is required to play on this server!"); + connection.send(new ClientboundLoginDisconnectPacket(reason)); connection.disconnect(reason); } } else { Common.players.put(playerName, true); GameProfile finalProfile = profile; - loginSynchronizer.waitFor(server.submit(() -> handleHandshake(connection, finalProfile, server.getServerPort(), buf, sender))); + loginSynchronizer.waitFor(server.submit(() -> handleHandshake(connection, finalProfile, server.getPort(), buf, sender))); } } - public static void handleHandshake(ClientConnection connection, GameProfile profile, int minecraftServerPort, PacketByteBuf buf, PacketSender packetSender) { + public static void handleHandshake(Connection connection, GameProfile profile, int minecraftServerPort, FriendlyByteBuf buf, PacketSender packetSender) { try { LOGGER.info("{} has installed AutoModpack.", profile.getName()); - String clientResponse = buf.readString(Short.MAX_VALUE); + String clientResponse = buf.readUtf(Short.MAX_VALUE); HandshakePacket clientHandshakePacket = HandshakePacket.fromJson(clientResponse); boolean isAcceptedLoader = false; @@ -87,11 +86,11 @@ public static void handleHandshake(ClientConnection connection, GameProfile prof } if (!isAcceptedLoader || !clientHandshakePacket.amVersion.equals(AM_VERSION)) { - Text reason = VersionedText.literal("AutoModpack version mismatch! Install " + AM_VERSION + " version of AutoModpack mod for " + LOADER_MANAGER.getPlatformType().toString().toLowerCase() + " to play on this server!"); + Component reason = VersionedText.literal("AutoModpack version mismatch! Install " + AM_VERSION + " version of AutoModpack mod for " + LOADER_MANAGER.getPlatformType().toString().toLowerCase() + " to play on this server!"); if (isClientVersionHigher(clientHandshakePacket.amVersion)) { reason = VersionedText.literal("You are using a more recent version of AutoModpack than the server. Please contact the server administrator to update the AutoModpack mod."); } - connection.send(new LoginDisconnectS2CPacket(reason)); + connection.send(new ClientboundLoginDisconnectPacket(reason)); connection.disconnect(reason); return; } @@ -102,60 +101,28 @@ public static void handleHandshake(ClientConnection connection, GameProfile prof } if (modpackExecutor.isGenerating()) { - Text reason = VersionedText.literal("AutoModapck is generating modpack. Please wait a moment and try again."); - connection.send(new LoginDisconnectS2CPacket(reason)); + Component reason = VersionedText.literal("AutoModpack is generating modpack. Please wait a moment and try again."); + connection.send(new ClientboundLoginDisconnectPacket(reason)); connection.disconnect(reason); return; } - String playerAddress = connection.getAddress().toString(); - String addressToSend; - - // If the player is connecting locally, use the local host IP - if (AddressHelpers.isLocal(playerAddress)) { - addressToSend = serverConfig.hostLocalIp; - } else { - addressToSend = serverConfig.hostIp; - } - // now we know player is authenticated, packets are encrypted and player is whitelisted // regenerate unique secret Secrets.Secret secret = Secrets.generateSecret(); SecretsStore.saveHostSecret(profile.getId().toString(), secret); - // We send empty string if hostIp/hostLocalIp is not specified in server config. Client will use ip by which it connected to the server in first place. - DataPacket dataPacket = new DataPacket(addressToSend, null, serverConfig.modpackName, secret, serverConfig.requireAutoModpackOnClient); - - if (serverConfig.reverseProxy) { - // With reverse proxy we dont append port to the link, it should be already included in the link - // But we need to check if the port is set in the config, since that's where modpack is actually hosted - if (serverConfig.hostPort == -1 && !serverConfig.hostModpackOnMinecraftPort) { - LOGGER.error("Reverse proxy is enabled but host port is not set in config! Please set it manually."); - } - - LOGGER.info("Sending {} modpack url: {}", profile.getName(), addressToSend); - } else { // Append server port - int portToSend; - if (serverConfig.hostModpackOnMinecraftPort) { - portToSend = minecraftServerPort; - } else { - portToSend = serverConfig.hostPort; - - if (serverConfig.hostPort == -1) { - LOGGER.error("Host port is not set in config! Please set it manually."); - } - } + String addressToSend = serverConfig.addressToSend; + int portToSend = serverConfig.portToSend; + boolean requiresMagic = serverConfig.bindPort == -1; - if (!addressToSend.isBlank()) { - LOGGER.info("Sending {} modpack url: {}:{}", profile.getName(), addressToSend, portToSend); - } - dataPacket = new DataPacket(addressToSend, portToSend, serverConfig.modpackName, secret, serverConfig.requireAutoModpackOnClient); - } + LOGGER.info("Sending {} modpack host address: {}:{}", profile.getName(), addressToSend, portToSend); + DataPacket dataPacket = new DataPacket(addressToSend, portToSend, serverConfig.modpackName, secret, serverConfig.requireAutoModpackOnClient, requiresMagic); String packetContentJson = dataPacket.toJson(); - PacketByteBuf outBuf = new PacketByteBuf(Unpooled.buffer()); - outBuf.writeString(packetContentJson, Short.MAX_VALUE); + FriendlyByteBuf outBuf = new FriendlyByteBuf(Unpooled.buffer()); + outBuf.writeUtf(packetContentJson, Short.MAX_VALUE); packetSender.sendPacket(DATA, outBuf); } catch (Exception e) { LOGGER.error("Error while handling handshake for {}", profile.getName(), e); diff --git a/src/main/java/pl/skidam/automodpack/networking/server/LoginRequestPayload.java b/src/main/java/pl/skidam/automodpack/networking/server/LoginRequestPayload.java index 83d0b9d25..7bd3f928b 100644 --- a/src/main/java/pl/skidam/automodpack/networking/server/LoginRequestPayload.java +++ b/src/main/java/pl/skidam/automodpack/networking/server/LoginRequestPayload.java @@ -1,17 +1,16 @@ package pl.skidam.automodpack.networking.server; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; - +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; /*? if <1.20.2 {*/ -/*public record LoginRequestPayload(Identifier id, PacketByteBuf data) { } +/*public record LoginRequestPayload(ResourceLocation id, FriendlyByteBuf data) { } *//*?} else {*/ -import net.minecraft.network.packet.s2c.login.LoginQueryRequestPayload; +import net.minecraft.network.protocol.login.custom.CustomQueryPayload; import pl.skidam.automodpack.networking.PayloadHelper; -public record LoginRequestPayload(Identifier id, PacketByteBuf data) implements LoginQueryRequestPayload { +public record LoginRequestPayload(ResourceLocation id, FriendlyByteBuf data) implements CustomQueryPayload { @Override - public void write(PacketByteBuf buf) { + public void write(FriendlyByteBuf buf) { PayloadHelper.write(buf, data()); } } diff --git a/src/main/java/pl/skidam/automodpack/networking/server/ServerLoginNetworkAddon.java b/src/main/java/pl/skidam/automodpack/networking/server/ServerLoginNetworkAddon.java index 58ce10d1a..9b9cfb8e1 100644 --- a/src/main/java/pl/skidam/automodpack/networking/server/ServerLoginNetworkAddon.java +++ b/src/main/java/pl/skidam/automodpack/networking/server/ServerLoginNetworkAddon.java @@ -1,13 +1,13 @@ package pl.skidam.automodpack.networking.server; import io.netty.buffer.Unpooled; -import net.minecraft.network.ClientConnection; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.c2s.login.LoginQueryResponseC2SPacket; -import net.minecraft.network.packet.s2c.login.LoginQueryRequestS2CPacket; +import net.minecraft.network.Connection; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.login.ClientboundCustomQueryPacket; +import net.minecraft.network.protocol.login.ServerboundCustomQueryAnswerPacket; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginNetworkHandler; -import net.minecraft.util.Identifier; +import net.minecraft.server.network.ServerLoginPacketListenerImpl; import org.jetbrains.annotations.Nullable; import pl.skidam.automodpack.mixin.core.ServerLoginNetworkHandlerAccessor; import pl.skidam.automodpack.networking.LoginNetworkingIDs; @@ -25,14 +25,14 @@ // credits to fabric api public class ServerLoginNetworkAddon implements PacketSender { - private final ServerLoginNetworkHandler handler; - private final ClientConnection connection; + private final ServerLoginPacketListenerImpl handler; + private final Connection connection; private final MinecraftServer server; private final Collection> synchronizers = new ConcurrentLinkedQueue<>(); - public final Map channels = new ConcurrentHashMap<>(); + public final Map channels = new ConcurrentHashMap<>(); private boolean firstTick = true; - public ServerLoginNetworkAddon(ServerLoginNetworkHandler serverLoginNetworkHandler) { + public ServerLoginNetworkAddon(ServerLoginPacketListenerImpl serverLoginNetworkHandler) { this.handler = serverLoginNetworkHandler; this.connection = ((ServerLoginNetworkHandlerAccessor) handler).getConnection(); this.server = ((ServerLoginNetworkHandlerAccessor) handler).getServer(); @@ -70,15 +70,15 @@ public boolean queryTick() { * @param packet the packet to handle * @return true if the packet was handled */ - public boolean handle(LoginQueryResponseC2SPacket packet) { + public boolean handle(ServerboundCustomQueryAnswerPacket packet) { LoginQueryParser loginQuery = new LoginQueryParser(packet); if (loginQuery.success) return handle(loginQuery.queryId, loginQuery.buf); return false; } - private boolean handle(int queryId, @Nullable PacketByteBuf originalBuf) { + private boolean handle(int queryId, @Nullable FriendlyByteBuf originalBuf) { - Identifier channel = this.channels.remove(queryId); + ResourceLocation channel = this.channels.remove(queryId); if (channel == null) { // Not an AutoModpack packet. @@ -92,7 +92,7 @@ private boolean handle(int queryId, @Nullable PacketByteBuf originalBuf) { return false; } - PacketByteBuf buf = understood ? new PacketByteBuf(originalBuf.slice()) : new PacketByteBuf(Unpooled.EMPTY_BUFFER); + FriendlyByteBuf buf = understood ? new FriendlyByteBuf(originalBuf.slice()) : new FriendlyByteBuf(Unpooled.EMPTY_BUFFER); try { handler.receive(this.server, this.handler, understood, buf, this.synchronizers::add, this); @@ -105,18 +105,18 @@ private boolean handle(int queryId, @Nullable PacketByteBuf originalBuf) { } @Override - public LoginQueryRequestS2CPacket createPacket(Identifier channelName, PacketByteBuf buf) { + public ClientboundCustomQueryPacket createPacket(ResourceLocation channelName, FriendlyByteBuf buf) { Integer queryId = LoginNetworkingIDs.getByKey(channelName); if (queryId == null) { return null; } - return new LoginQueryRequestS2CPacket(queryId, /*? if <1.20.2 {*/ /*channelName, buf *//*?} else {*/ new LoginRequestPayload(channelName, buf) /*?}*/); + return new ClientboundCustomQueryPacket(queryId, /*? if <1.20.2 {*/ /*channelName, buf *//*?} else {*/ new LoginRequestPayload(channelName, buf) /*?}*/); } @Override - public void sendPacket(LoginQueryRequestS2CPacket packet) { + public void sendPacket(ClientboundCustomQueryPacket packet) { Objects.requireNonNull(packet, "Connection cannot be null"); LoginQueryParser loginQuery = new LoginQueryParser(packet); diff --git a/src/main/java/pl/skidam/automodpack/networking/server/ServerLoginNetworking.java b/src/main/java/pl/skidam/automodpack/networking/server/ServerLoginNetworking.java index 3a92a1086..2d6f41127 100644 --- a/src/main/java/pl/skidam/automodpack/networking/server/ServerLoginNetworking.java +++ b/src/main/java/pl/skidam/automodpack/networking/server/ServerLoginNetworking.java @@ -1,9 +1,9 @@ package pl.skidam.automodpack.networking.server; -import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerLoginNetworkHandler; -import net.minecraft.util.Identifier; +import net.minecraft.server.network.ServerLoginPacketListenerImpl; import pl.skidam.automodpack.networking.PacketSender; import java.util.HashMap; @@ -14,7 +14,7 @@ // credits to fabric api public class ServerLoginNetworking { - private static final Map handlers = new HashMap<>(); + private static final Map handlers = new HashMap<>(); /** * Registers a handler to a query response channel. @@ -23,14 +23,14 @@ public class ServerLoginNetworking { * @param channelName the id of the channel * @param handler the handler */ - public static void registerGlobalReceiver(Identifier channelName, LoginQueryResponseHandler handler) { + public static void registerGlobalReceiver(ResourceLocation channelName, LoginQueryResponseHandler handler) { Objects.requireNonNull(channelName, "Channel name cannot be null"); Objects.requireNonNull(handler, "Channel handler cannot be null"); handlers.put(channelName, handler); } - public static LoginQueryResponseHandler getHandler(Identifier channelName) { + public static LoginQueryResponseHandler getHandler(ResourceLocation channelName) { return handlers.get(channelName); } @@ -40,7 +40,7 @@ public interface LoginQueryResponseHandler { * Handles an incoming query response from a client. * *

This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}. - * Modification to the game should be {@linkplain net.minecraft.util.thread.ThreadExecutor#submit(Runnable) scheduled} using the provided Minecraft client instance. + * Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft client instance. * *

Whether the client understood the query should be checked before reading from the payload of the packet. * @param server the server @@ -49,7 +49,7 @@ public interface LoginQueryResponseHandler { * @param buf the payload of the packet * @param synchronizer the synchronizer which may be used to delay log-in till a {@link Future} is completed. */ - void receive(MinecraftServer server, ServerLoginNetworkHandler handler, boolean understood, PacketByteBuf buf, LoginSynchronizer synchronizer, PacketSender responseSender); + void receive(MinecraftServer server, ServerLoginPacketListenerImpl handler, boolean understood, FriendlyByteBuf buf, LoginSynchronizer synchronizer, PacketSender responseSender); } @@ -92,7 +92,7 @@ public interface LoginSynchronizer { * })); * }); * } - * Usually it is enough to pass the return value for {@link net.minecraft.util.thread.ThreadExecutor#submit(Runnable)} for {@code future}.

+ * Usually it is enough to pass the return value for {@link net.minecraft.util.thread.BlockableEventLoop#submit(Runnable)} for {@code future}.

* * @param future the future that must be done before the player can log in */ diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg new file mode 100644 index 000000000..e67148695 --- /dev/null +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -0,0 +1 @@ +public net.minecraft.server.network.ServerLoginPacketListenerImpl$State \ No newline at end of file diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 45ab91744..c07f28b9b 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -8,15 +8,13 @@ version = "${version}" displayName = "${name}" displayURL = "https://modrinth.com/mod/automodpack" authors = "Skidam" -description = ''' - -''' -logoFile = "icon.png" +description = "${description}" +logoFile = "assets/automodpack/icon.png" [[dependencies."${id}"]] modId = "minecraft" mandatory = true -versionRange = "${minecraft_dependency}" +versionRange = "${minecraft}" ordering = "NONE" side = "BOTH" diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml index 45ab91744..c07f28b9b 100644 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -8,15 +8,13 @@ version = "${version}" displayName = "${name}" displayURL = "https://modrinth.com/mod/automodpack" authors = "Skidam" -description = ''' - -''' -logoFile = "icon.png" +description = "${description}" +logoFile = "assets/automodpack/icon.png" [[dependencies."${id}"]] modId = "minecraft" mandatory = true -versionRange = "${minecraft_dependency}" +versionRange = "${minecraft}" ordering = "NONE" side = "BOTH" diff --git a/src/main/resources/assets/automodpack/lang/fr_fr.json b/src/main/resources/assets/automodpack/lang/fr_fr.json index 5ec44f2b5a2bcf7b70853fd5b276dba058dd58c3..cff53b2c475acedcfc81563903dc5357f60df17d 100644 GIT binary patch literal 3433 zcmai1%Wm676y5tPrUn8hfWz*+DGbE{3bctE2icFwOL^Sk3_TCoR?&ayu2t6Eb;%#= zxkE~%q%m#4fGKhAoAOS&C7ymbJ%2e$Y%3XPi1TZo0&yI5e@77wVk=Lg`%B#0=;lLt(o}|nk{mrm zHP>(`!Mp;6+fewq9#ib%& zI@NM%obH;tcXV%+sT`f-Pc2PJYi{bEVlfA?r}D#ov~M0$d-}~{JLJehi%_)UEK_J_ zcp74bJ9R+QRUqG!dID>aV1Tl#2 zdvKUcY$a{ghYpK8rM%jx5F2e+1o`)CnVy3J%F? z+M3N=s}q90j;8qnGkselGpL#C*aIXxLvUiSqwTU-DSF)biL7f?-tpi{p_LB=iJ`6Z zaz7JqcPIV3oLF{W7sf8qInU8AV+qQ~K!WNTHVdS)!!$;*EtzY%O#9$-TsfAyM3YOD z78&Au3fT@T`)IV4RZ&V^MlFLf%OuA1NJWuNygNlf^4njjY1t96;7qs>Z+x!j-J$It zL#io%jGnldJ#Fkq1qT}8VlEWOz^>b4l;v}5i}04AWsdNL-tV1ZgP3v1@$liSEwEQa zi?Makxp3Xa+X%-@UJ3Ybb@xvLjmQ<1oMSLd2KTr`a?U14_$`uthy+1c>~f!mu#uX@ ziv=t$e#`-tP8anSqo14BdarJg6h64$Y)KANXS^67^jWg|fLN+QK_raY6_y^>YWj%l z)7GWIokmYgj;moNGR7;h`K{YHRjag{v1IUR0#vjb4uaaTZc(jfZ5?A)Qz-8eqqslC z7NH|(G;A~uV z8%ppUm$s5x;jV^iiU1eq2x+G#XM~R#E^N*6#q8g8|H4lAlC<5a%J4h9EWo5h_)4byj z^_i?1W#F0Mhcz^@`^mDvYbykW&a=9i^nJYi7laMH?Hld&Di9c$GD5?c8{p7=hkvt0 z)>8W(hOJr>BTsnZTaUqJ4LqED2ikYC8Gz;fBy7)coM4ibr42j6Pj=pF7=*-m9EF(mv9)?VH#@P z8R=J}>zSTg=yedj)!Kvbz3x{#t13NRg*!cer*A$NdXK~VxXZbIf2EaA2g%eLhD=hr0q=UVRmIpIy zK{b^I*ZRD#NgeHK66Qj^)a(CPHqQXZeio6`LWv|ip11WxNSzN=c%ds;)winYwP<%5 zYiAgRzNsy^hKFCW#&F+EB&(KZ*3w}me5R9YdLmqAZIjOZaeNYAJZ(`fglwt*r{Pxr z82SrcZ4@IzxsA8S;rKyxXAvFpZo@M%1FY}{%T46}%V;sKup3u%;Urp?5pffq55_l+ z9-C>$wRU!U{U`+UXqQ=(da2L8MTXjAytQ$cZ(c_XcwsK9yXM!rLc@uW!Ouqb;WHNC z|4plNNydX6*f-5Er`lnq7mQ)Yj+1?6mui~II27uK_-G!t+<;_sG}aMW=6&$;gk@UO zxrzUz@#tASpOedZ+ecr{S`f1KdaFU6wZo#RkE&6%nLiRsFQbp^UL4ioWArY&Rc(Bc zso=b`np)9kLwQW~QRX8m$2Ry_wRNJ2xYxyTyerc)R~J=prLD0EEiG~^n;E0a;)Z?C zwG+s!J2;9~+^u4>$lJA^o=2@V`sFpF_vC)kV1Lgk~D;PZdg%7$%?z?I;Ae|lSL1i&brtN!qsJ}W4X^r_)`{y*>Ck9eq5de|=rC&}s0W7D=vY9xEORG9TjR(YLlsr>;Hwf()Fv5dGa<#dY9rbC<}m(gxMk9SYG z)yOaFh{Li~4tJMPbKUtcyp~zJY7J4!PytN*>vE6_HuSwX+29AeX5dW=({d_~Puu?(oD)_w9_tA{OnK z^xkU)vMSXzc7U<3q8F$v`(^D8HT)ziGgG<-WaWoYru7lr``8QA*gZWjI+dmTKR@9~ z&l_@?tHd|INlwQUYVN!^M#%DR51YkHqbt{Qy^wvG&e5{GmwP8Zayscaj)kebUfyUm my|1r6Rc<2_rCl=0.3.5" } } diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index d0bc05bac..75c979a41 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,6 +1,7 @@ { "pack": { "description": "${name} Resources", - "pack_format": 1 + "pack_format": 15, + "supported_formats": [1, 1000] } } \ No newline at end of file diff --git a/stonecutter.gradle.kts b/stonecutter.gradle.kts index 3cbc12acc..45bea7b03 100644 --- a/stonecutter.gradle.kts +++ b/stonecutter.gradle.kts @@ -1,269 +1,34 @@ -import java.io.FileInputStream -import java.io.FileOutputStream -import java.util.concurrent.CompletableFuture -import java.util.zip.ZipEntry -import java.util.zip.ZipInputStream -import java.util.zip.ZipOutputStream - plugins { id("dev.kikugie.stonecutter") + kotlin("jvm") version "2.1.21" apply false + id("fabric-loom") version "1.11-SNAPSHOT" apply false + id("net.neoforged.moddev") version "2.0.103" apply false + id("com.gradleup.shadow") version "8.3.6" apply false + id("org.moddedmc.wiki.toolkit") version "0.2.7" } -stonecutter active "1.21.1-neoforge" /* [SC] DO NOT EDIT */ - -stonecutter registerChiseled tasks.register("chiseledBuild", stonecutter.chiseled) { - group = "project" - ofTask("build") - finalizedBy("mergeJars") -} - -stonecutter parameters { - val loader = metadata.project.substringAfterLast("-") - consts(loader, "fabric", "forge", "neoforge") -} - -// Non stonecutter stuff -val mergedDir = File("${rootProject.projectDir}/merged") - -class MinecraftVersionData(private val name: String) { - fun greaterThan(other: String) : Boolean { - return stonecutter.eval(name, ">" + other.lowercase()) - } - - fun lessThan(other: String) : Boolean { - return stonecutter.eval(name, "<" + other.lowercase()) - } - - fun greaterOrEqual(other: String) : Boolean { - return stonecutter.eval(name, ">=" + other.lowercase()) - } - - fun lessOrEqual(other: String) : Boolean { - return stonecutter.eval(name, "<=" + other.lowercase()) - } - - override fun equals(other: Any?) : Boolean { - return name == other - } - - override fun toString(): String { - return name - } - - override fun hashCode(): Int { - return name.hashCode() +wiki { + docs.create("automodpack") { + root = file("docs") } } -val coreModules = getProperty("core_modules")!!.split(',').map { it.trim() } +stonecutter active "1.21.6-neoforge" /* [SC] DO NOT EDIT */ -fun getProperty(key: String): String? { - return project.findProperty(key) as? String -} - -// TODO find better way to do it -// If you get Array Exception, run "clean" task -tasks.register("mergeJars") { - coreModules.forEach { module -> - dependsOn(":loader-$module:build") - } - - doLast { - mergedDir.mkdirs() - val jarsToMerge = File("$rootDir/versions").listFiles() - ?.flatMap { - File("$it/build/libs").listFiles() - ?.filter { file -> file.isFile && !file.name.endsWith("-sources.jar") && file.name.endsWith(".jar") } - ?: emptyList() - } - ?: emptyList() - - val tasks = mutableListOf>() - val time = System.currentTimeMillis() - val size = jarsToMerge.size - var current = 0 - - for (jarToMerge in jarsToMerge) { - val task = CompletableFuture.runAsync { - val minecraftVersionStr = jarToMerge.name.substringAfterLast("-mc").substringBefore("-") - val minecraftVersion = MinecraftVersionData(minecraftVersionStr) - - var loaderModule = "" - if (jarToMerge.name.contains("fabric")) { - loaderModule = "fabric/core" - } else if (jarToMerge.name.contains("neoforge")) { - loaderModule = if (minecraftVersion.greaterOrEqual("1.20.6")) { - "neoforge/fml4" - } else { - "neoforge/fml2" - } - } else if (jarToMerge.name.contains("forge")) { - loaderModule = if (minecraftVersion.lessOrEqual("1.18.2")) { - "forge/fml40" - } else { - "forge/fml47" - } - } - - val loaderFile = File("${rootProject.projectDir}/loader/$loaderModule/build/libs").listFiles() - ?.single { it.isFile && !it.name.endsWith("-sources.jar") && it.name.endsWith(".jar") } ?: return@runAsync - val finalJar = File("$mergedDir/${jarToMerge.name}") - - loaderFile.copyTo(finalJar, overwrite = true) - appendFileToZip(finalJar, jarToMerge, "automodpack-mod.jar") - - println("${++current}/$size - Merged: ${jarToMerge.name} into: ${finalJar.name} from: ${loaderFile.name}") - } +stonecutter.parameters { + constants.match(node.metadata.project.substringAfterLast('-'), "fabric", "neoforge", "forge") - tasks.add(task) + replacements { + string { + direction = eval(current.version, ">=1.20.2") + phase = "FIRST" + replace("ServerboundCustomQueryPacket", "ServerboundCustomQueryAnswerPacket") } - tasks.forEach { it.join() } - - if (size == 0) { - error("No jars to merge!") - } else if (size != current) { - error("Not all jars were merged!") - } else { - println("All jars were merged! Took: ${System.currentTimeMillis() - time}ms") + string { + direction = eval(current.version, ">=1.20.2") + phase = "FIRST" + replace(".SystemToastIds.", ".SystemToastId.") } } -} - -fun appendFileToZip(zipFile: File, fileToAppend: File, entryName: String) { - val entries = ZipInputStream(FileInputStream(zipFile)).use { zipStream -> - generateSequence { zipStream.nextEntry } - .toList() - } - - val graph = mutableMapOf>() - - entries.forEach { entry -> - val children = entry.name.split("/") - var currentParent = "" - children.forEach { child -> - if (child.isNotEmpty()) { - currentParent = "$currentParent$child/" - val parent = graph.getOrPut(currentParent) { mutableListOf() } - parent.add(child) - } - } - } - -// graph.forEach { (parent, children) -> -// println("$parent -> $children") -// } - - val filteredGraph = filterEntries(entries, graph, zipFile) - - // Doing with temp file since for some reason just adding the file breaks the zip/jar file - val tempFile = File("$zipFile.temp") - tempFile.createNewFile() - - ZipOutputStream(FileOutputStream(tempFile)).use { zipStream -> - ZipInputStream(FileInputStream(zipFile)).use { existingZipStream -> - while (true) { - val entry = existingZipStream.nextEntry ?: break - if (filteredGraph.containsKey("${entry.name}/")) { - try { - val zipEntry = ZipEntry(entry.name) - zipStream.putNextEntry(zipEntry) - existingZipStream.copyTo(zipStream) - zipStream.closeEntry() - } catch (e: Exception) { - println("Error while copying entry: ${entry.name}") - } - } - } - } - - // Add the new entry - zipStream.putNextEntry(ZipEntry(entryName)) - FileInputStream(fileToAppend).use { fileInputStream -> - fileInputStream.copyTo(zipStream) - } - zipStream.closeEntry() - } - - // Replace the original zip file with the one containing the new entry - zipFile.delete() - tempFile.renameTo(zipFile) -} - -val dupesDir = File("${rootProject.projectDir}/dupes") - -fun filterEntries(entries: List, graph: Map>, zipFile: File): Map> { - - val emptyDirs = mutableSetOf() - - // find empty directories - graph.forEach { (parent, children) -> - if (children.size == 0) { - emptyDirs.add(parent) - } - } - - // dump duplicate entries - dupesDir.deleteRecursively() - dupesDir.mkdirs() - - dumpDupeEntries(zipFile, entries) - - // filter empty directories - // filter single duplicate files (leave only one) - val dupes = mutableSetOf() - - val filteredGraph = graph.filter { (parent, children) -> - if (emptyDirs.contains(parent)) { - println("Filtering empty dir: $parent -> $children") - return@filter false - } - - val count = graph.count { parent == it.key } - if (count > 1 && !dupes.add(children[0])) { - return@filter false - } - - return@filter true - } - - return filteredGraph -} - -fun dumpDupeEntries(zipFile: File, entries: List) { - // check for duplicates - val entryNames = mutableSetOf() - entries.forEach { duplicate -> - if (!entryNames.add(duplicate.name)) { - println("Duplicate entry: $duplicate") - - // write the entry to the file - ZipInputStream(FileInputStream(zipFile)).use { zipStream -> - var i = 0 - generateSequence { zipStream.nextEntry } - .filter { it.name == duplicate.name } - .forEach { _ -> - i++ - val dupeFile = File("$dupesDir/$i-$duplicate.dupe") - println("Extracting to: $dupeFile") - dupeFile.parentFile.mkdirs() - dupeFile.createNewFile() - FileOutputStream(dupeFile).use { fileOutputStream -> - zipStream.copyTo(fileOutputStream) - } - } - } - } - } -} - - -tasks.register("clean") { - dependsOn("cleanMerged") -} - -tasks.register("cleanMerged") { - doLast { - mergedDir.deleteRecursively() - } -} +} \ No newline at end of file diff --git a/versions/1.18.2-fabric/gradle.properties b/versions/1.18.2-fabric/gradle.properties index ceb436883..fbe2a23dd 100644 --- a/versions/1.18.2-fabric/gradle.properties +++ b/versions/1.18.2-fabric/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.18.2 -yarn_mappings=1.18.2+build.4 -loom.platform=fabric -minecraft_dependency=1.18.x -fabric_version=0.76.0+1.18.2 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.18\n1.18.1\n1.18.2 \ No newline at end of file +deps.minecraft=1.18.2 +deps.parchment=1.18.2:2022.11.06 +deps.fabric-api=0.76.0+1.18.2 +meta.minecraft=1.18.x +publish_versions=1.18\n1.18.1\n1.18.2 \ No newline at end of file diff --git a/versions/1.18.2-forge/gradle.properties b/versions/1.18.2-forge/gradle.properties index 3d10c6025..062b54532 100644 --- a/versions/1.18.2-forge/gradle.properties +++ b/versions/1.18.2-forge/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.18.2 -yarn_mappings=1.18.2+build.4 -loom.platform=forge -minecraft_dependency=1.18.x -loader_forge=40.2.10 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.18\n1.18.1\n1.18.2 +deps.minecraft=1.18.2 +deps.parchment=1.18.2:2022.11.06 +deps.forge=1.18.2-40.2.10 +meta.minecraft=1.18.x +publish_versions=1.18\n1.18.1\n1.18.2 diff --git a/versions/1.19.2-fabric/gradle.properties b/versions/1.19.2-fabric/gradle.properties index 09e1b3394..d6edf72fa 100644 --- a/versions/1.19.2-fabric/gradle.properties +++ b/versions/1.19.2-fabric/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.19.2 -yarn_mappings=1.19.2+build.28 -loom.platform=fabric -minecraft_dependency=>=1.19 <=1.19.2 -fabric_version=0.76.1+1.19.2 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.19\n1.19.1\n1.19.2 \ No newline at end of file +deps.minecraft=1.19.2 +deps.fabric-api=0.76.1+1.19.2 +deps.parchment=1.19.2:2022.11.27 +meta.minecraft=>=1.19 <=1.19.2 +publish_versions=1.19\n1.19.1\n1.19.2 \ No newline at end of file diff --git a/versions/1.19.2-forge/gradle.properties b/versions/1.19.2-forge/gradle.properties index c0a58b92a..d4ec7ed84 100644 --- a/versions/1.19.2-forge/gradle.properties +++ b/versions/1.19.2-forge/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.19.2 -yarn_mappings=1.19.2+build.28 -loom.platform=forge -minecraft_dependency=>=1.19 <=1.19.2 -loader_forge=43.3.0 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.19\n1.19.1\n1.19.2 \ No newline at end of file +deps.minecraft=1.19.2 +deps.forge=1.19.2-43.3.0 +deps.parchment=1.19.2:2022.11.27 +meta.minecraft=>=1.19 <=1.19.2 +publish_versions=1.19\n1.19.1\n1.19.2 \ No newline at end of file diff --git a/versions/1.19.4-fabric/gradle.properties b/versions/1.19.4-fabric/gradle.properties index 2f06d41f4..8f72b9e20 100644 --- a/versions/1.19.4-fabric/gradle.properties +++ b/versions/1.19.4-fabric/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.19.4 -yarn_mappings=1.19.4+build.2 -loom.platform=fabric -minecraft_dependency=1.19.4 -fabric_version=0.87.2+1.19.4 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.19.4 \ No newline at end of file +deps.minecraft=1.19.4 +deps.fabric-api=0.87.2+1.19.4 +deps.parchment=1.19.4:2023.06.26 +meta.minecraft=1.19.4 +publish_versions=1.19.4 \ No newline at end of file diff --git a/versions/1.19.4-forge/gradle.properties b/versions/1.19.4-forge/gradle.properties index e579ae507..297fbf226 100644 --- a/versions/1.19.4-forge/gradle.properties +++ b/versions/1.19.4-forge/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.19.4 -yarn_mappings=1.19.4+build.2 -loom.platform=forge -minecraft_dependency=1.19.4 -loader_forge=45.3.0 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.19.4 \ No newline at end of file +deps.minecraft=1.19.4 +deps.forge=1.19.4-45.3.0 +deps.parchment=1.19.4:2023.06.26 +meta.minecraft=1.19.4 +publish_versions=1.19.4 \ No newline at end of file diff --git a/versions/1.20.1-fabric/gradle.properties b/versions/1.20.1-fabric/gradle.properties index 967732db3..e12481046 100644 --- a/versions/1.20.1-fabric/gradle.properties +++ b/versions/1.20.1-fabric/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.20.1 -yarn_mappings=1.20.1+build.10 -loom.platform=fabric -minecraft_dependency=>=1.20 <=1.20.1 -fabric_version=0.92.5+1.20.1 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.20\n1.20.1 \ No newline at end of file +deps.minecraft=1.20.1 +deps.fabric-api=0.92.6+1.20.1 +deps.parchment=1.20.1:2023.09.03 +meta.minecraft=>=1.20 <=1.20.1 +publish_versions=1.20\n1.20.1 \ No newline at end of file diff --git a/versions/1.20.1-forge/gradle.properties b/versions/1.20.1-forge/gradle.properties index ddeefc921..93985f5f1 100644 --- a/versions/1.20.1-forge/gradle.properties +++ b/versions/1.20.1-forge/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.20.1 -yarn_mappings=1.20.1+build.10 -loom.platform=forge -minecraft_dependency=>=1.20 <=1.20.1 -loader_forge=47.3.0 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.20\n1.20.1 +deps.minecraft=1.20.1 +deps.forge=1.20.1-47.3.0 +deps.parchment=1.20.1:2023.09.03 +meta.minecraft=>=1.20 <=1.20.1 +publish_versions=1.20\n1.20.1 diff --git a/versions/1.20.4-fabric/gradle.properties b/versions/1.20.4-fabric/gradle.properties index eab4d0458..8723a8ce9 100644 --- a/versions/1.20.4-fabric/gradle.properties +++ b/versions/1.20.4-fabric/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.20.4 -yarn_mappings=1.20.4+build.3 -loom.platform=fabric -minecraft_dependency=1.20.4 -fabric_version=0.97.1+1.20.4 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.20.4 \ No newline at end of file +deps.minecraft=1.20.4 +deps.fabric-api=0.97.3+1.20.4 +deps.parchment=1.20.4:2024.04.14 +meta.minecraft=1.20.4 +publish_versions=1.20.4 \ No newline at end of file diff --git a/versions/1.20.4-neoforge/gradle.properties b/versions/1.20.4-neoforge/gradle.properties index bc596fdbb..4899839a0 100644 --- a/versions/1.20.4-neoforge/gradle.properties +++ b/versions/1.20.4-neoforge/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.20.4 -yarn_mappings=1.20.4+build.3 -loom.platform=neoforge -minecraft_dependency=1.20.4 -loader_neoforge=20.4.237 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.20.4 \ No newline at end of file +deps.minecraft=1.20.4 +deps.neoforge=20.4.248 +deps.parchment=1.20.4:2024.04.14 +meta.minecraft=1.20.4 +publish_versions=1.20.4 \ No newline at end of file diff --git a/versions/1.20.6-fabric/gradle.properties b/versions/1.20.6-fabric/gradle.properties index afcb225bb..b13737fbf 100644 --- a/versions/1.20.6-fabric/gradle.properties +++ b/versions/1.20.6-fabric/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.20.6 -yarn_mappings=1.20.6+build.3 -loom.platform=fabric -minecraft_dependency=1.20.6 -fabric_version=0.100.0+1.20.6 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.20.6 \ No newline at end of file +deps.minecraft=1.20.6 +deps.fabric-api=0.100.8+1.20.6 +deps.parchment=1.20.6:2024.06.16 +meta.minecraft=1.20.6 +publish_versions=1.20.6 \ No newline at end of file diff --git a/versions/1.20.6-neoforge/gradle.properties b/versions/1.20.6-neoforge/gradle.properties index 5a5586036..1d286b9d0 100644 --- a/versions/1.20.6-neoforge/gradle.properties +++ b/versions/1.20.6-neoforge/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.20.6 -yarn_mappings=1.20.6+build.3 -loom.platform=neoforge -minecraft_dependency=1.20.6 -loader_neoforge=20.6.117 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.20.6 +deps.minecraft=1.20.6 +deps.neoforge=20.6.135 +deps.parchment=1.20.6:2024.06.16 +meta.minecraft=1.20.6 +publish_versions=1.20.6 diff --git a/versions/1.21.1-fabric/gradle.properties b/versions/1.21.1-fabric/gradle.properties index 5a8155fee..664fdb11f 100644 --- a/versions/1.21.1-fabric/gradle.properties +++ b/versions/1.21.1-fabric/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.21.1 -yarn_mappings=1.21.1+build.3 -loom.platform=fabric -minecraft_dependency=>=1.21 <=1.21.1 -fabric_version=0.116.0+1.21.1 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.21\n1.21.1 \ No newline at end of file +deps.minecraft=1.21.1 +deps.fabric-api=0.116.3+1.21.1 +deps.parchment=1.21.1:2024.11.17 +meta.minecraft=>=1.21 <=1.21.1 +publish_versions=1.21\n1.21.1 \ No newline at end of file diff --git a/versions/1.21.1-neoforge/gradle.properties b/versions/1.21.1-neoforge/gradle.properties index e7ffd7574..8b0a89942 100644 --- a/versions/1.21.1-neoforge/gradle.properties +++ b/versions/1.21.1-neoforge/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.21 -yarn_mappings=1.21.1+build.3 -loom.platform=neoforge -minecraft_dependency=>=1.21 <=1.21.1 -loader_neoforge=21.1.169 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.21\n1.21.1 \ No newline at end of file +deps.minecraft=1.21.1 +deps.neoforge=21.1.169 +deps.parchment=1.21.1:2024.11.17 +meta.minecraft=>=1.21 <=1.21.1 +publish_versions=1.21\n1.21.1 \ No newline at end of file diff --git a/versions/1.21.3-fabric/gradle.properties b/versions/1.21.3-fabric/gradle.properties index a4bcde35e..62015b1bb 100644 --- a/versions/1.21.3-fabric/gradle.properties +++ b/versions/1.21.3-fabric/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.21.3 -yarn_mappings=1.21.3+build.2 -loom.platform=fabric -minecraft_dependency=>=1.21.2 <=1.21.3 -fabric_version=0.114.0+1.21.3 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.21.2\n1.21.3 \ No newline at end of file +deps.minecraft=1.21.3 +deps.fabric-api=0.114.1+1.21.3 +deps.parchment=1.21.3:2024.12.07 +meta.minecraft=>=1.21.2 <=1.21.3 +publish_versions=1.21.2\n1.21.3 \ No newline at end of file diff --git a/versions/1.21.3-neoforge/gradle.properties b/versions/1.21.3-neoforge/gradle.properties index cca94e4f2..1a3adccf5 100644 --- a/versions/1.21.3-neoforge/gradle.properties +++ b/versions/1.21.3-neoforge/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.21.3 -yarn_mappings=1.21.3+build.2 -loom.platform=neoforge -minecraft_dependency=>=1.21.2 <=1.21.3 -loader_neoforge=21.3.76 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.21.2\n1.21.3 \ No newline at end of file +deps.minecraft=1.21.3 +deps.neoforge=21.3.76 +deps.parchment=1.21.3:2024.12.07 +meta.minecraft=>=1.21.2 <=1.21.3 +publish_versions=1.21.2\n1.21.3 \ No newline at end of file diff --git a/versions/1.21.4-fabric/gradle.properties b/versions/1.21.4-fabric/gradle.properties index 36b761cca..32a9524c8 100644 --- a/versions/1.21.4-fabric/gradle.properties +++ b/versions/1.21.4-fabric/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.21.4 -yarn_mappings=1.21.4+build.8 -loom.platform=fabric -minecraft_dependency=>=1.21.4 -fabric_version=0.119.2+1.21.4 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.21.4 \ No newline at end of file +deps.minecraft=1.21.4 +deps.fabric-api=0.119.3+1.21.4 +deps.parchment=1.21.4:2025.03.23 +meta.minecraft=>=1.21.4 +publish_versions=1.21.4 \ No newline at end of file diff --git a/versions/1.21.4-neoforge/gradle.properties b/versions/1.21.4-neoforge/gradle.properties index 2f7877b87..e31bf34fa 100644 --- a/versions/1.21.4-neoforge/gradle.properties +++ b/versions/1.21.4-neoforge/gradle.properties @@ -1,8 +1,5 @@ -minecraft_version=1.21.4 -yarn_mappings=1.21.4+build.8 -loom.platform=neoforge -minecraft_dependency=>=1.21.4 -loader_neoforge=21.4.135 - -# The target mc versions for the mod during mod publishing, separated with \n -game_versions=1.21.4 \ No newline at end of file +deps.minecraft=1.21.4 +deps.neoforge=21.4.135 +deps.parchment=1.21.4:2025.03.23 +meta.minecraft=>=1.21.4 +publish_versions=1.21.4 \ No newline at end of file diff --git a/versions/1.21.5-fabric/gradle.properties b/versions/1.21.5-fabric/gradle.properties new file mode 100644 index 000000000..509c61a89 --- /dev/null +++ b/versions/1.21.5-fabric/gradle.properties @@ -0,0 +1,5 @@ +deps.minecraft=1.21.5 +deps.fabric-api=0.128.0+1.21.5 +deps.parchment=1.21.5:2025.06.15 +meta.minecraft=1.21.5 +publish_versions=1.21.5 \ No newline at end of file diff --git a/versions/1.21.5-neoforge/gradle.properties b/versions/1.21.5-neoforge/gradle.properties new file mode 100644 index 000000000..7a0f88d7a --- /dev/null +++ b/versions/1.21.5-neoforge/gradle.properties @@ -0,0 +1,5 @@ +deps.minecraft=1.21.5 +deps.neoforge=21.5.75 +deps.parchment=1.21.5:2025.06.15 +meta.minecraft=1.21.5 +publish_versions=1.21.5 \ No newline at end of file diff --git a/versions/1.21.6-fabric/gradle.properties b/versions/1.21.6-fabric/gradle.properties new file mode 100644 index 000000000..0c926b8c5 --- /dev/null +++ b/versions/1.21.6-fabric/gradle.properties @@ -0,0 +1,4 @@ +deps.minecraft=1.21.6 +deps.fabric-api=0.128.0+1.21.6 +meta.minecraft=>=1.21.6 +publish_versions=1.21.6 \ No newline at end of file diff --git a/versions/1.21.6-neoforge/gradle.properties b/versions/1.21.6-neoforge/gradle.properties new file mode 100644 index 000000000..dfe3f829e --- /dev/null +++ b/versions/1.21.6-neoforge/gradle.properties @@ -0,0 +1,4 @@ +deps.minecraft=1.21.6 +deps.neoforge=21.6.11-beta +meta.minecraft=>=1.21.6 +publish_versions=1.21.6 \ No newline at end of file From b59d884eb5d0e11abdfc8bf5e5145b837bf0e2d3 Mon Sep 17 00:00:00 2001 From: Suerion Date: Thu, 21 Aug 2025 03:01:08 +0200 Subject: [PATCH 50/56] update to groups.... the selection screens need to change for all builds.... fabric and forge etc... LOTS OF TODO -> Change the DownloadSelectionScreen for all screens on different loaders --- .../pl/skidam/automodpack_core/Server.java | 21 +++++- .../skidam/automodpack_core/config/Jsons.java | 37 ++++++----- .../modpack/FullServerPack.java | 24 ++++++- .../modpack/FullServerPackContent.java | 24 +++---- .../automodpack_loader_core/Preload.java | 64 +++++++++++++------ 5 files changed, 116 insertions(+), 54 deletions(-) diff --git a/core/src/main/java/pl/skidam/automodpack_core/Server.java b/core/src/main/java/pl/skidam/automodpack_core/Server.java index 8b82ca78e..6e782a0fe 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/Server.java +++ b/core/src/main/java/pl/skidam/automodpack_core/Server.java @@ -2,9 +2,11 @@ import pl.skidam.automodpack_core.config.ConfigTools; import pl.skidam.automodpack_core.config.Jsons; +import pl.skidam.automodpack_core.modpack.FullServerPackContent; import pl.skidam.automodpack_core.modpack.ModpackExecutor; import pl.skidam.automodpack_core.modpack.FullServerPack; import pl.skidam.automodpack_core.protocol.netty.NettyServer; +import pl.skidam.automodpack_core.utils.CustomFileUtils; import java.nio.file.Path; @@ -12,6 +14,10 @@ public class Server { + //hostmodpack folder + private static final Path hostContentModpackDir = CustomFileUtils.getPathFromCWD("automodpack/host-modpack"); + + // TODO Finish this class that it will be able to host the server without mod public static void main(String[] args) { @@ -74,9 +80,10 @@ public static void main(String[] args) { //LOGGER.info("Starting server on port {}", serverConfig.bindPort); FullServerPack fullserverpack = new FullServerPack(modpackExecutor); - FullServerPackContent fullServerPackContent = new FullServerPackContent(serverConfig.modpackName, hostContentModpackDir, fullserverpack.executor.getExecutor()); - boolean fullpackgenerated = fullserverpack.generateNew(fullServerPackContent); + String modpackName = serverConfig.groups.get("host").groupName; + FullServerPackContent fullServerPackContent = new FullServerPackContent(modpackName, hostContentModpackDir, fullserverpack.executor.getExecutor()); + boolean fullpackgenerated = fullserverpack.generateNew(fullServerPackContent); if (fullpackgenerated) { LOGGER.info("FullServerPack generated!"); @@ -86,7 +93,15 @@ public static void main(String[] args) { modpackExecutor.stop(); fullserverpack.shutdownExecutor(); - LOGGER.info("Starting server on port {}", serverConfig.hostPort); + //port from Config + Jsons.GroupDeclaration hostGroup = serverConfig.groups.get("host"); + if (hostGroup == null) { + LOGGER.error("Host group not found in server config!"); + return; + } + + int port = serverConfig.bindPort; + LOGGER.info("Starting server on port {}", port); server.start(); // wait for server to stop diff --git a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java index 19a3d5a72..20bc39fe4 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java +++ b/core/src/main/java/pl/skidam/automodpack_core/config/Jsons.java @@ -123,7 +123,7 @@ public static class ServerConfigFieldsV2 { } public static class GroupDeclaration { - public String groupName = ""; + public String groupName = ""; //Also Modpack Name? public boolean generateModpackOnStart = true; public List syncedFiles = List.of(); public List allowEditsInFiles = List.of(); @@ -139,6 +139,7 @@ public static class GroupDeclaration { public static GroupDeclaration mainGroupDeclaration() { GroupDeclaration decl = new GroupDeclaration(); + decl.groupName = "main"; decl.required = true; decl.checkByDefault = true; decl.syncedFiles = List.of("/mods/*.jar", "/kubejs/**", "!/kubejs/server_scripts/**", "/emotes/*"); @@ -146,11 +147,19 @@ public static GroupDeclaration mainGroupDeclaration() { return decl; } + public static GroupDeclaration hostGroupDeclaration() { + GroupDeclaration decl = new GroupDeclaration(); + decl.groupName = "host"; //also modpackname? + return decl; + } + public static class ServerConfigFieldsV3 { public int DO_NOT_CHANGE_IT = 3; // file version public boolean modpackHost = true; + public boolean enableFullServerPack = false; public Map groups = Map.of( - "main", mainGroupDeclaration() + "main", mainGroupDeclaration(), + "host", hostGroupDeclaration() ); public boolean requireAutoModpackOnClient = true; public boolean nagUnModdedClients = true; @@ -203,19 +212,13 @@ public ModpackContentMasterFields() { } public static class ModpackGroupFields { - public String groupName = ""; - public Set list; - - public ModpackGroupFields(Set list) { - this.list = list; - } - - public ModpackGroupFields() { - this.list = Set.of(); - } - - public static class ModpackGroupFields { - public String groupName = ""; + public String groupName = ""; //also modpack name? + public String automodpackVersion = ""; + public String loader = ""; + public String loaderVersion = ""; + public String mcVersion = ""; + public String modpackName = ""; + public boolean enableFullServerPack = false; public Set list; public ModpackGroupFields(Set list) { @@ -251,6 +254,7 @@ public String toString() { } } } + public static class FullServerPackContentFields { public String modpackName = ""; public String mcVersion = ""; @@ -289,5 +293,4 @@ public String toString() { } } } -} - +} \ No newline at end of file diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java index 01fa902a2..49eb28382 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPack.java @@ -1,9 +1,13 @@ package pl.skidam.automodpack_core.modpack; +import pl.skidam.automodpack_core.config.ConfigTools; +import pl.skidam.automodpack_core.config.Jsons; +import pl.skidam.automodpack_core.utils.CustomFileUtils; import pl.skidam.automodpack_core.utils.CustomThreadFactoryBuilder; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -28,9 +32,22 @@ private FullServerPackContent init() { return null; } + // Load config if Fullpack is enabled + Path serverConfigFile = CustomFileUtils.getPathFromCWD("automodpack/automodpack-server.json"); + if (!Files.exists(serverConfigFile)) { + LOGGER.error("Server config file not found!"); + return null; + } + + Jsons.ServerConfigFieldsV3 serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV3.class); + if (serverConfig == null || !serverConfig.enableFullServerPack) { + LOGGER.info("FullServerPack is disabled."); + return null; + } + try { - if (!Files.exists(hostContentModpackDir)) { - Files.createDirectories(hostContentModpackDir); + if (!Files.exists(hostModpackDir)) { + Files.createDirectories(hostModpackDir); } } catch (IOException e) { LOGGER.error("Failed to create modpack directory", e); @@ -38,7 +55,8 @@ private FullServerPackContent init() { return null; } - return new FullServerPackContent(serverConfig.modpackName, hostContentModpackDir, executor.getExecutor()); + // Use a fixed name for the full server pack + return new FullServerPackContent("FullServerPack", hostModpackDir, executor.getExecutor()); } public boolean generateNew(FullServerPackContent content) { diff --git a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java index f9f196dd5..e7ec0521a 100644 --- a/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java +++ b/core/src/main/java/pl/skidam/automodpack_core/modpack/FullServerPackContent.java @@ -33,7 +33,6 @@ public String getModpackName() { return MODPACK_NAME; } - public boolean create() { LOGGER.info("FullServerPackContent.create() is called"); try { @@ -45,8 +44,9 @@ public boolean create() { return false; } - Jsons.ServerConfigFields serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFields.class); - if (serverConfig == null || !serverConfig.enableFullServerPack) { + // Use the latest version of server config + Jsons.ServerConfigFieldsV3 serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV3.class); + if (serverConfig == null || !serverConfig.modpackHost) { LOGGER.info("FullServerPack creation is disabled or config invalid."); return false; } @@ -54,7 +54,9 @@ public boolean create() { List filesToInclude = new ArrayList<>(); //check synced files but not excluded, because we will get all files - List syncedFilePaths = serverConfig.syncedFiles != null ? serverConfig.syncedFiles : new ArrayList<>(); + Jsons.GroupDeclaration mainGroup = serverConfig.groups.get("main"); + List syncedFilePaths = mainGroup != null ? mainGroup.syncedFiles : new ArrayList<>(); + for (String relativePath : syncedFilePaths) { Path path = CustomFileUtils.getPathFromCWD(relativePath); if (!Files.exists(path) || Files.isDirectory(path)) continue; @@ -148,9 +150,8 @@ public boolean create() { } } - private List collectFiles(Jsons.ServerConfigFields serverConfig) { + private List collectFiles(Jsons.ServerConfigFieldsV3 serverConfig) { List filesToInclude = new ArrayList<>(); - return filesToInclude; } @@ -233,16 +234,14 @@ public static void generateFromServerConfig() { LOGGER.info("start generating server pack content file"); Path automodpackserverConfig = CustomFileUtils.getPathFromCWD("automodpack/automodpack-server.json"); - //if file is deleted from user, stop if (!Files.exists(automodpackserverConfig)) { LOGGER.info("automodpack-server.json is missing? did you delete the file?"); return; } - //load config - Jsons.ServerConfigFields serverConfig = ConfigTools.load(automodpackserverConfig, Jsons.ServerConfigFields.class); - //if config null or false, stop - if (serverConfig == null || !serverConfig.enableFullServerPack) { + // Use the latest version of server config (V3) + Jsons.ServerConfigFieldsV3 serverConfig = ConfigTools.load(automodpackserverConfig, Jsons.ServerConfigFieldsV3.class); + if (serverConfig == null || !serverConfig.modpackHost) { LOGGER.info("Fullserverpack creation on default disabled."); return; } @@ -250,7 +249,8 @@ public static void generateFromServerConfig() { List filesToInclude = new ArrayList<>(); //check synced files - List syncedFilePaths = serverConfig.syncedFiles != null ? serverConfig.syncedFiles : new ArrayList<>(); + Jsons.GroupDeclaration mainGroup = serverConfig.groups.get("main"); + List syncedFilePaths = mainGroup != null ? mainGroup.syncedFiles : new ArrayList<>(); for (String relativePath : syncedFilePaths) { Path path = CustomFileUtils.getPathFromCWD(relativePath); diff --git a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java index 8d22ce510..5e2dc85e7 100644 --- a/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java +++ b/loader/core/src/main/java/pl/skidam/automodpack_loader_core/Preload.java @@ -17,6 +17,7 @@ import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermissions; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.zip.ZipEntry; @@ -41,7 +42,6 @@ public Preload() { } private void updateAll() { - var optionalSelectedModpackDir = ModpackContentTools.getModpackDir(clientConfig.selectedModpack); if (LOADER_MANAGER.getEnvironmentType() == LoaderManagerService.EnvironmentType.SERVER || optionalSelectedModpackDir.isEmpty()) { @@ -69,27 +69,62 @@ private void updateAll() { Jsons.ModpackAddresses modpackAddresses = new Jsons.ModpackAddresses(selectedModpackAddress, selectedServerAddress, requiresMagic); var optionalLatestModpackContent = ModpackUtils.requestServerModpackContent(modpackAddresses, secret, false); - var latestModpackContent = ConfigTools.loadModpackContent(selectedModpackDir.resolve(hostModpackContentFile.getFileName())); + + // Laden Sie den vorhandenen Modpack-Inhalt + Jsons.ModpackContentMasterFields latestModpackContent = ConfigTools.load(selectedModpackDir.resolve(hostModpackContentFile.getFileName()), Jsons.ModpackContentMasterFields.class); // Use the latest modpack content if available if (optionalLatestModpackContent.isPresent()) { - latestModpackContent = optionalLatestModpackContent.get(); + Jsons.ModpackGroupFields serverGroupContent = optionalLatestModpackContent.get(); + + // Erstellen Sie ein MasterContent-Objekt aus der Gruppenantwort + Jsons.ModpackContentMasterFields serverMasterContent = new Jsons.ModpackContentMasterFields(); + serverMasterContent.groups = Set.of(serverGroupContent); + serverMasterContent.automodpackVersion = serverGroupContent.automodpackVersion; + serverMasterContent.loader = serverGroupContent.loader; + serverMasterContent.loaderVersion = serverGroupContent.loaderVersion; + serverMasterContent.mcVersion = serverGroupContent.mcVersion; + serverMasterContent.enableFullServerPack = serverGroupContent.enableFullServerPack; // Update AutoModpack to server version only if we can get newest modpack content - if (SelfUpdater.update(latestModpackContent)) { + if (SelfUpdater.update(serverMasterContent)) { return; } + + // Aktualisieren Sie den lokalen Inhalt mit dem Server-Inhalt + latestModpackContent = serverMasterContent; + } + + // Extract all content items from all groups for deleteDummyFiles + Set allContentItems = null; + if (latestModpackContent != null && latestModpackContent.groups != null) { + allContentItems = new HashSet<>(); + for (Jsons.ModpackGroupFields group : latestModpackContent.groups) { + if (group.list != null) { + allContentItems.addAll(group.list); + } + } } // Delete dummy files - CustomFileUtils.deleteDummyFiles(Path.of(System.getProperty("user.dir")), latestModpackContent == null ? null : latestModpackContent.list); + CustomFileUtils.deleteDummyFiles(Path.of(System.getProperty("user.dir")), allContentItems); + + // Find the main group for ModpackUpdater + Jsons.ModpackGroupFields mainGroup = null; + if (latestModpackContent != null && latestModpackContent.groups != null) { + for (Jsons.ModpackGroupFields group : latestModpackContent.groups) { + if ("main".equals(group.groupName)) { + mainGroup = group; + break; + } + } + } // Update modpack - new ModpackUpdater().prepareUpdate(latestModpackContent, modpackAddresses, secret); + new ModpackUpdater().prepareUpdate(mainGroup, modpackAddresses, secret); } } - private void initializeGlobalVariables() { // Initialize global variables preload = true; @@ -129,12 +164,10 @@ private void loadConfigs() { clientConfigV1.DO_NOT_CHANGE_IT = 2; clientConfigV1.installedModpacks = null; } - ConfigTools.save(clientConfigFile, clientConfigV1); LOGGER.info("Updated client config version to {}", clientConfigVersion.DO_NOT_CHANGE_IT); } } - clientConfig = ConfigTools.load(clientConfigFile, Jsons.ClientConfigFieldsV2.class); } else { // TODO: when connecting to the new server which provides modpack different modpack, ask the user if they want, stop using overrides @@ -168,20 +201,17 @@ private void loadConfigs() { serverConfigV2.portToSend = serverConfigV1.hostPort; } } - ConfigTools.save(serverConfigFile, serverConfigV2); LOGGER.info("Updated server config version to {}", serverConfigVersion.DO_NOT_CHANGE_IT); } if (serverConfigVersion.DO_NOT_CHANGE_IT == 2) { - // Update the configs schemes to not crash the game if loaded with old config! var serverConfigV2 = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV2.class); var serverConfigV3 = ConfigTools.softLoad(serverConfigFile, Jsons.ServerConfigFieldsV3.class); if (serverConfigV2 != null && serverConfigV3 != null) { serverConfigVersion.DO_NOT_CHANGE_IT = 3; serverConfigV3.DO_NOT_CHANGE_IT = 3; - // copy all modpack fields from v2 to main modpack v3 serverConfigV3.groups.get("main").groupName = serverConfigV2.modpackName; serverConfigV3.groups.get("main").generateModpackOnStart = serverConfigV2.generateModpackOnStart; serverConfigV3.groups.get("main").autoExcludeUnnecessaryFiles = serverConfigV2.autoExcludeUnnecessaryFiles; @@ -195,7 +225,6 @@ private void loadConfigs() { } } } - // load server config serverConfig = ConfigTools.load(serverConfigFile, Jsons.ServerConfigFieldsV3.class); @@ -207,15 +236,14 @@ private void loadConfigs() { serverConfig.acceptedLoaders.add(LOADER); } - // Check modpack name and fix it if needed, because it will be used for naming a folder on client for (String groupId : serverConfig.groups.keySet()) { + // Check modpack name and fix it if needed, because it will be used for naming a folder on client if (!groupId.isEmpty() && FileInspection.isInValidFileName(groupId)) { serverConfig.groups.put(FileInspection.fixFileName(groupId), serverConfig.groups.get(groupId)); serverConfig.groups.remove(groupId); LOGGER.info("Changed modpack name to {}", groupId); } } - // Save changes ConfigTools.save(serverConfigFile, serverConfig); } @@ -229,7 +257,6 @@ private void loadConfigs() { if (clientConfig.selectedModpack == null) { clientConfig.selectedModpack = ""; } - // Save changes ConfigTools.save(clientConfigFile, clientConfig); } @@ -248,7 +275,7 @@ private void loadConfigs() { if (os.contains("win")) { Files.setAttribute(privateDir, "dos:hidden", true); } else if (os.contains("nix") || os.contains("nux") || os.contains("aix") || os.contains("mac")) { - Set perms = PosixFilePermissions.fromString("rwx------"); // Corresponds to 0700 + Set perms = PosixFilePermissions.fromString("rwx------"); Files.setPosixFilePermissions(privateDir, perms); } } catch (UnsupportedOperationException | IOException e) { @@ -258,11 +285,10 @@ private void loadConfigs() { LOGGER.error("Failed to create private directory", e); } - if (serverConfig == null || clientConfig == null) { throw new RuntimeException("Failed to load config!"); } LOGGER.info("Loaded config! took {}ms", System.currentTimeMillis() - startTime); } -} +} \ No newline at end of file From 577d7dca23d84cbe76ef88a3b08761ce1e8f4617 Mon Sep 17 00:00:00 2001 From: Suerion Date: Thu, 21 Aug 2025 03:26:58 +0200 Subject: [PATCH 51/56] added an versioned util, but builds on 1.19 and 1.18 are agein problematic, need to look more int this --- .../client/ui/DownloadSelectionScreen.java | 48 +++++++------------ .../client/ui/versioned/VersionedText.java | 18 +++++++ .../client/ui/versioned/VersionedUtil.java | 14 ++++++ 3 files changed, 49 insertions(+), 31 deletions(-) create mode 100644 src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index bf3e86066..ae97b7eed 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -2,24 +2,22 @@ import java.util.List; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.util.Formatting; -import net.minecraft.util.Util; import pl.skidam.automodpack_loader_core.client.ModpackUpdater; import pl.skidam.automodpack.client.audio.AudioManager; import pl.skidam.automodpack.client.ui.versioned.VersionedMatrices; import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; import pl.skidam.automodpack.client.ui.versioned.VersionedText; +import pl.skidam.automodpack.client.ui.versioned.VersionedUtil; import pl.skidam.automodpack_loader_core.utils.SelectionManager; import static pl.skidam.automodpack_core.GlobalVariables.serverConfig; public class DownloadSelectionScreen extends VersionedScreen { - private final Screen parent; + private final VersionedScreen parent; private final ModpackUpdater modpackUpdaterInstance; - public DownloadSelectionScreen(Screen parent, ModpackUpdater modpackUpdaterInstance) { + public DownloadSelectionScreen(VersionedScreen parent, ModpackUpdater modpackUpdaterInstance) { super(VersionedText.literal("DownloadSelectionScreen")); this.parent = parent; this.modpackUpdaterInstance = modpackUpdaterInstance; @@ -28,13 +26,14 @@ public DownloadSelectionScreen(Screen parent, ModpackUpdater modpackUpdaterInsta AudioManager.stopMusic(); } } + @Override protected void init() { super.init(); assert this.client != null; this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 150, 120, 20, VersionedText.translatable("automodpack.ds.cancel"), button -> { - this.client.setScreen(parent); + this.client.setScreen(parent.getMinecraftScreen()); })); //buttons from Selectionmanager @@ -49,48 +48,35 @@ protected void init() { // between buttons int y = dynamicY + (i * 25); - var displayText = VersionedText.literal(modpack).formatted(modpack.equalsIgnoreCase(currentSelected) ? Formatting.GREEN : Formatting.BOLD); + var displayText = VersionedText.literal(modpack); + if (modpack.equalsIgnoreCase(currentSelected)) { + displayText = VersionedText.green(modpack); + } else { + displayText = VersionedText.bold(modpack); + } - this.addDrawableChild(buttonWidget(this.width / 2, y, 140, 20, VersionedText.literal(modpack).formatted(Formatting.BOLD), button -> { + this.addDrawableChild(buttonWidget(this.width / 2, y, 140, 20, displayText, button -> { //select and start SelectionManager.setSelectedPack(modpack); - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + VersionedUtil.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); i++; } //Full Serverpack Button if Modpack has permission from server if (serverConfig != null && serverConfig.enableFullServerPack) { - this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, VersionedText.translatable("automodpack.ds.fullserverpack").formatted(Formatting.RED), button -> { + this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, VersionedText.red(VersionedText.translatable("automodpack.ds.fullserverpack").getString()), button -> { SelectionManager.setSelectedPack("fullserver"); - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + VersionedUtil.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); } - - /* Old Buttons - this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 50, 120, 20, VersionedText.translatable("automodpack.ds.standard").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); - })); - - this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 75, 120, 20, VersionedText.translatable("automodpack.ds.highendconfirm").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startHighUpdate); - })); - - this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 100, 120, 20, VersionedText.translatable("automodpack.ds.lowendconfirm").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startLowUpdate); - })); - - this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 125, 120, 20, VersionedText.translatable("automodpack.ds.completeconfirm").formatted(Formatting.BOLD), button -> { - Util.getMainWorkerExecutor().execute(modpackUpdaterInstance::startServerUpdate); - })); - */ } @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { //ADDE - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.selected", VersionedText.literal(SelectionManager.getSelectedPack()).formatted(Formatting.GREEN, Formatting.BOLD)),this.width / 2, this.height / 2 - 15, 0xAAAAAA); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds").formatted(Formatting.BOLD), this.width / 2, this.height / 2 - 60, 16777215); + drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.selected", VersionedText.green(VersionedText.bold(SelectionManager.getSelectedPack()).getString())),this.width / 2, this.height / 2 - 15, 0xAAAAAA); + drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.bold(VersionedText.translatable("automodpack.ds").getString()), this.width / 2, this.height / 2 - 60, 16777215); drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.description"), this.width / 2, this.height / 2 - 35, 16777215); drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.secDescription"), this.width / 2, this.height / 2 - 25, 16777215); } diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java index 102a51b09..b79a2fd96 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java @@ -28,4 +28,22 @@ public static MutableComponent literal(String string) { return Component.literal(string); } /*?}*/ + + public static MutableComponent green(String text) { + /*? if >=1.19 {*/ + /*return literal(text).withStyle(net.minecraft.ChatFormatting.GREEN);*//*?} else {*/ + /*return literal(text).formatted(net.minecraft.util.Formatting.GREEN);*//*?}*/ + } + + public static MutableComponent bold(String text) { + /*? if >=1.19 {*/ + /*return literal(text).withStyle(net.minecraft.ChatFormatting.BOLD);*//*?} else {*/ + /*return literal(text).formatted(net.minecraft.util.Formatting.BOLD);*//*?}*/ + } + + public static MutableComponent red(String text) { + /*? if >=1.19 {*/ + /*return literal(text).withStyle(net.minecraft.ChatFormatting.RED);*//*?} else {*/ + /*return literal(text).formatted(net.minecraft.util.Formatting.RED);*//*?}*/ + } } \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java new file mode 100644 index 000000000..7f170ea90 --- /dev/null +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java @@ -0,0 +1,14 @@ +package pl.skidam.automodpack.client.ui.versioned; + +import java.util.concurrent.Executor; + +//try to create an util for more versions? +public class VersionedUtil { + public static Executor getMainWorkerExecutor() { + /*? if >=1.18 {*/ + return net.minecraft.Util.getMainWorkerExecutor(); + /*?} else {*/ + /*return net.minecraft.util.Util.getMainWorkerExecutor();*/ + /*?}*/ + } +} \ No newline at end of file From 2505ae54812ae3c45673e5e84d684accb6c44bc4 Mon Sep 17 00:00:00 2001 From: Suerion Date: Thu, 21 Aug 2025 05:00:29 +0200 Subject: [PATCH 52/56] fix problems with stonecutter, had not a lot issues anymore --- .../skidam/automodpack/client/ScreenImpl.java | 9 + .../client/ui/DownloadSelectionScreen.java | 43 +++-- .../client/ui/versioned/VersionedScreen.java | 182 ++++++++++-------- .../client/ui/versioned/VersionedText.java | 40 ++-- .../client/ui/versioned/VersionedUtil.java | 9 +- .../networking/packet/DataC2SPacket.java | 9 +- .../networking/packet/HandshakeS2CPacket.java | 7 +- 7 files changed, 176 insertions(+), 123 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java b/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java index 08b2e45cb..add999034 100644 --- a/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java +++ b/src/main/java/pl/skidam/automodpack/client/ScreenImpl.java @@ -1,6 +1,7 @@ package pl.skidam.automodpack.client; import pl.skidam.automodpack.client.ui.*; +import pl.skidam.automodpack.client.ui.versioned.VersionedScreen; import pl.skidam.automodpack_loader_core.client.Changelogs; import pl.skidam.automodpack_loader_core.client.ModpackUpdater; import pl.skidam.automodpack_loader_core.screen.ScreenService; @@ -62,6 +63,11 @@ public void validation(Object... args) { Screens.validation(args[0], args[1], args[2], args[3]); } + @Override + public void downloadselection(Object... args) { + Screens.downloadselection(args[0], args[1]); + } + @Override public Optional getScreenString() { Screen screen = Screens.getScreen(); @@ -114,6 +120,9 @@ public static void title() { public static void menu() { // Screens.setScreen(new MenuScreen()); } + public static void downloadselection(Object parent, Object modpackUpdaterInstance) { + Screens.setScreen(new DownloadSelectionScreen((VersionedScreen) parent, (ModpackUpdater) modpackUpdaterInstance)); + } public static void validation(Object parent, Object serverFingerprint, Object validatedCallback, Object canceledCallback) { diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index ae97b7eed..ce9d96a68 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -30,11 +30,17 @@ public DownloadSelectionScreen(VersionedScreen parent, ModpackUpdater modpackUpd @Override protected void init() { super.init(); - assert this.client != null; + assert this.getClient() != null; + /*? if >=1.19.3 {*/ this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 150, 120, 20, VersionedText.translatable("automodpack.ds.cancel"), button -> { - this.client.setScreen(parent.getMinecraftScreen()); + this.getClient().setScreen(this.parent); })); + /*?} else {*/ + this.addButton(buttonWidget(this.width / 2, this.height / 2 + 150, 120, 20, VersionedText.translatable("automodpack.ds.cancel"), button -> { + this.getClient().setScreen(this.parent); + })); + /*?}*/ //buttons from Selectionmanager String currentSelected = SelectionManager.getSelectedPack(); @@ -48,37 +54,48 @@ protected void init() { // between buttons int y = dynamicY + (i * 25); - var displayText = VersionedText.literal(modpack); - if (modpack.equalsIgnoreCase(currentSelected)) { - displayText = VersionedText.green(modpack); - } else { - displayText = VersionedText.bold(modpack); - } + var displayText = modpack.equalsIgnoreCase(currentSelected) + ? VersionedText.green(modpack) + : VersionedText.bold(modpack); + /*? if >=1.19.3 {*/ this.addDrawableChild(buttonWidget(this.width / 2, y, 140, 20, displayText, button -> { //select and start SelectionManager.setSelectedPack(modpack); VersionedUtil.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); + /*?} else {*/ + this.addButton(buttonWidget(this.width / 2, y, 140, 20, displayText, button -> { + //select and start + SelectionManager.setSelectedPack(modpack); + VersionedUtil.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + })); + /*?}*/ i++; } //Full Serverpack Button if Modpack has permission from server if (serverConfig != null && serverConfig.enableFullServerPack) { + /*? if >=1.19.3 {*/ this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, VersionedText.red(VersionedText.translatable("automodpack.ds.fullserverpack").getString()), button -> { SelectionManager.setSelectedPack("fullserver"); VersionedUtil.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); + /*?} else {*/ + this.addButton(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, VersionedText.red(VersionedText.translatable("automodpack.ds.fullserverpack").getString()), button -> { + SelectionManager.setSelectedPack("fullserver"); + VersionedUtil.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); + })); + /*?}*/ } } @Override public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { - //ADDE - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.selected", VersionedText.green(VersionedText.bold(SelectionManager.getSelectedPack()).getString())),this.width / 2, this.height / 2 - 15, 0xAAAAAA); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.bold(VersionedText.translatable("automodpack.ds").getString()), this.width / 2, this.height / 2 - 60, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.description"), this.width / 2, this.height / 2 - 35, 16777215); - drawCenteredTextWithShadow(matrices, this.textRenderer, VersionedText.translatable("automodpack.ds.secDescription"), this.width / 2, this.height / 2 - 25, 16777215); + drawCenteredTextWithShadow(matrices, this.getTextRenderer(), VersionedText.translatable("automodpack.ds.selected", VersionedText.green(VersionedText.bold(SelectionManager.getSelectedPack()).getString())), this.width / 2, this.height / 2 - 15, 0xAAAAAA); + drawCenteredTextWithShadow(matrices, this.getTextRenderer(), VersionedText.bold(VersionedText.translatable("automodpack.ds").getString()), this.width / 2, this.height / 2 - 60, 16777215); + drawCenteredTextWithShadow(matrices, this.getTextRenderer(), VersionedText.translatable("automodpack.ds.description"), this.width / 2, this.height / 2 - 35, 16777215); + drawCenteredTextWithShadow(matrices, this.getTextRenderer(), VersionedText.translatable("automodpack.ds.secDescription"), this.width / 2, this.height / 2 - 25, 16777215); } @Override diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java index c7d81330d..4ad63a572 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java @@ -24,91 +24,107 @@ public class VersionedScreen extends Screen { - protected VersionedScreen(Component title) { - super(title); - } + protected VersionedScreen(Component title) { + super(title); + } - /*? if <1.20 {*/ - /*@Override + /*? if <1.20 {*/ + /*@Override public void render(PoseStack matrix, int mouseX, int mouseY, float delta) { VersionedMatrices matrices = new VersionedMatrices(); - *//*?} else {*/ - @Override - public void render(GuiGraphics matrix, int mouseX, int mouseY, float delta) { - VersionedMatrices matrices = new VersionedMatrices(matrix); - /*?}*/ - - // Render background - /*? if <1.20.2 {*/ + *//*?} else {*/ + @Override + public void render(GuiGraphics matrix, int mouseX, int mouseY, float delta) { + VersionedMatrices matrices = new VersionedMatrices(matrix); + /*?}*/ + + // Render background + /*? if <1.20.2 {*/ /*super.renderBackground(matrices.getContext()); - *//*?} elif <1.20.6 {*/ + *//*?} elif <1.20.6 {*/ /*super.renderBackground(matrices.getContext(), mouseX, mouseY, delta); - *//*?} else {*/ - super.render(matrix, mouseX, mouseY, delta); - /*?}*/ - - // Render the rest of our screen - versionedRender(matrices, mouseX, mouseY, delta); - - /*? if <1.20.6 {*/ - /*super.render(matrices.getContext(), mouseX, mouseY, delta); - *//*?}*/ - } - - // This method is to be override by the child classes - public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { } - - - /*? if <=1.16.5 {*//* - public void addDrawableChild(T child) { - if (child instanceof ClickableWidget) { - super.addButton((ClickableWidget) child); - return; - } - super.addChild(child); - } - *//*?}*/ - - /*? if >=1.20 {*/ - public static void drawCenteredTextWithShadow(VersionedMatrices matrices, Font textRenderer, MutableComponent text, int centerX, int y, int color) { - matrices.getContext().drawCenteredString(textRenderer, text, centerX, y, color); - } - /*?} else {*/ - /*public static void drawCenteredTextWithShadow(VersionedMatrices matrices, Font textRenderer, MutableComponent text, int centerX, int y, int color) { - textRenderer.drawShadow(matrices.getContext(), text, (float)(centerX - textRenderer.width(text) / 2), (float)y, color); - } - *//*?}*/ - - - /*? if <1.19.3 {*/ - /*public static Button buttonWidget(int x, int y, int width, int height, Component message, Button.OnPress onPress) { - return new Button(x, y, width, height, message, onPress); - } - *//*?} else {*/ - public static Button buttonWidget(int x, int y, int width, int height, Component message, Button.OnPress onPress) { - return Button.builder(message, onPress).pos(x, y).size(width, height).build(); - } - /*?}*/ - - /*? if <=1.20 {*/ - /*public static void drawTexture(ResourceLocation textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { - /^? if <=1.16.5 {^/ - /^Minecraft.getInstance().getTextureManager().bindTexture(textureID); - ^//^?} else {^/ - RenderSystem.setShaderTexture(0, textureID); - /^?}^/ - GuiComponent.blit(matrices.getContext(), x, y, u, v, width, height, textureWidth, textureHeight); - } - *//*?} else {*/ - public static void drawTexture(ResourceLocation textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { - /*? if >=1.21.6 {*/ - matrices.getContext().blit(RenderPipelines.GUI_TEXTURED, textureID, x, y, u, v, width, height, textureWidth, textureHeight); - /*?} elif >=1.21.2 {*/ - /*Function RenderTypes = RenderType::guiTextured; - matrices.getContext().blit(RenderTypes, textureID, x, y, u, v, width, height, textureWidth, textureHeight); - *//*?} else {*/ - /*matrices.getContext().blit(textureID, x, y, u, v, width, height, textureWidth, textureHeight); - *//*?}*/ - } - /*?}*/ -} + *//*?} else {*/ + super.render(matrix, mouseX, mouseY, delta); + /*?}*/ + + // Render the rest of our screen + versionedRender(matrices, mouseX, mouseY, delta); + + /*? if <1.20.6 {*/ + /*super.render(matrices.getContext(), mouseX, mouseY, delta); + *//*?}*/ + } + + public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { } + + /*? if <=1.16.5 {*//* + public void addDrawableChild(T child) { + if (child instanceof ClickableWidget) { + super.addButton((ClickableWidget) child); + return; + } + super.addChild(child); + } + + /*? if >=1.20 {*/ + public static void drawCenteredTextWithShadow(VersionedMatrices matrices, Font textRenderer, MutableComponent text, int centerX, int y, int color) { + matrices.getContext().drawCenteredString(textRenderer, text, centerX, y, color); + } + /*?} else {*/ + /*public static void drawCenteredTextWithShadow(VersionedMatrices matrices, Font textRenderer, MutableComponent text, int centerX, int y, int color) { + textRenderer.drawShadow(matrices.getContext(), text, (float)(centerX - textRenderer.width(text) / 2), (float)y, color); + } + *//*?}*/ + + /*? if <1.19.3 {*/ + /*public static Button buttonWidget(int x, int y, int width, int height, Component message, Button.OnPress onPress) { + return new Button(x, y, width, height, message, onPress); + } + *//*?} else {*/ + public static Button buttonWidget(int x, int y, int width, int height, Component message, Button.OnPress onPress) { + return Button.builder(message, onPress).pos(x, y).size(width, height).build(); + } + /*?}*/ + + /*? if <=1.20 {*/ + /*public static void drawTexture(ResourceLocation textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { + /^? if <=1.16.5 {^/ + /^Minecraft.getInstance().getTextureManager().bindTexture(textureID); + ^//^?} else {^/ + RenderSystem.setShaderTexture(0, textureID); + /^?}^/ + GuiComponent.blit(matrices.getContext(), x, y, u, v, width, height, textureWidth, textureHeight); + } + *//*?} else {*/ + public static void drawTexture(ResourceLocation textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { + /*? if >=1.21.6 {*/ + matrices.getContext().blit(RenderPipelines.GUI_TEXTURED, textureID, x, y, u, v, width, height, textureWidth, textureHeight); + /*?} elif >=1.21.2 {*/ + /*Function RenderTypes = RenderType::guiTextured; + matrices.getContext().blit(RenderTypes, textureID, x, y, u, v, width, height, textureWidth, textureHeight); + *//*?} else {*/ + /*matrices.getContext().blit(textureID, x, y, u, v, width, height, textureWidth, textureHeight); + *//*?}*/ + } + /*?}*/ + + public net.minecraft.client.Minecraft getClient() { + /*? if >=1.20 {*/ + return this.minecraft; + /*?} else {*/ + return this.minecraft; + /*?}*/ + } + + public net.minecraft.client.gui.Font getTextRenderer() { + /*? if >=1.20 {*/ + return this.minecraft.font; + /*?} else {*/ + return this.font; + /*?}*/ + } + + public net.minecraft.client.gui.screens.Screen getMinecraftScreen() { + return (net.minecraft.client.gui.screens.Screen) this; + } +} \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java index b79a2fd96..763970439 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedText.java @@ -1,7 +1,8 @@ package pl.skidam.automodpack.client.ui.versioned; import net.minecraft.network.chat.MutableComponent; -/*? if <= 1.19.1 {*/ + +/*? if <=1.19.1 {*/ /*import net.minecraft.network.chat.TextComponent; import net.minecraft.network.chat.TranslatableComponent; *//*?} else {*/ @@ -10,7 +11,7 @@ public class VersionedText { - /*? if <=1.19.1 {*/ + /*? if <=1.19.1 {*/ /*public static MutableComponent translatable(String key, Object... args) { return new TranslatableComponent(key, args); } @@ -18,32 +19,37 @@ public class VersionedText { public static MutableComponent literal(String string) { return new TextComponent(string); } + *//*?} else {*/ + public static MutableComponent translatable(String key, Object... args) { + return Component.translatable(key, args); + } - *//*?} else {*/ - public static MutableComponent translatable(String key, Object... args) { - return Component.translatable(key, args); - } - - public static MutableComponent literal(String string) { - return Component.literal(string); - } - /*?}*/ + public static MutableComponent literal(String string) { + return Component.literal(string); + } + /*?}*/ public static MutableComponent green(String text) { /*? if >=1.19 {*/ - /*return literal(text).withStyle(net.minecraft.ChatFormatting.GREEN);*//*?} else {*/ - /*return literal(text).formatted(net.minecraft.util.Formatting.GREEN);*//*?}*/ + return literal(text).withStyle(net.minecraft.ChatFormatting.GREEN); + /*?} else {*/ + return literal(text); + /*?}*/ } public static MutableComponent bold(String text) { /*? if >=1.19 {*/ - /*return literal(text).withStyle(net.minecraft.ChatFormatting.BOLD);*//*?} else {*/ - /*return literal(text).formatted(net.minecraft.util.Formatting.BOLD);*//*?}*/ + return literal(text).withStyle(net.minecraft.ChatFormatting.BOLD); + /*?} else {*/ + return literal(text); + /*?}*/ } public static MutableComponent red(String text) { /*? if >=1.19 {*/ - /*return literal(text).withStyle(net.minecraft.ChatFormatting.RED);*//*?} else {*/ - /*return literal(text).formatted(net.minecraft.util.Formatting.RED);*//*?}*/ + return literal(text).withStyle(net.minecraft.ChatFormatting.RED); + /*?} else {*/ + return literal(text); + /*?}*/ } } \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java index 7f170ea90..3fded98c3 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java @@ -2,13 +2,12 @@ import java.util.concurrent.Executor; -//try to create an util for more versions? public class VersionedUtil { - public static Executor getMainWorkerExecutor() { - /*? if >=1.18 {*/ - return net.minecraft.Util.getMainWorkerExecutor(); + public static java.util.concurrent.Executor getMainWorkerExecutor() { + /*? if >=1.19 {*/ + return net.minecraft.Util.backgroundExecutor(); /*?} else {*/ - /*return net.minecraft.util.Util.getMainWorkerExecutor();*/ + return net.minecraft.util.Util.getMainWorkerExecutor(); /*?}*/ } } \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java b/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java index 51acba586..c984296b7 100644 --- a/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java +++ b/src/main/java/pl/skidam/automodpack/networking/packet/DataC2SPacket.java @@ -76,12 +76,15 @@ public static CompletableFuture receive(Minecraft Minecraft, Cl LOGGER.info("Modpack address: {}:{} Requires to follow magic protocol: {}", modpackAddress.getHostString(), modpackAddress.getPort(), requiresMagic); + // Create modpackAddresses object first + Jsons.ModpackAddresses modpackAddresses = new Jsons.ModpackAddresses(modpackAddress, serverAddress, requiresMagic); + Boolean needsDisconnecting = null; FriendlyByteBuf response = new FriendlyByteBuf(Unpooled.buffer()); - + // Now use modpackAddresses Path modpackDir = ModpackUtils.getModpackPath(modpackAddresses, modpackName); - Jsons.ModpackAddresses modpackAddresses = new Jsons.ModpackAddresses(modpackAddress, serverAddress, requiresMagic); + var optionalServerModpackContent = ModpackUtils.requestServerModpackContent(modpackAddresses, secret, true); if (optionalServerModpackContent.isPresent()) { @@ -131,4 +134,4 @@ public static CompletableFuture receive(Minecraft Minecraft, Cl private static void disconnectImmediately(ClientHandshakePacketListenerImpl clientLoginNetworkHandler) { ((ClientConnectionAccessor) ((ClientLoginNetworkHandlerAccessor) clientLoginNetworkHandler).getConnection()).getChannel().disconnect(); } -} +} \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeS2CPacket.java b/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeS2CPacket.java index d88c49e75..22fd99bd2 100644 --- a/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeS2CPacket.java +++ b/src/main/java/pl/skidam/automodpack/networking/packet/HandshakeS2CPacket.java @@ -118,8 +118,11 @@ public static void handleHandshake(Connection connection, GameProfile profile, i LOGGER.info("Sending {} modpack host address: {}:{}", profile.getName(), addressToSend, portToSend); - DataPacket dataPacket = new DataPacket(addressToSend, portToSend, serverConfig.modpackName, secret, serverConfig.requireAutoModpackOnClient, requiresMagic); - String packetContentJson = dataPacket.toJson(); + String mainGroupName = "main"; // Standardwert + if (serverConfig.groups != null && serverConfig.groups.containsKey("main")) { + mainGroupName = serverConfig.groups.get("main").groupName; + } + DataPacket dataPacket = new DataPacket(addressToSend, portToSend, mainGroupName, secret, serverConfig.requireAutoModpackOnClient, requiresMagic); String packetContentJson = dataPacket.toJson(); FriendlyByteBuf outBuf = new FriendlyByteBuf(Unpooled.buffer()); outBuf.writeUtf(packetContentJson, Short.MAX_VALUE); From b588ec39d27816390ca9435c981d4e4f423c66c4 Mon Sep 17 00:00:00 2001 From: Suerion Date: Thu, 21 Aug 2025 05:03:02 +0200 Subject: [PATCH 53/56] most version that has only litle issues --- .../client/ui/DownloadSelectionScreen.java | 30 ++++--------------- .../client/ui/versioned/VersionedScreen.java | 5 ++++ 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java index ce9d96a68..3836d26a5 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/DownloadSelectionScreen.java @@ -32,15 +32,9 @@ protected void init() { super.init(); assert this.getClient() != null; - /*? if >=1.19.3 {*/ this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 150, 120, 20, VersionedText.translatable("automodpack.ds.cancel"), button -> { this.getClient().setScreen(this.parent); })); - /*?} else {*/ - this.addButton(buttonWidget(this.width / 2, this.height / 2 + 150, 120, 20, VersionedText.translatable("automodpack.ds.cancel"), button -> { - this.getClient().setScreen(this.parent); - })); - /*?}*/ //buttons from Selectionmanager String currentSelected = SelectionManager.getSelectedPack(); @@ -54,39 +48,27 @@ protected void init() { // between buttons int y = dynamicY + (i * 25); - var displayText = modpack.equalsIgnoreCase(currentSelected) - ? VersionedText.green(modpack) - : VersionedText.bold(modpack); + var displayText = VersionedText.literal(modpack); + if (modpack.equalsIgnoreCase(currentSelected)) { + displayText = VersionedText.green(modpack); + } else { + displayText = VersionedText.bold(modpack); + } - /*? if >=1.19.3 {*/ this.addDrawableChild(buttonWidget(this.width / 2, y, 140, 20, displayText, button -> { //select and start SelectionManager.setSelectedPack(modpack); VersionedUtil.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); - /*?} else {*/ - this.addButton(buttonWidget(this.width / 2, y, 140, 20, displayText, button -> { - //select and start - SelectionManager.setSelectedPack(modpack); - VersionedUtil.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); - })); - /*?}*/ i++; } //Full Serverpack Button if Modpack has permission from server if (serverConfig != null && serverConfig.enableFullServerPack) { - /*? if >=1.19.3 {*/ this.addDrawableChild(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, VersionedText.red(VersionedText.translatable("automodpack.ds.fullserverpack").getString()), button -> { SelectionManager.setSelectedPack("fullserver"); VersionedUtil.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); })); - /*?} else {*/ - this.addButton(buttonWidget(this.width / 2, this.height / 2 + 175, 160, 20, VersionedText.red(VersionedText.translatable("automodpack.ds.fullserverpack").getString()), button -> { - SelectionManager.setSelectedPack("fullserver"); - VersionedUtil.getMainWorkerExecutor().execute(modpackUpdaterInstance::startUpdate); - })); - /*?}*/ } } diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java index 4ad63a572..d34cc8521 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java @@ -65,6 +65,11 @@ public void addDrawableChild(T child) { } super.addChild(child); } + *//*?} elif <1.19.3 {*/ + public void addDrawableChild(Button button) { + this.addButton(button); + } + /*?}*/ /*? if >=1.20 {*/ public static void drawCenteredTextWithShadow(VersionedMatrices matrices, Font textRenderer, MutableComponent text, int centerX, int y, int color) { From ba830839572133c93dc9b7f8cad948aebd40044a Mon Sep 17 00:00:00 2001 From: Suerion Date: Thu, 28 Aug 2025 19:03:38 +0200 Subject: [PATCH 54/56] try to fix stonecutter versioning screen... --- .../ui/versioned/VersionedMatrices.java | 101 ++++++++-------- .../client/ui/versioned/VersionedScreen.java | 109 +++++++----------- .../client/ui/versioned/VersionedUtil.java | 4 +- 3 files changed, 97 insertions(+), 117 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java index c7ef8d638..f421912da 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java @@ -3,50 +3,57 @@ /*? if >=1.20 {*/ import net.minecraft.client.gui.GuiGraphics; /*?} else {*/ -/*import com.mojang.blaze3d.vertex.PoseStack; -*//*?}*/ - -public class VersionedMatrices /*? if <1.20 {*/ /*extends PoseStack *//*?}*/ { - -/*? if >=1.20 {*/ - private final GuiGraphics context; - - public VersionedMatrices(GuiGraphics context) { - this.context = context; - } - - public GuiGraphics getContext() { - return context; - } - - /*? if >=1.21.6 {*/ - public void pushPose() { - context.pose().pushMatrix(); - } - - public void popPose() { - context.pose().popMatrix(); - } - - public void scale(float x, float y, float z) { - context.pose().scale(x, y); - } - /*?} else {*/ - /*public void pushPose() { - context.pose().pushPose(); - } - - public void popPose() { - context.pose().popPose(); - } - - public void scale(float x, float y, float z) { - context.pose().scale(x, y, z); - } - *//*?}*/ -/*?} else {*/ - /*public PoseStack getContext() { - return this; - } -*//*?}*/ -} +import com.mojang.blaze3d.vertex.PoseStack; +/*?}*/ + +public class VersionedMatrices { + /*? if >=1.20 {*/ + private final GuiGraphics context; + + public VersionedMatrices(GuiGraphics context) { + this.context = context; + } + + public GuiGraphics getContext() { + return context; + } + + public void pushPose() { + context.pose().pushPose(); + } + + public void popPose() { + context.pose().popPose(); + } + + public void scale(float x, float y, float z) { + context.pose().scale(x, y, z); + } + /*?} else {*/ + private PoseStack context; + + public VersionedMatrices() { + this.context = new PoseStack(); + } + + public void set(PoseStack matrix) { + this.context = matrix; + } + + public PoseStack getContext() { + return this.context; + } + + public void pushPose() { + context.pushPose(); + } + + public void popPose() { + context.popPose(); + } + + public void scale(float x, float y, float z) { + context.scale(x, y, z); + } + /*?}*/ +} \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java index d34cc8521..6f5e7703c 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java @@ -7,18 +7,20 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; +/*? if >=1.21.2 {*/ +import net.minecraft.client.render.RenderLayer; +import java.util.function.Function; +/*?}*/ + /*? if >=1.21.6 {*/ import net.minecraft.client.renderer.RenderPipelines; -/*?} else if >=1.21.2 {*/ -/*import net.minecraft.client.renderer.RenderType; -import java.util.function.Function; -*//*?}*/ +/*?}*/ /*? if <1.20 {*/ -/*import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.gui.GuiComponent; -*//*?} else {*/ +/*?} else {*/ import net.minecraft.client.gui.GuiGraphics; /*?}*/ @@ -29,99 +31,70 @@ protected VersionedScreen(Component title) { } /*? if <1.20 {*/ - /*@Override + @Override public void render(PoseStack matrix, int mouseX, int mouseY, float delta) { VersionedMatrices matrices = new VersionedMatrices(); - *//*?} else {*/ + matrices.set(matrix); + + super.render(matrix, mouseX, mouseY, delta); + + versionedRender(matrices, mouseX, mouseY, delta); + } + /*?} else {*/ @Override public void render(GuiGraphics matrix, int mouseX, int mouseY, float delta) { VersionedMatrices matrices = new VersionedMatrices(matrix); - /*?}*/ - // Render background - /*? if <1.20.2 {*/ - /*super.renderBackground(matrices.getContext()); - *//*?} elif <1.20.6 {*/ - /*super.renderBackground(matrices.getContext(), mouseX, mouseY, delta); - *//*?} else {*/ super.render(matrix, mouseX, mouseY, delta); - /*?}*/ - // Render the rest of our screen versionedRender(matrices, mouseX, mouseY, delta); - - /*? if <1.20.6 {*/ - /*super.render(matrices.getContext(), mouseX, mouseY, delta); - *//*?}*/ } + /*?}*/ public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { } - /*? if <=1.16.5 {*//* - public void addDrawableChild(T child) { - if (child instanceof ClickableWidget) { - super.addButton((ClickableWidget) child); - return; - } - super.addChild(child); + public T addDrawableChild(T widget) { + return super.addRenderableWidget(widget); } - *//*?} elif <1.19.3 {*/ - public void addDrawableChild(Button button) { - this.addButton(button); - } - /*?}*/ - /*? if >=1.20 {*/ public static void drawCenteredTextWithShadow(VersionedMatrices matrices, Font textRenderer, MutableComponent text, int centerX, int y, int color) { + /*? if >=1.20 {*/ matrices.getContext().drawCenteredString(textRenderer, text, centerX, y, color); + /*?} else {*/ + textRenderer.drawShadow(matrices.getContext(), text, centerX - textRenderer.width(text) / 2, y, color); + /*?}*/ } - /*?} else {*/ - /*public static void drawCenteredTextWithShadow(VersionedMatrices matrices, Font textRenderer, MutableComponent text, int centerX, int y, int color) { - textRenderer.drawShadow(matrices.getContext(), text, (float)(centerX - textRenderer.width(text) / 2), (float)y, color); - } - *//*?}*/ - /*? if <1.19.3 {*/ - /*public static Button buttonWidget(int x, int y, int width, int height, Component message, Button.OnPress onPress) { - return new Button(x, y, width, height, message, onPress); - } - *//*?} else {*/ public static Button buttonWidget(int x, int y, int width, int height, Component message, Button.OnPress onPress) { + /*? if >=1.20 {*/ return Button.builder(message, onPress).pos(x, y).size(width, height).build(); + /*?} else if >=1.19.4 {*/ + return Button.builder(message, onPress).bounds(x, y, width, height).build(); + /*?} else {*/ + return new Button(x, y, width, height, message, onPress); + /*?}*/ } - /*?}*/ - /*? if <=1.20 {*/ - /*public static void drawTexture(ResourceLocation textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { - /^? if <=1.16.5 {^/ - /^Minecraft.getInstance().getTextureManager().bindTexture(textureID); - ^//^?} else {^/ - RenderSystem.setShaderTexture(0, textureID); - /^?}^/ - GuiComponent.blit(matrices.getContext(), x, y, u, v, width, height, textureWidth, textureHeight); - } - *//*?} else {*/ public static void drawTexture(ResourceLocation textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { /*? if >=1.21.6 {*/ matrices.getContext().blit(RenderPipelines.GUI_TEXTURED, textureID, x, y, u, v, width, height, textureWidth, textureHeight); /*?} elif >=1.21.2 {*/ - /*Function RenderTypes = RenderType::guiTextured; - matrices.getContext().blit(RenderTypes, textureID, x, y, u, v, width, height, textureWidth, textureHeight); - *//*?} else {*/ - /*matrices.getContext().blit(textureID, x, y, u, v, width, height, textureWidth, textureHeight); - *//*?}*/ + matrices.getContext().blit(RenderLayer::guiTextured, textureID, x, y, (float)u, (float)v, width, height, textureWidth, textureHeight); + /*?} elif >=1.21 {*/ + matrices.getContext().blit(RenderLayer::guiTextured, textureID, x, y, u, v, width, height, textureWidth, textureHeight); + /*?} elif >=1.20 {*/ + matrices.getContext().blit(textureID, x, y, u, v, width, height, textureWidth, textureHeight); + /*?} else {*/ + RenderSystem.setShaderTexture(0, textureID); + GuiComponent.blit(matrices.getContext(), x, y, u, v, width, height, textureWidth, textureHeight); + /*?}*/ } - /*?}*/ public net.minecraft.client.Minecraft getClient() { - /*? if >=1.20 {*/ return this.minecraft; - /*?} else {*/ - return this.minecraft; - /*?}*/ } - public net.minecraft.client.gui.Font getTextRenderer() { + public Font getTextRenderer() { /*? if >=1.20 {*/ return this.minecraft.font; /*?} else {*/ @@ -129,7 +102,7 @@ public net.minecraft.client.gui.Font getTextRenderer() { /*?}*/ } - public net.minecraft.client.gui.screens.Screen getMinecraftScreen() { - return (net.minecraft.client.gui.screens.Screen) this; + public Screen getMinecraftScreen() { + return this; } } \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java index 3fded98c3..8efd0eeb2 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedUtil.java @@ -3,11 +3,11 @@ import java.util.concurrent.Executor; public class VersionedUtil { - public static java.util.concurrent.Executor getMainWorkerExecutor() { + public static Executor getMainWorkerExecutor() { /*? if >=1.19 {*/ return net.minecraft.Util.backgroundExecutor(); /*?} else {*/ - return net.minecraft.util.Util.getMainWorkerExecutor(); + return net.minecraft.Util.ioPool(); /*?}*/ } } \ No newline at end of file From 3b7df815f9dceb42bb94e3f3d5c84c67f6492f01 Mon Sep 17 00:00:00 2001 From: Suerion Date: Thu, 28 Aug 2025 19:38:45 +0200 Subject: [PATCH 55/56] try to fix stonecutter versioning screen... again, 1.21.6 will not working again... don't know whats goint on on neoforge --- .../client/ui/versioned/VersionedMatrices.java | 14 ++++++++++++++ .../client/ui/versioned/VersionedScreen.java | 6 ++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java index f421912da..41f501353 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java @@ -18,6 +18,19 @@ public GuiGraphics getContext() { return context; } + /*? if >=1.21.6 {*/ + public void pushPose() { + context.pose().pushMatrix(); + } + + public void popPose() { + context.pose().popMatrix(); + } + + public void scale(float x, float y, float z) { + context.pose().scale(x, y); // In 1.21.6 nimmt scale nur x und y + } + /*?} else {*/ public void pushPose() { context.pose().pushPose(); } @@ -29,6 +42,7 @@ public void popPose() { public void scale(float x, float y, float z) { context.pose().scale(x, y, z); } + /*?}*/ /*?} else {*/ private PoseStack context; diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java index 6f5e7703c..1a8b56ef6 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java @@ -8,7 +8,7 @@ import net.minecraft.resources.ResourceLocation; /*? if >=1.21.2 {*/ -import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.renderer.RenderType; import java.util.function.Function; /*?}*/ @@ -79,9 +79,7 @@ public static void drawTexture(ResourceLocation textureID, VersionedMatrices mat /*? if >=1.21.6 {*/ matrices.getContext().blit(RenderPipelines.GUI_TEXTURED, textureID, x, y, u, v, width, height, textureWidth, textureHeight); /*?} elif >=1.21.2 {*/ - matrices.getContext().blit(RenderLayer::guiTextured, textureID, x, y, (float)u, (float)v, width, height, textureWidth, textureHeight); - /*?} elif >=1.21 {*/ - matrices.getContext().blit(RenderLayer::guiTextured, textureID, x, y, u, v, width, height, textureWidth, textureHeight); + matrices.getContext().blit(RenderType::guiTextured, textureID, x, y, (float)u, (float)v, width, height, textureWidth, textureHeight); /*?} elif >=1.20 {*/ matrices.getContext().blit(textureID, x, y, u, v, width, height, textureWidth, textureHeight); /*?} else {*/ From a56ef9371950b7b3f3ffe19820d27534e0361daf Mon Sep 17 00:00:00 2001 From: Suerion Date: Thu, 28 Aug 2025 21:15:17 +0200 Subject: [PATCH 56/56] try to fix stonecutter versioning screen... again, 1.21.6 bruhhh, yet it is an issue on fabric... --- .../ui/versioned/VersionedMatrices.java | 76 ++++++++----------- .../client/ui/versioned/VersionedScreen.java | 38 ++++++---- 2 files changed, 58 insertions(+), 56 deletions(-) diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java index 41f501353..270e6c448 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedMatrices.java @@ -1,73 +1,63 @@ package pl.skidam.automodpack.client.ui.versioned; -/*? if >=1.20 {*/ -import net.minecraft.client.gui.GuiGraphics; -/*?} else {*/ +/*? if <1.20 {*/ import com.mojang.blaze3d.vertex.PoseStack; +/*?} else {*/ +import net.minecraft.client.gui.GuiGraphics; /*?}*/ public class VersionedMatrices { - /*? if >=1.20 {*/ - private final GuiGraphics context; - - public VersionedMatrices(GuiGraphics context) { - this.context = context; - } - - public GuiGraphics getContext() { - return context; - } - - /*? if >=1.21.6 {*/ - public void pushPose() { - context.pose().pushMatrix(); - } - - public void popPose() { - context.pose().popMatrix(); - } - - public void scale(float x, float y, float z) { - context.pose().scale(x, y); // In 1.21.6 nimmt scale nur x und y - } + /*? if <1.20 {*/ + private PoseStack context; /*?} else {*/ - public void pushPose() { - context.pose().pushPose(); - } - - public void popPose() { - context.pose().popPose(); - } - - public void scale(float x, float y, float z) { - context.pose().scale(x, y, z); - } + private GuiGraphics context; /*?}*/ - /*?} else {*/ - private PoseStack context; + /*? if <1.20 {*/ public VersionedMatrices() { this.context = new PoseStack(); } - public void set(PoseStack matrix) { - this.context = matrix; + public void set(PoseStack matrices) { + this.context = matrices; + } + /*?} else {*/ + public VersionedMatrices(GuiGraphics matrices) { + this.context = matrices; } + /*?}*/ + /*? if <1.20 {*/ public PoseStack getContext() { - return this.context; + return context; + } + /*?} else {*/ + public GuiGraphics getContext() { + return context; } + /*?}*/ public void pushPose() { + /*? if <1.20 {*/ context.pushPose(); + /*?} else {*/ + context.pose().pushPose(); + /*?}*/ } public void popPose() { + /*? if <1.20 {*/ context.popPose(); + /*?} else {*/ + context.pose().popPose(); + /*?}*/ } public void scale(float x, float y, float z) { + /*? if <1.20 {*/ context.scale(x, y, z); + /*?} else {*/ + context.pose().scale(x, y, z); + /*?}*/ } - /*?}*/ } \ No newline at end of file diff --git a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java index 1a8b56ef6..56da6e960 100644 --- a/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java +++ b/src/main/java/pl/skidam/automodpack/client/ui/versioned/VersionedScreen.java @@ -7,19 +7,24 @@ import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; -/*? if >=1.21.2 {*/ +/*? if >=1.21.2 {*//* import net.minecraft.client.renderer.RenderType; import java.util.function.Function; -/*?}*/ +*//*?}*/ -/*? if >=1.21.6 {*/ +/*? if >=1.21.6 {*//* import net.minecraft.client.renderer.RenderPipelines; -/*?}*/ +*//*?}*/ /*? if <1.20 {*/ import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; +/*? if <1.21.6 {*/ import net.minecraft.client.gui.GuiComponent; +/*?} else { */ +// Ab 1.21.6 wurde GuiComponent entfernt +import net.minecraft.client.gui.GuiGraphics; +/*?} */ /*?} else {*/ import net.minecraft.client.gui.GuiGraphics; /*?}*/ @@ -35,21 +40,17 @@ protected VersionedScreen(Component title) { public void render(PoseStack matrix, int mouseX, int mouseY, float delta) { VersionedMatrices matrices = new VersionedMatrices(); matrices.set(matrix); - super.render(matrix, mouseX, mouseY, delta); - versionedRender(matrices, mouseX, mouseY, delta); } /*?} else {*/ @Override public void render(GuiGraphics matrix, int mouseX, int mouseY, float delta) { VersionedMatrices matrices = new VersionedMatrices(matrix); - super.render(matrix, mouseX, mouseY, delta); - versionedRender(matrices, mouseX, mouseY, delta); } - /*?}*/ + /*?} */ public void versionedRender(VersionedMatrices matrices, int mouseX, int mouseY, float delta) { } @@ -67,24 +68,35 @@ public static void drawCenteredTextWithShadow(VersionedMatrices matrices, Font t public static Button buttonWidget(int x, int y, int width, int height, Component message, Button.OnPress onPress) { /*? if >=1.20 {*/ - return Button.builder(message, onPress).pos(x, y).size(width, height).build(); - /*?} else if >=1.19.4 {*/ return Button.builder(message, onPress).bounds(x, y, width, height).build(); + /*?} else if >=1.19.3 {*/ + // Für Minecraft 1.19.3 und 1.19.4: Erstelle eine anonyme Button-Unterklasse + return new Button(x, y, width, height, message, onPress, button -> Component.empty()) { + // Zusätzliche Methodenüberschreibungen falls nötig + }; /*?} else {*/ return new Button(x, y, width, height, message, onPress); /*?}*/ } public static void drawTexture(ResourceLocation textureID, VersionedMatrices matrices, int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight) { + /*? if >=1.20 {*/ /*? if >=1.21.6 {*/ - matrices.getContext().blit(RenderPipelines.GUI_TEXTURED, textureID, x, y, u, v, width, height, textureWidth, textureHeight); + matrices.getContext().blit(textureID, x, y, u, v, width, height, textureWidth, textureHeight); + /*?} elif >=1.21.3 {*/ + matrices.getContext().blit((resourceLocation) -> RenderType.gui(), textureID, x, y, (float)u, (float)v, width, height, textureWidth, textureHeight); /*?} elif >=1.21.2 {*/ matrices.getContext().blit(RenderType::guiTextured, textureID, x, y, (float)u, (float)v, width, height, textureWidth, textureHeight); - /*?} elif >=1.20 {*/ + /*?} else {*/ matrices.getContext().blit(textureID, x, y, u, v, width, height, textureWidth, textureHeight); + /*?}*/ /*?} else {*/ RenderSystem.setShaderTexture(0, textureID); + /*? if <1.21.6 {*/ GuiComponent.blit(matrices.getContext(), x, y, u, v, width, height, textureWidth, textureHeight); + /*?} else {*/ + matrices.getContext().blit(textureID, x, y, u, v, width, height, textureWidth, textureHeight); + /*?}*/ /*?}*/ }