From 4c7da4cab566dae2bf3bd3736fcd2866dcb87594 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ana=C3=AFs=20Saraiva?= <53227802+Kisakay@users.noreply.github.com> Date: Mon, 19 Oct 2026 23:31:49 +0200 Subject: [PATCH] =?UTF-8?q?nosingleplayer=201.1.9=20:=20menu=20titre=20r?= =?UTF-8?q?=C3=A9silient=20(repli=20vanilla)=20+=20launcher=20:=20plus=20d?= =?UTF-8?q?e=20console=20noire=20Windows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Écran noir au menu titre sur les PC Windows (2 postes) : dans TitleScreen.extractRenderState, les widgets sont dessinés juste APRÈS extractPanorama. Toute exception dans la redirection du panorama interrompt donc le rendu du menu entier (écran noir, sans bouton). Mod nosingleplayer 1.1.9 : - try/catch autour du fond custom + repli automatique sur le panorama vanilla (avant : écran noir définitif si la texture est refusée par le GPU ou absente du jar) ; - try/catch autour de la construction du menu, et les widgets vanilla ne sont retirés qu'APRÈS la création des widgets SurviePote (avant : une exception laissait un menu vidé) ; - ping serveur déplacé sur un thread dédié : il était lancé depuis extractWidgetRenderState, donc sur le thread de rendu (un DNS lent suffisait à figer le menu) ; - log GPU au démarrage du menu (nom/vendor/pilote/backend) ; - option de diagnostic -Dsurviepote.customTitle=false (menu vanilla). Launcher : java.exe est lancé avec detached:true sans windowsHide -> sur Windows, une console noire et vide s'ouvre par-dessus le jeu. Ajout de windowsHide:true. atlas : distribution.json regénéré (MD5/URL du nouveau jar). --- atlas/root/distribution.json | 8 +- ...yer-1.1.8.jar => nosingleplayer-1.1.9.jar} | Bin 3637392 -> 3639116 bytes launcher/app/assets/js/processbuilder.js | 4 + mods/nosingleplayer/README.md | 12 +- mods/nosingleplayer/gradle.properties | 2 +- .../gui/ServerStatusWidget.java | 27 +++- .../nosingleplayer/mixin/ScreenAccessor.java | 10 ++ .../mixin/TitleScreenMixin.java | 26 +++- .../mixin/TitleScreenRenderMixin.java | 120 ++++++++++++++---- 9 files changed, 170 insertions(+), 39 deletions(-) rename atlas/root/servers/SurviePote-26.3/fabricmods/required/{nosingleplayer-1.1.8.jar => nosingleplayer-1.1.9.jar} (99%) diff --git a/atlas/root/distribution.json b/atlas/root/distribution.json index 09bb1bf..58d846c 100644 --- a/atlas/root/distribution.json +++ b/atlas/root/distribution.json @@ -487,13 +487,13 @@ } }, { - "id": "fr.surviepote:nosingleplayer:1.1.8@jar", + "id": "fr.surviepote:nosingleplayer:1.1.9@jar", "name": "NoSingleplayer (SurviePote)", "type": "FabricMod", "artifact": { - "size": 3637392, - "url": "https://git.kisakay.com/k/mc/raw/branch/main/atlas/root/servers/SurviePote-26.3/fabricmods/required/nosingleplayer-1.1.8.jar", - "MD5": "dc69cd7ebc5d10ba4797c4e212e47e0c" + "size": 3639116, + "url": "https://git.kisakay.com/k/mc/raw/branch/main/atlas/root/servers/SurviePote-26.3/fabricmods/required/nosingleplayer-1.1.9.jar", + "MD5": "d9666a2698e9bcb3d69e03097dc081b4" } }, { diff --git a/atlas/root/servers/SurviePote-26.3/fabricmods/required/nosingleplayer-1.1.8.jar b/atlas/root/servers/SurviePote-26.3/fabricmods/required/nosingleplayer-1.1.9.jar similarity index 99% rename from atlas/root/servers/SurviePote-26.3/fabricmods/required/nosingleplayer-1.1.8.jar rename to atlas/root/servers/SurviePote-26.3/fabricmods/required/nosingleplayer-1.1.9.jar index c0b90fd5f8a70ca2859d3f075676299182d10731..6c47547765b9632c5bad3fd781dd948890110347 100644 GIT binary patch delta 12373 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 O4dxPTN6O6^7#ILI8l;y1 delta 10704 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 z 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 nouvelle + // console) : une fenêtre noire, vide (stdout est pipe vers le launcher), + // qui traîne par-dessus la fenêtre du jeu pendant toute la session. + windowsHide: true, env: gameEnv }) diff --git a/mods/nosingleplayer/README.md b/mods/nosingleplayer/README.md index 6fafdb6..3349a67 100644 --- a/mods/nosingleplayer/README.md +++ b/mods/nosingleplayer/README.md @@ -13,4 +13,14 @@ au serveur unique : pas de refmap nécessaire. Build : `cd mods/nosingleplayer && ./gradlew build` (dans nix-shell racine pour Java 25). -Jar : `build/libs/nosingleplayer-1.1.4.jar` → copié dans `atlas/.../fabricmods/required/`. +Jar : `build/libs/nosingleplayer-1.1.9.jar` → copié dans `atlas/.../fabricmods/required/`. + +## Diagnostic + +- `-Dsurviepote.customTitle=false` (options JVM du launcher) : repasser au menu **vanilla** + (panorama vanilla au lieu du fond custom). Sert à isoler un souci de rendu du fond custom. +- Le mod log au démarrage du menu : `[SurviePote] GPU: | | pilote | backend ` + et `[SurviePote] Fond chargé : x` (ou l'erreur de chargement de la texture). +- Si le fond custom échoue (texture refusée par le GPU, jar corrompu…), le mod se repli + automatiquement sur le panorama vanilla au lieu de laisser un écran noir. + diff --git a/mods/nosingleplayer/gradle.properties b/mods/nosingleplayer/gradle.properties index 3b623e8..4a289e5 100644 --- a/mods/nosingleplayer/gradle.properties +++ b/mods/nosingleplayer/gradle.properties @@ -5,7 +5,7 @@ loader_version=0.20.0 loom_version=1.19.1 # Mod Properties -mod_version=1.1.8 +mod_version=1.1.9 maven_group=fr.surviepote archives_base_name=nosingleplayer diff --git a/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/gui/ServerStatusWidget.java b/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/gui/ServerStatusWidget.java index 056d277..0cfff86 100644 --- a/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/gui/ServerStatusWidget.java +++ b/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/gui/ServerStatusWidget.java @@ -26,6 +26,14 @@ public class ServerStatusWidget extends AbstractWidget { private static final long REFRESH_MS = 15000L; private static final long TIMEOUT_MS = 8000L; + /** Thread dédié : le ping ne doit jamais bloquer le thread de rendu. */ + private static final java.util.concurrent.ExecutorService PING_EXECUTOR = + java.util.concurrent.Executors.newSingleThreadExecutor(r -> { + Thread t = new Thread(r, "SurviePote-ServerStatus"); + t.setDaemon(true); + return t; + }); + private static final int BG_COLOR = 0xB0000000; private static final int ONLINE_COLOR = 0xFF4CD964; private static final int OFFLINE_COLOR = 0xFFE04B4B; @@ -106,12 +114,25 @@ public class ServerStatusWidget extends AbstractWidget { } private void refresh() { + // ATTENTION : pingServer() fait une résolution DNS + ouvre une connexion. + // Appelé depuis extractWidgetRenderState (thread de rendu), ça BLOQUE le + // rendu du menu (écran figé/noir) le temps du timeout DNS. On le lance + // donc sur un thread dédié ; l'état lu par le rendu est "volatile". try { this.pingStartedAt = System.currentTimeMillis(); this.pending = true; - this.pinger.pingServer(this.data, () -> { - }, () -> { - }, EventLoopGroupHolder.remote(Minecraft.getInstance().options.useNativeTransport())); + PING_EXECUTOR.execute(() -> { + try { + this.pinger.pingServer(this.data, () -> { + }, () -> { + }, EventLoopGroupHolder.remote(Minecraft.getInstance().options.useNativeTransport())); + } catch (Exception e) { + NoSingleplayer.LOGGER.warn("[SurviePote] Ping serveur impossible : {}", e.toString()); + this.pending = false; + this.resolved = true; + this.online = false; + } + }); } catch (Exception e) { NoSingleplayer.LOGGER.warn("[SurviePote] Ping serveur impossible : {}", e.toString()); this.pending = false; diff --git a/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/ScreenAccessor.java b/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/ScreenAccessor.java index 50cf1bb..f7a790d 100644 --- a/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/ScreenAccessor.java +++ b/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/ScreenAccessor.java @@ -1,14 +1,24 @@ package fr.surviepote.nosingleplayer.mixin; import java.util.List; +import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.components.Renderable; import net.minecraft.client.gui.screens.Screen; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(Screen.class) public interface ScreenAccessor { @Accessor("renderables") List surviepote$getRenderables(); + + /** + * Panorama vanilla (déclaré dans Screen, appelé par TitleScreen). + * Utilisé en repli quand le fond custom de SurviePote n'a pas pu être chargé : + * sans ça, la redirection de l'appel laisse l'écran entièrement noir. + */ + @Invoker("extractPanorama") + void surviepote$extractVanillaPanorama(GuiGraphicsExtractor extractor, float partialTick); } diff --git a/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/TitleScreenMixin.java b/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/TitleScreenMixin.java index d6c81cf..4db3088 100644 --- a/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/TitleScreenMixin.java +++ b/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/TitleScreenMixin.java @@ -45,7 +45,18 @@ public abstract class TitleScreenMixin { @Inject(method = "init", at = @At("TAIL")) private void surviepote$customizeMenu(CallbackInfo ci) { - TitleScreen self = (TitleScreen) (Object) this; + // Garde-fou : si la personnalisation échoue, on NE DOIT PAS avoir retiré les + // boutons vanilla (menu vide + fond noir = "écran cassé"). Les retraits ne + // sont appliqués qu'après la création des widgets, en fin de méthode. + try { + surviepote$buildMenu((TitleScreen) (Object) this); + } catch (Throwable t) { + NoSingleplayer.LOGGER.error("[SurviePote] Personnalisation du menu échouée, menu vanilla conservé.", t); + } + } + + @Unique + private void surviepote$buildMenu(TitleScreen self) { Minecraft minecraft = Minecraft.getInstance(); String solo = Component.translatable("menu.singleplayer").getString(); @@ -97,9 +108,9 @@ public abstract class TitleScreenMixin { } } } - for (GuiEventListener widget : toRemove) { - surviepote$removeWidget(self, widget); - } + // ATTENTION : les retraits des widgets vanilla ne sont appliqués qu'APRÈS la + // création des widgets SurviePote (fin de méthode). Si une exception survient + // entre-temps, le menu vanilla est conservé au lieu d'être vidé. Button join = Button.builder(Component.literal("Rejoindre SurviePote"), pressed -> { ServerData data = new ServerData("SurviePote", SERVER_HOST, ServerData.Type.OTHER); @@ -158,6 +169,13 @@ public abstract class TitleScreenMixin { w.visible = true; w.active = true; } + + // Tout est prêt : on retire enfin les widgets vanilla (Solo, Multi, Realms, + // réseau social, icônes bas) remplacés ci-dessus. + for (GuiEventListener widget : toRemove) { + surviepote$removeWidget(self, widget); + } + if (!foundMulti) { NoSingleplayer.LOGGER.warn("[SurviePote] Bouton Multi introuvable, Join placé par défaut."); } diff --git a/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/TitleScreenRenderMixin.java b/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/TitleScreenRenderMixin.java index bb1250a..67591ce 100644 --- a/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/TitleScreenRenderMixin.java +++ b/mods/nosingleplayer/src/main/java/fr/surviepote/nosingleplayer/mixin/TitleScreenRenderMixin.java @@ -1,5 +1,6 @@ package fr.surviepote.nosingleplayer.mixin; +import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.realmsclient.gui.screens.RealmsNotificationsScreen; import fr.surviepote.nosingleplayer.ModTextures; import fr.surviepote.nosingleplayer.NoSingleplayer; @@ -29,6 +30,15 @@ public abstract class TitleScreenRenderMixin { private static final String SURVIEPOTE_BACKGROUND_RESOURCE = "/assets/nosingleplayer/textures/gui/background.png"; + /** + * Option de diagnostic : lancer le jeu avec + * {@code -Dsurviepote.customTitle=false} pour repasser au menu vanilla + * (utilisable dans les options JVM du launcher). Sert à isoler un éventuel + * souci de rendu du fond custom sur un poste donné. + */ + @Unique + private static final String DISABLE_CUSTOM_TITLE_PROPERTY = "surviepote.customTitle"; + @Unique private static DynamicTexture surviepote$background; @@ -38,6 +48,13 @@ public abstract class TitleScreenRenderMixin { @Unique private static int surviepote$backgroundHeight; + // Le fond custom a déjà échoué : on ne réessaie plus (le menu reste noir sinon). + @Unique + private static boolean surviepote$backgroundFailed; + + @Unique + private static boolean surviepote$gpuLogged; + // Pas de panorama dynamique : fond statique custom à la place. // Note : extractPanorama est déclarée dans Screen (héritée), on redirige donc // l'APPEL dans TitleScreen plutôt que la méthode elle-même. @@ -46,39 +63,90 @@ public abstract class TitleScreenRenderMixin { at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screens/TitleScreen;extractPanorama(Lnet/minecraft/client/gui/GuiGraphicsExtractor;F)V")) private void surviepote$customBackground(TitleScreen self, GuiGraphicsExtractor extractor, float partialTick) { - int w = Minecraft.getInstance().getWindow().getGuiScaledWidth(); - int h = Minecraft.getInstance().getWindow().getGuiScaledHeight(); + // Les widgets du menu sont dessinés par super.extractRenderState(), juste APRÈS + // cet appel. Toute exception levée ici interromp le rendu du menu entier => + // écran 100 % noir (sans boutons). D'où les garde-fous ci-dessous. + surviepote$logGpuOnce(); - surviepote$loadBackground(); - if (surviepote$background == null) { + // Menu vanilla si le fond custom a déjà échoué, ou si l'utilisateur a forcé + // -Dsurviepote.customTitle=false (option de diagnostic). + final boolean customEnabled = !"false".equalsIgnoreCase( + System.getProperty(DISABLE_CUSTOM_TITLE_PROPERTY, "true")); + if (surviepote$backgroundFailed || !customEnabled) { + surviepote$vanillaPanorama(self, extractor, partialTick); return; } - float screenAspect = (float) w / (float) h; - float texAspect = (float) surviepote$backgroundWidth / (float) surviepote$backgroundHeight; + try { + int w = Minecraft.getInstance().getWindow().getGuiScaledWidth(); + int h = Minecraft.getInstance().getWindow().getGuiScaledHeight(); - int u, v, srcW, srcH; - if (screenAspect > texAspect) { - // Écran plus large que l'image : on rogne en haut/bas. - srcW = surviepote$backgroundWidth; - srcH = Math.round(surviepote$backgroundWidth / screenAspect); - u = 0; - v = (surviepote$backgroundHeight - srcH) / 2; - } else { - // Écran plus haut que l'image : on rogne à gauche/droite. - srcH = surviepote$backgroundHeight; - srcW = Math.round(surviepote$backgroundHeight * screenAspect); - u = (surviepote$backgroundWidth - srcW) / 2; - v = 0; + surviepote$loadBackground(); + if (surviepote$background == null) { + surviepote$vanillaPanorama(self, extractor, partialTick); + return; + } + + float screenAspect = (float) w / (float) h; + float texAspect = (float) surviepote$backgroundWidth / (float) surviepote$backgroundHeight; + + int u, v, srcW, srcH; + if (screenAspect > texAspect) { + // Écran plus large que l'image : on rogne en haut/bas. + srcW = surviepote$backgroundWidth; + srcH = Math.round(surviepote$backgroundWidth / screenAspect); + u = 0; + v = (surviepote$backgroundHeight - srcH) / 2; + } else { + // Écran plus haut que l'image : on rogne à gauche/droite. + srcH = surviepote$backgroundHeight; + srcW = Math.round(surviepote$backgroundHeight * screenAspect); + u = (surviepote$backgroundWidth - srcW) / 2; + v = 0; + } + + // Surcharge complète : (u, v) = origine dans la texture, (w, h) = taille à + // l'écran, (srcW, srcH) = taille de la région source dans la texture. + // L'overload court réutilise w/h comme région source (=> zoom sur un coin). + extractor.blit(RenderPipelines.GUI_TEXTURED, SURVIEPOTE_BACKGROUND, + 0, 0, (float) u, (float) v, + w, h, srcW, srcH, + surviepote$backgroundWidth, surviepote$backgroundHeight, -1); + } catch (Throwable t) { + // Repli : on bascule sur le panorama vanilla pour ne pas laisser un écran noir. + surviepote$backgroundFailed = true; + NoSingleplayer.LOGGER.error("[SurviePote] Échec du fond custom, repli sur le panorama vanilla.", t); + surviepote$vanillaPanorama(self, extractor, partialTick); } + } - // Surcharge complète : (u, v) = origine dans la texture, (w, h) = taille à - // l'écran, (srcW, srcH) = taille de la région source dans la texture. - // L'overload court réutilise w/h comme région source (=> zoom sur un coin). - extractor.blit(RenderPipelines.GUI_TEXTURED, SURVIEPOTE_BACKGROUND, - 0, 0, (float) u, (float) v, - w, h, srcW, srcH, - surviepote$backgroundWidth, surviepote$backgroundHeight, -1); + /** + * Redessine le panorama vanilla (appelé dans Screen, pas dans TitleScreen : + * la redirection porte sur l'appel, donc pas de récursion). + */ + @Unique + private void surviepote$vanillaPanorama(TitleScreen self, GuiGraphicsExtractor extractor, float partialTick) { + try { + ((ScreenAccessor) self).surviepote$extractVanillaPanorama(extractor, partialTick); + } catch (Throwable t) { + NoSingleplayer.LOGGER.error("[SurviePote] Échec du panorama vanilla.", t); + } + } + + /** Log une fois les infos GPU : permet de comparer un poste qui plante d'un poste qui marche. */ + @Unique + private static void surviepote$logGpuOnce() { + if (surviepote$gpuLogged) { + return; + } + surviepote$gpuLogged = true; + try { + var info = RenderSystem.getDevice().getDeviceInfo(); + NoSingleplayer.LOGGER.info("[SurviePote] GPU: {} | {} | pilote {} | backend {}", + info.name(), info.vendorName(), info.driverInfo(), info.backendName()); + } catch (Throwable t) { + NoSingleplayer.LOGGER.warn("[SurviePote] Infos GPU indisponibles : {}", t.toString()); + } } /**