feat(launcher): native Windows support
Port the egui launcher to run natively on Windows (no Wine/Proton). The GUI,
launch state machine, config, health/account monitors, and openfut.cfg writing
are unchanged and cross-platform; only the effect layer is branched:
- game_launch: cfg(windows) launch spawns the game executable directly with its
working dir (the version.dll hijack loads from the game dir; no WINEDLLOVERRIDES,
Wine prefix, or licence regen). Requires the launcher to run elevated so the
child inherits admin. Linux Proton path gated cfg(unix).
- arm: cfg(windows) is a no-op (routing is openfut.cfg, written by the client-files
step; no ptrace_scope/DNAT/hosts). Linux arming gated cfg(unix).
- local_services: on Windows LSX/autopatch are in-process (stp-origin_emu.dll +
version.dll hook), so ensure_running reports ready without spawning. Gated the
unix-only CommandExt/process_group.
- preflight: cfg(windows) run() keeps only backend-reachable + hook-config checks.
- config: GameProfile configured()/validate() accept a runner-less Windows profile.
theme: fix a latent cross-platform panic — egui 0.29 keeps a Style per theme, so
set_style only reached the active one and TextStyle::resolve("Hero") panicked when
the other theme rendered. Install the full style into both themes and pin Dark.
Cross-built for x86_64-pc-windows-gnu; Linux build + 75 tests unchanged.
This commit is contained in:
+14
-1
@@ -25,6 +25,7 @@ use crate::config::LauncherConfig;
|
||||
/// Accept only hostname/IP characters. These values come from config fields that
|
||||
/// are ever only IPs or hostnames, so a surprising character is a bug — reject it
|
||||
/// rather than try to escape it into an elevated shell command.
|
||||
#[cfg(unix)]
|
||||
fn safe_host(s: &str) -> anyhow::Result<&str> {
|
||||
let t = s.trim();
|
||||
if t.is_empty() {
|
||||
@@ -41,6 +42,7 @@ fn safe_host(s: &str) -> anyhow::Result<&str> {
|
||||
|
||||
/// Build the privileged arming script. Pure and unit-tested; the effectful part
|
||||
/// ([`arm`]) only validates config and hands this to the elevated runner.
|
||||
#[cfg(unix)]
|
||||
pub(crate) fn arming_script(
|
||||
server: &str,
|
||||
redirector_port: u16,
|
||||
@@ -84,6 +86,7 @@ pub(crate) fn arming_script(
|
||||
/// Human-readable list of what [`arm`] changed, in the order the script applies
|
||||
/// it. Logged by the UI so the user sees exactly what was set — not just that
|
||||
/// "something" ran under `pkexec`.
|
||||
#[cfg(unix)]
|
||||
pub(crate) fn arming_summary(
|
||||
server: &str,
|
||||
redirector_port: u16,
|
||||
@@ -103,6 +106,16 @@ pub(crate) fn arming_summary(
|
||||
/// Arm the client from config, under one elevated prompt. Requires the same
|
||||
/// fields preflight reads; a missing one is a clear error, never a silent
|
||||
/// loopback fallback. Returns the applied changes for the UI to surface.
|
||||
/// On native Windows there is nothing to arm: routing is the `openfut.cfg` the
|
||||
/// client-files step writes into the game directory (read by the version.dll
|
||||
/// hook), and there is no `ptrace_scope`, DNAT, or `/etc/hosts` to set. Returns
|
||||
/// no changes so the launch sequence treats client preparation as satisfied.
|
||||
#[cfg(windows)]
|
||||
pub fn arm(_cfg: &LauncherConfig) -> anyhow::Result<Vec<String>> {
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn arm(cfg: &LauncherConfig) -> anyhow::Result<Vec<String>> {
|
||||
let server = cfg.openfut_server_host.trim();
|
||||
if server.is_empty() {
|
||||
@@ -128,7 +141,7 @@ pub fn arm(cfg: &LauncherConfig) -> anyhow::Result<Vec<String>> {
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(all(test, unix))]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user