Fix PR 3 review findings [skip ci]
This commit is contained in:
1 parent
590178e41a
commit
454620f21e
21 files changed
+522
-160
No files matched your search
@@ -392,6 +392,17 @@ pub struct Sync {
|
||||
pub async fn sync(GameServer(server): GameServer, State(state): State<AppState>, Json(s): Json<Sync>) -> AppResult<Json<Value>> {
|
||||
let at_now = now();
|
||||
let mut tx = state.db.begin().await?;
|
||||
let leveling_on = s.features.as_ref().and_then(|f| f.leveling_enabled).unwrap_or(true);
|
||||
let mut xp_before = std::collections::HashMap::new();
|
||||
if !leveling_on {
|
||||
for uuid in s.stats.iter().filter_map(|d| dashed(&d.uuid))
|
||||
.chain(s.events.iter().filter_map(|e| e.uuid.as_deref().and_then(dashed))) {
|
||||
if xp_before.contains_key(&uuid) { continue; }
|
||||
let xp: i64 = sqlx::query_scalar("SELECT global_xp FROM user_levels WHERE uuid = ?")
|
||||
.bind(&uuid).fetch_optional(&mut *tx).await?.unwrap_or(0);
|
||||
xp_before.insert(uuid, xp);
|
||||
}
|
||||
}
|
||||
|
||||
// Record the receipt in the same transaction as the deltas. A response
|
||||
// lost after commit can then be retried without counting activity twice.
|
||||
@@ -476,6 +487,7 @@ pub async fn sync(GameServer(server): GameServer, State(state): State<AppState>,
|
||||
}
|
||||
|
||||
let achievements_on = s.features.as_ref().and_then(|f| f.achievements_enabled).unwrap_or(true);
|
||||
let quests_on = s.features.as_ref().and_then(|f| f.quests_enabled).unwrap_or(true);
|
||||
|
||||
for e in s.events.iter().filter(|_| fresh).take(MAX_EVENTS_PER_SYNC) {
|
||||
let kind = clip(&e.kind, 24).to_ascii_lowercase();
|
||||
@@ -494,8 +506,18 @@ pub async fn sync(GameServer(server): GameServer, State(state): State<AppState>,
|
||||
.bind(&kind)
|
||||
.bind(e.detail.as_deref().map(|d| clip(d, 256)))
|
||||
.bind(at)
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
.execute(&mut *tx)
|
||||
.await?;
|
||||
|
||||
if quests_on && kind == "action" {
|
||||
if let (Some(uuid), Some(detail)) = (e.uuid.as_deref().and_then(dashed), e.detail.as_deref()) {
|
||||
if let Some((action, count)) = detail.rsplit_once(" +") {
|
||||
if let Ok(count) = count.parse::<i64>() {
|
||||
crate::routes::quests::advance_action_quests(&mut tx, &uuid, action, count.clamp(0, 1_000_000), &at_now).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if event unlocks an achievement (if achievements enabled)
|
||||
if achievements_on {
|
||||
@@ -523,7 +545,17 @@ pub async fn sync(GameServer(server): GameServer, State(state): State<AppState>,
|
||||
let mut rewarded = std::collections::HashSet::new();
|
||||
for d in &s.stats { if let Some(uuid) = dashed(&d.uuid) { rewarded.insert(uuid); } }
|
||||
for e in &s.events { if let Some(uuid) = e.uuid.as_deref().and_then(dashed) { rewarded.insert(uuid); } }
|
||||
for uuid in rewarded { crate::routes::leveling::grant_rewards(&mut tx, &uuid, &at_now).await?; }
|
||||
if leveling_on {
|
||||
for uuid in rewarded { crate::routes::leveling::grant_rewards(&mut tx, &uuid, &at_now).await?; }
|
||||
} else {
|
||||
// Achievement unlocks remain enabled, but their trigger must not grant
|
||||
// progression on a server whose leveling module is disabled.
|
||||
for (uuid, xp) in xp_before {
|
||||
let level = crate::routes::leveling::level_from_xp(xp).0;
|
||||
sqlx::query("UPDATE user_levels SET global_xp = ?, global_level = ? WHERE uuid = ?")
|
||||
.bind(xp).bind(level).bind(&uuid).execute(&mut *tx).await?;
|
||||
}
|
||||
}
|
||||
tx.commit().await?;
|
||||
|
||||
// Occasional housekeeping.
|
||||
|
||||
Reference in new issue
Block a user