Commit graph

5 commits

Author SHA1 Message Date
MiTHRAL
babb887d4b ci: fix init-submodules empty-worktree check (ls -A counts .git)
A submodule with only a .git pointer looks non-empty to ls -A, so the
self-heal skipped every un-checked-out nested submodule. Check for real
worktree content instead (find excluding .git).
2026-08-27 11:53:54 -04:00
MiTHRAL
7173d7e88d releases: local build+upload script, optional Forgejo Actions workflow, docs
Clarifies that releases ship ONLY the recompiled binaries (skate3 +
librexruntime + ghost_relay + README) - never the game files; the game dump
(default.xex + EAWebkit.xex) is required at BUILD TIME for codegen only.

- tools/release/release.sh: builds + packages a per-platform release zip
  (configure -> codegen -> build -> zip), prints a sha256sum, and with
  --upload creates/updates a Forgejo Release and attaches the zip via the
  API (GITEA_TOKEN). Supports linux/windows/macos presets on their native
  hosts.
- .forgejo/workflows/release.yml: optional automation - builds on a
  self-hosted Docker runner (ubuntu-24.04 label), self-heals the broken
  nested submodule pins via tools/ci/init-submodules.sh, and publishes a
  Linux release on v* tags. Needs the game dump mounted on the runner
  (codegen only, never uploaded), SUBMODULE_KEY + RELEASE_TOKEN secrets.
- tools/ci/init-submodules.sh: recursive submodule init that self-heals
  upstream pins a fresh clone can no longer fetch (the rexglue fork pins
  thirdparty/imgui to a commit ocornut/imgui dropped; the script checks out
  the upstream default tip for any nested submodule left empty).
- docs/releases.md: what's in a release, the local path, and the optional
  CI path.
- .gitignore: keep tools/ci + tools/release, ignore local release zips.
2026-08-26 23:32:13 -04:00
MiTHRAL
1763b39eca ghost multiplayer: deployment docs + systemd unit + install script
- docs/ghost-multiplayer.md: the full beta guide - player usage, cvars,
  relay deployment (VPS build/install, free-tunnel option, verification),
  logging/troubleshooting and security notes.
- tools/ghost_relay.service: hardened systemd unit for the public relay
  (Restart=on-failure, NoNewPrivileges, PrivateTmp, ProtectSystem).
- tools/ghost_relay_deploy.sh: one-shot build + install + enable script for
  the VPS (GHOST_RELAY_PORT / GHOST_RELAY_VERBOSE overrides; opens the UDP
  port via ufw). Verified: the exact build line compiles and runs.
- README: multiplayer pointer under 'How Do I Play?'.
2026-08-26 22:21:08 -04:00
MiTHRAL
7a48eb9f35 ghost multiplayer: beta hardening - version handshake, crash-proofing, logging, persistence
Production-readiness pass toward 1.0:

- Protocol handshake: JOIN carries kGhostVersion; a mismatched client is
  REFUSED by the relay (HELLO session 0) and its poses are never forwarded,
  so two builds can never silently corrupt each other's pose stream. The
  client surfaces the refusal in the menu and skips refused LAN hosts during
  discovery.
- Crash-proofing: every received payload is bounds-checked against its
  packet size before parsing (HELLO / PoseChunk / JOIN); both the client
  network thread and the relay thread are exception-guarded (a throw logs
  and keeps the loop alive instead of hitting std::terminate). The relay no
  longer creates client records for unknown-address POSE/LEAVE floods and
  enforces a hard client cap (--max-clients, default 64).
- Logging: rate-limited error logging throughout (send failures, resolve
  failures, refusals, thread exceptions, client-cap drops). The relay core
  uses a build-flag shim (REXLOG in-game, a tiny {} formatter in the
  dependency-free standalone), with --verbose join/leave lines for the
  server. Game crashes themselves are already handled by the SDK's crash
  handlers + file logs; this layer now avoids triggering them and explains
  itself when it can't connect.
- Settings persistence: server/room/name/port/rate save into the app's cvar
  config on change, so a player's multiplayer setup survives a restart.
- Menu: status now shows protocol refusals and the last error.

Tests updated for the handshake (version-refusal case added); all suites
pass.
2026-08-26 22:07:09 -04:00
MiTHRAL
269fbcee32 Add ghost multiplayer: UDP relay + pose broadcasting + placeholder cubes
Bolt-on multiplayer layer confined to src/native and hand-written code (no
codegen output touched):

- GhostRelay core (src/native/skate3_native_ghost_relay.*): small UDP relay
  matching clients into rooms by a shareable code; forwards each client's
  pose to the other room members. Used by both the standalone binary and
  the in-game LAN host fallback.
- Standalone server (tools/ghost_relay_main.cpp, ghost_relay target): runs
  on a public VPS or behind a free tunnel; clients connect OUTBOUND, so no
  port forwarding is needed on any client.
- In-game module (skate3_native_ghost.*): captures the local player's world
  transform at Sk8::UpdateBoneTransforms exit (pack-owner entity +416,
  verified layout) and broadcasts it at a fixed rate; auto-connects to the
  default public relay, falls back to LAN auto-host + UDP broadcast
  discovery when unreachable.
- Renderer: draws a solid-color cube per remote player in RenderScene via
  the existing scene PSO tint.a>0 branch (no new shader/SPIR-V).
- UI: GhostDialog (M key) with enable toggle, room code, relay override,
  status readout. Off by default.

Wire protocol in skate3_native_ghost_proto.h (JOIN/HELLO/POSE/PING/LEAVE).
2026-08-26 20:12:45 -04:00