nosingleplayer 1.1.3: fix connexion + bouton Quitter SurviePote
- TitleScreenMixin : TransferState null sur startConnecting -> connexion normale, corrige "This server does not accept transfers". - PauseScreenMixin (nouveau) : renomme le bouton de deconnexion du menu Echap en "Quitter SurviePote" et redirige vers l'ecran d'accueil (TitleScreen) au lieu de la liste des serveurs. - build.gradle : tache runClient (dev sans loom) reutilisant ~/.surviepote/common. - Jar 1.1.3 copie dans l'atlas + distribution.json regenere.
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
# nosingleplayer (mod maison SurviePote)
|
||||
|
||||
Désactive le bouton **Solo** du menu principal (Mixin sur `TitleScreen.init`).
|
||||
Désactive le bouton **Solo** du menu principal (Mixin sur `TitleScreen.init`) et adapte l'UI
|
||||
au serveur unique :
|
||||
- Menu titre : bouton **Rejoindre SurviePote** (connexion directe à `mcpv.ihorizon.org:25565`,
|
||||
sans transfert) ; Solo, Multi, Realms, réseau social et icônes bas retirés.
|
||||
- Menu Échap : le bouton de déconnexion devient **Quitter SurviePote** et renvoie à l'écran
|
||||
d'accueil du jeu (et non la liste des serveurs).
|
||||
- MC 26.3, Fabric Loader 0.20.0, Java 25, `environment: client`.
|
||||
- Particularité 26.x : Mojang ne publie plus de mappings (ni Yarn ni `client_mappings`) et le
|
||||
jeu n'est plus obfusqué → **pas de Loom**, compilation directe contre le jar client Mojang
|
||||
@@ -8,4 +13,4 @@ Désactive le bouton **Solo** du menu principal (Mixin sur `TitleScreen.init`).
|
||||
pas de refmap nécessaire.
|
||||
|
||||
Build : `cd mods/nosingleplayer && ./gradlew build` (dans nix-shell racine pour Java 25).
|
||||
Jar : `build/libs/nosingleplayer-1.0.0.jar` → copié dans `atlas/.../fabricmods/required/`.
|
||||
Jar : `build/libs/nosingleplayer-1.1.3.jar` → copié dans `atlas/.../fabricmods/required/`.
|
||||
|
||||
@@ -64,3 +64,97 @@ processResources {
|
||||
java {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Dev : lance le vrai client MC 26.3 + nosingleplayer (build sans loom).
|
||||
// Réutilise l'installation commune du launcher SurviePote (~/.surviepote/common :
|
||||
// versions, libraries, assets — remplie au premier lancement). Le mod est copié
|
||||
// dans runClient/game/mods/ (Knot le découvre comme un mod Fabric classique).
|
||||
// Usage : ./gradlew runClient
|
||||
// ---------------------------------------------------------------------------
|
||||
def survieCommon = new File(System.getProperty('user.home'), '.surviepote/common')
|
||||
def mcVersion = project.minecraft_version
|
||||
def loaderVersion = project.loader_version
|
||||
|
||||
tasks.register('extractClientNatives', Copy) {
|
||||
def versionJson = new groovy.json.JsonSlurper().parse(
|
||||
new File(survieCommon, "versions/${mcVersion}/${mcVersion}.json"))
|
||||
from(versionJson.libraries.findAll { lib ->
|
||||
lib.name.contains(':natives-linux') && (lib.rules == null || lib.rules.any { it.action == 'allow' && (it.os == null || it.os.name == 'linux') })
|
||||
}.collect { lib ->
|
||||
zipTree(new File(survieCommon, "libraries/${lib.downloads.artifact.path}"))
|
||||
})
|
||||
into(layout.buildDirectory.dir('runClient/natives'))
|
||||
include('**/*.so')
|
||||
eachFile { f -> f.path = f.name }
|
||||
}
|
||||
|
||||
tasks.register('runClient', JavaExec) {
|
||||
dependsOn('extractClientNatives', 'jar')
|
||||
group = 'fabric'
|
||||
description = 'Lance le client Minecraft avec le mod (dev visuel, sans loom).'
|
||||
|
||||
def versionJson = new groovy.json.JsonSlurper().parse(
|
||||
new File(survieCommon, "versions/${mcVersion}/${mcVersion}.json"))
|
||||
def fabricJson = new groovy.json.JsonSlurper().parse(
|
||||
new File(survieCommon, "versions/${mcVersion}-fabric-${loaderVersion}/${mcVersion}-fabric-${loaderVersion}.json"))
|
||||
def mavenToPath = { String coord ->
|
||||
def parts = coord.split(':')
|
||||
return "${parts[0].replace('.', '/')}/${parts[1]}/${parts[2]}/${parts[1]}-${parts[2]}.jar"
|
||||
}
|
||||
|
||||
doFirst {
|
||||
def modsDir = layout.buildDirectory.dir('runClient/game/mods').get().asFile
|
||||
delete(modsDir)
|
||||
modsDir.mkdirs()
|
||||
copy {
|
||||
from(tasks.named('jar'))
|
||||
into(modsDir)
|
||||
}
|
||||
}
|
||||
|
||||
// NixOS : dlopen ne voit ni libGL ni libvulkan sans LD_LIBRARY_PATH (cf launcher).
|
||||
def nixStore = new File('/nix/store')
|
||||
def glDirs = []
|
||||
['/run/opengl-driver/lib', '/run/current-system/sw/lib'].each { d ->
|
||||
if (new File(d).exists()) glDirs << d
|
||||
}
|
||||
if (nixStore.exists()) {
|
||||
nixStore.eachDir { e ->
|
||||
def n = e.name
|
||||
if (n.contains('libglvnd') || n.contains('vulkan-loader') || n.contains('alsa-lib')
|
||||
|| n.contains('pulseaudio') || (n.contains('pipewire') && !n.contains('python'))) {
|
||||
def lib = new File(e, 'lib')
|
||||
if (lib.exists()) glDirs << lib.absolutePath
|
||||
}
|
||||
}
|
||||
}
|
||||
def prevLd = System.getenv('LD_LIBRARY_PATH')
|
||||
environment('LD_LIBRARY_PATH', (prevLd ? prevLd + ':' : '') + glDirs.join(':'))
|
||||
if (!System.getenv('SDL_VIDEODRIVER') && (System.getenv('WAYLAND_DISPLAY') || new File('/run/user/1000/wayland-1').exists())) {
|
||||
environment('SDL_VIDEODRIVER', 'wayland')
|
||||
}
|
||||
|
||||
javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(25) }
|
||||
classpath = files(
|
||||
new File(survieCommon, "versions/${mcVersion}/${mcVersion}.jar"),
|
||||
versionJson.libraries.findAll { lib ->
|
||||
!(lib.name.contains(':natives-')) && (lib.rules == null || lib.rules.any { it.action == 'allow' && (it.os == null || it.os.name == 'linux') })
|
||||
}.collect { new File(survieCommon, "libraries/${it.downloads.artifact.path}") },
|
||||
fabricJson.libraries.collect { new File(survieCommon, "libraries/${mavenToPath(it.name)}") }
|
||||
)
|
||||
mainClass = 'net.fabricmc.loader.impl.launch.knot.KnotClient'
|
||||
args = [
|
||||
'--gameDir', layout.buildDirectory.dir('runClient/game').get().asFile.absolutePath,
|
||||
'--assetsDir', new File(survieCommon, 'assets').absolutePath,
|
||||
'--assetIndex', versionJson.assetIndex.id,
|
||||
'--version', "${project.archives_base_name}-dev",
|
||||
'--username', 'Dev', '--uuid', '00000000-0000-0000-0000-000000000000',
|
||||
'--accessToken', '0', '--versionType', 'release'
|
||||
]
|
||||
jvmArgs = [
|
||||
"-Djava.library.path=${layout.buildDirectory.dir('runClient/natives').get().asFile.absolutePath}",
|
||||
'-Xmx4G'
|
||||
]
|
||||
systemProperties['org.lwjgl.util.Debug'] = 'false'
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ loader_version=0.20.0
|
||||
loom_version=1.19.1
|
||||
|
||||
# Mod Properties
|
||||
mod_version=1.1.2
|
||||
mod_version=1.1.3
|
||||
maven_group=fr.surviepote
|
||||
archives_base_name=nosingleplayer
|
||||
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package fr.surviepote.nosingleplayer.mixin;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
import net.minecraft.client.gui.screens.PauseScreen;
|
||||
import net.minecraft.client.gui.screens.TitleScreen;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.network.chat.CommonComponents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(PauseScreen.class)
|
||||
public abstract class PauseScreenMixin {
|
||||
|
||||
@Unique
|
||||
private static final Component SURVIEPOTE_QUIT = Component.literal("Quitter SurviePote");
|
||||
|
||||
// Quitte le monde comme le bouton vanilla, mais renvoie vers l'écran d'accueil
|
||||
// (au lieu de la liste des serveurs pour un serveur distant).
|
||||
@Unique
|
||||
private static void surviepote$quitToTitle(Button button) {
|
||||
button.active = false;
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
// Conserve la gestion vanilla du brouillon de signalement, puis redirige.
|
||||
minecraft.getReportingContext().draftReportHandled(minecraft, minecraft.gui.screen(), () -> {
|
||||
minecraft.disconnectFromWorld(ClientLevel.DEFAULT_QUIT_MESSAGE);
|
||||
minecraft.setScreenAndShow(new TitleScreen());
|
||||
}, true);
|
||||
}
|
||||
|
||||
@Redirect(method = "createPauseMenu",
|
||||
at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/gui/components/Button;builder(Lnet/minecraft/network/chat/Component;Lnet/minecraft/client/gui/components/Button$OnPress;)Lnet/minecraft/client/gui/components/Button$Builder;"))
|
||||
private static Button.Builder surviepote$relabelDisconnect(Component message, Button.OnPress onPress) {
|
||||
// createPauseMenu ne crée que deux boutons via Button.builder : "Retour au jeu"
|
||||
// et "Déconnexion". On ne remplace que ce dernier.
|
||||
if (message.getString().equals(CommonComponents.GUI_DISCONNECT.getString())) {
|
||||
return Button.builder(SURVIEPOTE_QUIT, PauseScreenMixin::surviepote$quitToTitle);
|
||||
}
|
||||
return Button.builder(message, onPress);
|
||||
}
|
||||
}
|
||||
+3
-4
@@ -2,7 +2,6 @@ package fr.surviepote.nosingleplayer.mixin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.components.Button;
|
||||
@@ -13,7 +12,6 @@ import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.screens.ConnectScreen;
|
||||
import net.minecraft.client.gui.screens.TitleScreen;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.multiplayer.TransferState;
|
||||
import net.minecraft.client.multiplayer.resolver.ServerAddress;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import fr.surviepote.nosingleplayer.NoSingleplayer;
|
||||
@@ -86,8 +84,9 @@ public abstract class TitleScreenMixin {
|
||||
|
||||
Button join = Button.builder(Component.literal("Rejoindre SurviePote"), pressed -> {
|
||||
ServerData data = new ServerData("SurviePote", SERVER_HOST, ServerData.Type.OTHER);
|
||||
ConnectScreen.startConnecting(self, minecraft, ServerAddress.parseString(SERVER_HOST), data, false,
|
||||
new TransferState(Map.of(), Map.of(), false));
|
||||
// TransferState null = connexion normale. En passer un déclenche une connexion
|
||||
// de type "transfert", que le serveur refuse ("This server does not accept transfers").
|
||||
ConnectScreen.startConnecting(self, minecraft, ServerAddress.parseString(SERVER_HOST), data, false, null);
|
||||
}).bounds(joinX, joinY, 200, 20).build();
|
||||
((ScreenAccessor) self).surviepote$getRenderables().add(join);
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"TitleScreenRenderMixin",
|
||||
"TitleScreenTextMixin",
|
||||
"RealmsNotificationsMixin",
|
||||
"PauseScreenMixin",
|
||||
"ScreenAccessor"
|
||||
],
|
||||
"injectors": {
|
||||
|
||||
Reference in New Issue
Block a user