feat(web): add solitaire_web Bevy WASM build targeting play.html canvas
Build and Deploy / build-and-push (push) Failing after 58s

Adds a new `solitaire_web` crate that compiles the full `solitaire_engine`
to `wasm32-unknown-unknown` and renders to a `<canvas id="bevy-canvas">`
element in `play.html` — the same ECS code path as desktop and Android.

Changes to enable the WASM target:
- .cargo/config.toml: add wasm32-unknown-unknown rustflags for getrandom
- Workspace Cargo.toml: add solitaire_web member
- solitaire_data/Cargo.toml: gate tokio/reqwest/dirs/keyring to non-wasm
- solitaire_data/src: add wasm32 branch to data_dir() (returns None);
  cfg-gate sync_client network types, auth_tokens, matomo_client
- solitaire_engine/Cargo.toml: gate tokio/reqwest/kira/arboard/dirs/zip
  to non-wasm (mio/cpal/arboard don't compile for wasm32-unknown-unknown)
- solitaire_engine/src/lib.rs: cfg-gate module declarations and re-exports
  for analytics, audio, sync, sync_setup, avatar, leaderboard plugins
- solitaire_engine/src/core_game_plugin.rs: cfg-gate plugin registrations
  that require TokioRuntime (audio, sync, analytics, leaderboard, avatar)
- solitaire_engine/src/resources.rs: cfg-gate TokioRuntimeResource
- solitaire_engine/src/game_plugin.rs: cfg-gate std::fs::remove_file (x10)
- solitaire_engine/src/theme/mod.rs: cfg-gate importer module (uses dirs+zip)
- solitaire_engine/src/settings_plugin.rs: cfg-gate theme ZIP import UI
- solitaire_engine/src/assets/sources.rs: cfg-gate FileAssetReader/user_theme_dir
- solitaire_engine/src/auto_complete_plugin.rs: cfg-gate audio system
- solitaire_engine/src/daily_challenge_plugin.rs: cfg-gate server fetch
- solitaire_engine/src/hud_plugin.rs: cfg-gate AvatarResource import
- solitaire_engine/src/profile_plugin.rs: cfg-gate AvatarResource import
- solitaire_server/web/play.html: minimal HTML canvas shell
- solitaire_web/: new crate (Cargo.toml + src/lib.rs)
- build_wasm.sh: add Bevy WASM build step (cargo + wasm-bindgen + wasm-opt)

All tests pass; clippy --workspace -- -D warnings clean; native build
(solitaire_engine, solitaire_app) unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-01 13:46:45 -07:00
parent 9260ca7994
commit 835a48fe9d
23 changed files with 573 additions and 51 deletions
+42
View File
@@ -0,0 +1,42 @@
//! Browser entry point for the Ferrous Solitaire Bevy WASM build.
//!
//! This crate compiles the full `solitaire_engine` to `wasm32-unknown-unknown`
//! and renders to a `<canvas id="bevy-canvas">` element. It shares the same
//! ECS code path as the desktop and Android builds; the only differences are:
//! - Audio, sync, and analytics plugins are cfg-gated out in `CoreGamePlugin`
//! on the wasm32 target (see `solitaire_engine/src/core_game_plugin.rs`).
//! - `LocalOnlyProvider` is passed as the sync provider (sync is disabled).
//! - Storage is handled automatically by `WasmStorage` (localStorage-backed),
//! wired by `CoreGamePlugin` via `default_storage_backend()`.
use bevy::prelude::*;
use bevy::window::{Window, WindowPlugin};
use solitaire_data::LocalOnlyProvider;
use solitaire_engine::CoreGamePlugin;
use wasm_bindgen::prelude::*;
#[wasm_bindgen(start)]
pub fn start() {
console_error_panic_hook::set_once();
App::new()
.add_plugins(
DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
// Bind to the existing <canvas id="bevy-canvas"> in play.html.
// Without this, Bevy appends its own canvas to <body>.
canvas: Some("#bevy-canvas".into()),
// Let CSS size the canvas; Bevy follows the element's size.
fit_canvas_to_parent: true,
// Prevent the browser stealing keyboard events and scroll.
prevent_default_event_handling: true,
..default()
}),
..default()
}),
)
// LocalOnlyProvider disables cloud sync — correct for the web build
// since SyncPlugin is cfg-gated out on wasm32 anyway.
.add_plugins(CoreGamePlugin::new(Box::new(LocalOnlyProvider)))
.run();
}