fix(engine,server): safe area clamp, analytics batch, achievement save order, daily rollover, replay validation, leaderboard opt-in (#56, #60, #61, #62, #66, #68)
Build and Deploy / build-and-push (push) Successful in 3m54s
Build and Deploy / build-and-push (push) Successful in 3m54s
- #66: Clamp safe-area insets to 25% of window height with warn!() on excess - #68: Move fire_flush outside per-event loop in analytics (batch flush once) - #56: Persist progress before marking reward_granted to prevent XP loss on crash - #60: Add DateRolloverTimer + check_date_rollover system for midnight seed refresh - #62: Add validate_header() in replay upload with mode/draw_mode allowlists - #61: Restore two-query leaderboard opt-in check (SELECT then UPDATE); original queries already in .sqlx cache; EXISTS variant would require sqlx prepare Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -9,7 +9,7 @@ use std::sync::Arc;
|
||||
use bevy::prelude::*;
|
||||
use bevy::tasks::AsyncComputeTaskPool;
|
||||
use solitaire_core::game_state::GameMode;
|
||||
use solitaire_data::{matomo_client::MatomoClient, settings::SyncBackend, Settings};
|
||||
use solitaire_data::{Settings, matomo_client::MatomoClient, settings::SyncBackend};
|
||||
|
||||
use crate::events::{AchievementUnlockedEvent, ForfeitEvent, GameWonEvent, NewGameRequestEvent};
|
||||
use crate::resources::{GameStateResource, TokioRuntimeResource};
|
||||
@@ -59,13 +59,13 @@ impl Plugin for AnalyticsPlugin {
|
||||
// refuses to create threads (resource-limited / sandboxed environments).
|
||||
match TokioRuntimeResource::new() {
|
||||
Ok(rt) => {
|
||||
app.insert_resource(rt).add_systems(
|
||||
Update,
|
||||
(on_game_won, on_forfeit, tick_flush_timer),
|
||||
);
|
||||
app.insert_resource(rt)
|
||||
.add_systems(Update, (on_game_won, on_forfeit, tick_flush_timer));
|
||||
}
|
||||
Err(e) => {
|
||||
bevy::log::warn!("analytics_plugin: Tokio runtime unavailable — analytics flush disabled: {e}");
|
||||
bevy::log::warn!(
|
||||
"analytics_plugin: Tokio runtime unavailable — analytics flush disabled: {e}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,9 +96,13 @@ fn on_game_won(
|
||||
let Some(client) = analytics.client.clone() else {
|
||||
return;
|
||||
};
|
||||
let mut any = false;
|
||||
for ev in wins.read() {
|
||||
client.event("Game", "Won", None, Some(ev.score as f64));
|
||||
fire_flush(client.clone(), rt.0.clone());
|
||||
any = true;
|
||||
}
|
||||
if any {
|
||||
fire_flush(client, rt.0.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,9 +114,13 @@ fn on_forfeit(
|
||||
let Some(client) = analytics.client.clone() else {
|
||||
return;
|
||||
};
|
||||
let mut any = false;
|
||||
for _ev in forfeits.read() {
|
||||
client.event("Game", "Forfeit", None, None);
|
||||
fire_flush(client.clone(), rt.0.clone());
|
||||
any = true;
|
||||
}
|
||||
if any {
|
||||
fire_flush(client, rt.0.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +180,11 @@ fn client_for(settings: &Settings) -> Option<Arc<MatomoClient>> {
|
||||
SyncBackend::SolitaireServer { username, .. } => Some(username.clone()),
|
||||
SyncBackend::Local => None,
|
||||
};
|
||||
Some(Arc::new(MatomoClient::new(url, settings.matomo_site_id, uid)))
|
||||
Some(Arc::new(MatomoClient::new(
|
||||
url,
|
||||
settings.matomo_site_id,
|
||||
uid,
|
||||
)))
|
||||
}
|
||||
|
||||
fn fire_flush(client: Arc<MatomoClient>, rt: Arc<tokio::runtime::Runtime>) {
|
||||
|
||||
Reference in New Issue
Block a user