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).
69 lines
2.1 KiB
C++
69 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#include "generated/skate3_init.h"
|
|
|
|
#include <atomic>
|
|
#include <filesystem>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <set>
|
|
#include <string>
|
|
|
|
#include <rex/rex_app.h>
|
|
#include <rex/ui/overlay/simple_settings_overlay.h>
|
|
|
|
#include "skate3_native_debug_dialog.h"
|
|
#include "skate3_native_ghost_dialog.h"
|
|
|
|
namespace rex::ui {
|
|
class ImGuiDrawer;
|
|
}
|
|
|
|
class Skate3BaseApp : public rex::ReXApp {
|
|
public:
|
|
using rex::ReXApp::ReXApp;
|
|
~Skate3BaseApp() override;
|
|
|
|
protected:
|
|
std::optional<rex::PathConfig> OnFinalizePaths(
|
|
const rex::PathConfig& defaults,
|
|
std::function<void(rex::PathConfig)> resume) override;
|
|
void OnConfigurePaths(rex::PathConfig& paths) override;
|
|
void OnConfigureFonts(ImFontAtlas* atlas) override;
|
|
void OnCreateDialogs(rex::ui::ImGuiDrawer* drawer) override;
|
|
void OnPostSetup() override;
|
|
void OnShutdown() override;
|
|
|
|
private:
|
|
void InstallRecipeOverlay();
|
|
void InstallBigDeviceAliases();
|
|
void InstallDlcPackages();
|
|
void ToggleSimpleSettings();
|
|
void ToggleNativeDebug();
|
|
void ToggleGhost();
|
|
void ApplySettingsCursorMode();
|
|
void ApplyGameplayCursorMode();
|
|
void RestartGame();
|
|
void SaveDrawFingerprintLog();
|
|
void LogUserMarker();
|
|
void LogDebugMarker();
|
|
void ApplySelectedProfileToRuntime();
|
|
|
|
static bool IsRecipeNameChar(char c);
|
|
static std::set<std::string> DiscoverRecipeAliases(
|
|
const std::filesystem::path& content_root);
|
|
static bool CreateOverlayDirectory(const std::filesystem::path& overlay_root,
|
|
std::string_view guest_path);
|
|
|
|
std::filesystem::path config_path_;
|
|
std::filesystem::path user_settings_path_;
|
|
std::filesystem::path profiles_path_;
|
|
std::unique_ptr<rex::ui::SimpleSettingsDialog> simple_settings_dialog_;
|
|
std::unique_ptr<skate3::NativeDebugDialog> native_debug_dialog_;
|
|
std::unique_ptr<skate3::GhostDialog> ghost_dialog_;
|
|
std::unique_ptr<skate3::RenderModeIndicator> render_mode_indicator_;
|
|
bool recipe_overlay_installed_ = false;
|
|
bool big_device_aliases_installed_ = false;
|
|
std::atomic<uint32_t> debug_marker_count_{0};
|
|
};
|