mirror of
https://github.com/bdnugget/rs-sdk.git
synced 2026-11-07 09:07:30 +00:00
fix(hiscores): stamp playtime only when a skill's level changes
Skill and overall rows rewrote playtime on every logout, even with no XP gained. Playtime is the tiebreak (level desc, playtime asc), so maxed players slid down the board for continuing to play. Now playtime records when the current level was reached; XP-only changes still update value. Matches the quest points board. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ab59cc31bf
commit
415491a1cc
2 files changed
+16
-6
No files matched your search
@@ -104,6 +104,13 @@ survival) is described in the project memory; this file is the human-readable ch
|
||||
outfit hiscore write; `/hiscores/outfit` shows a `/sprite/player` image for the top 10 and
|
||||
`/sprite/item` icons (no in-browser viewer bundle). Sprites come from `web/sprites/`
|
||||
(worker hosting webclient `src/viewer/ItemViewer.ts` `renderPlayerSprite`).
|
||||
- [ ] **Hiscore playtime tiebreak** — `hiscore.playtime`/`hiscore_large.playtime` (migration
|
||||
`20260208000000_hiscore_playtime_and_outfit`); boards rank level desc, playtime asc.
|
||||
`LoginServer.ts` `updateHiscores()` stamps playtime only when a row's **level** changes
|
||||
(XP-only changes keep it), so it means "playtime when this level was reached" — restamping
|
||||
on every logout pushed maxed players down for continuing to play. Quest points (type 100,
|
||||
`updateQuestHiscore()`) follows the same rule.
|
||||
Verify: `grep -n "existing.level === totalLevel ? existing.playtime" src/server/login/LoginServer.ts`
|
||||
- [ ] **Worker-thread crash hardening** — `src/server/InternalClient.ts` uses persistent
|
||||
`.on('close'/'error')` handlers instead of `.once()` (a second ws error after a
|
||||
successful open was an unhandled EventEmitter 'error' that killed the worker → every
|
||||
|
||||
@@ -115,15 +115,18 @@ async function updateHiscores(account: HiscoreAccount | undefined, player: Playe
|
||||
totalLevel += player.baseLevels[i];
|
||||
}
|
||||
|
||||
const existing = await db.selectFrom('hiscore_large').select('type').select('value').select('playtime').where('account_id', '=', account.id).where('type', '=', 0).where('profile', '=', profile).executeTakeFirst();
|
||||
if (existing && (existing.value !== totalXp || existing.playtime !== player.playtime)) {
|
||||
// rs-sdk: playtime is the tiebreak (level desc, playtime asc), so it's only stamped when the
|
||||
// level changes - it records when the player reached that level. Restamping it on every
|
||||
// logout pushed maxed players down the board for continuing to play.
|
||||
const existing = await db.selectFrom('hiscore_large').select('type').select('level').select('value').select('playtime').where('account_id', '=', account.id).where('type', '=', 0).where('profile', '=', profile).executeTakeFirst();
|
||||
if (existing && (existing.value !== totalXp || existing.level !== totalLevel)) {
|
||||
await db
|
||||
.updateTable('hiscore_large')
|
||||
.set({
|
||||
type: 0,
|
||||
level: totalLevel,
|
||||
value: totalXp,
|
||||
playtime: player.playtime,
|
||||
playtime: existing.level === totalLevel ? existing.playtime : player.playtime,
|
||||
date: toDbDate(new Date())
|
||||
})
|
||||
.where('account_id', '=', account.id)
|
||||
@@ -153,13 +156,13 @@ async function updateHiscores(account: HiscoreAccount | undefined, player: Playe
|
||||
const hiscoreType = stat + 1;
|
||||
|
||||
// todo: can we upsert in kysely?
|
||||
const existing = await db.selectFrom('hiscore').select('type').select('value').select('playtime').where('account_id', '=', account.id).where('type', '=', hiscoreType).where('profile', '=', profile).executeTakeFirst();
|
||||
if (existing && (existing.value !== player.stats[stat] || existing.playtime !== player.playtime)) {
|
||||
const existing = await db.selectFrom('hiscore').select('type').select('level').select('value').select('playtime').where('account_id', '=', account.id).where('type', '=', hiscoreType).where('profile', '=', profile).executeTakeFirst();
|
||||
if (existing && (existing.value !== player.stats[stat] || existing.level !== player.baseLevels[stat])) {
|
||||
update.push({
|
||||
type: hiscoreType,
|
||||
level: player.baseLevels[stat],
|
||||
value: player.stats[stat],
|
||||
playtime: player.playtime,
|
||||
playtime: existing.level === player.baseLevels[stat] ? existing.playtime : player.playtime,
|
||||
date: toDbDate(new Date())
|
||||
});
|
||||
} else if (!existing) {
|
||||
|
||||
Reference in new issue
Block a user