@dotrino/lobby 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dotrino/lobby",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Lobby + matchmaking reciclable para juegos del ecosistema Dotrino: salas, asientos, espectadores, motor de turnos autoritativo, reputación y contactos sobre el proxy/identity/reputation compartidos",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -18,7 +18,8 @@
18
18
  "LICENSE"
19
19
  ],
20
20
  "scripts": {
21
- "test": "node --test"
21
+ "test": "node --test",
22
+ "type-check": "tsc --noEmit"
22
23
  },
23
24
  "keywords": [
24
25
  "lobby",
@@ -32,7 +33,7 @@
32
33
  ],
33
34
  "peerDependencies": {
34
35
  "@dotrino/identity": ">=0.5.0",
35
- "@dotrino/proxy-client": "^0.10.0",
36
+ "@dotrino/proxy-client": ">=0.13.1",
36
37
  "@dotrino/reputation": ">=0.3.0"
37
38
  },
38
39
  "peerDependenciesMeta": {
@@ -45,5 +46,9 @@
45
46
  "repository": {
46
47
  "type": "git",
47
48
  "url": "git+https://github.com/imdotrino/dotrino-lobby.git"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^22.0.0",
52
+ "typescript": "5.9.3"
48
53
  }
49
54
  }
package/src/lobby.js CHANGED
@@ -118,7 +118,9 @@ export class Lobby extends Emitter {
118
118
  return new Promise((resolve) => {
119
119
  const got = new Map()
120
120
  let timer = null
121
- const done = () => { if (timer) clearTimeout(timer); this._infoCollector = null; resolve([...got.values()]) }
121
+ // Ordenado por token: el orden de llegada de las respuestas es una carrera
122
+ // de red y cambia en cada pasada; quien liste tiene que ver siempre lo mismo.
123
+ const done = () => { if (timer) clearTimeout(timer); this._infoCollector = null; resolve([...got.values()].sort((a, b) => String(a.roomId || '').localeCompare(String(b.roomId || '')))) }
122
124
  if (!tokens.length) return done()
123
125
  this._infoCollector = (from, summary) => { if (summary) got.set(from, summary); if (got.size >= tokens.length) done() }
124
126
  for (const t of tokens) this._sendTo(t, K.INFO_REQUEST, {})
package/src/reputation.js CHANGED
@@ -52,9 +52,13 @@ export async function rankRooms (rooms, { reputation, contacts, preferContacts =
52
52
  const isContact = !!(contacts && room.hostPubkey && [...contacts].some(c => samePubkey(c, room.hostPubkey)))
53
53
  return { ...room, reputation: rep, hostScore: rep && rep.score != null ? rep.score : 0, isContact }
54
54
  }))
55
+ // El desempate por roomId NO es cosmético: sin él, dos salas con el mismo
56
+ // score quedan en el orden en que contestaron al INFO (una carrera de red que
57
+ // sale distinta cada vez), así que la lista pública bailaba en cada refresco.
55
58
  enriched.sort((a, b) => {
56
59
  if (preferContacts && a.isContact !== b.isContact) return a.isContact ? -1 : 1
57
- return b.hostScore - a.hostScore
60
+ if (b.hostScore !== a.hostScore) return b.hostScore - a.hostScore
61
+ return String(a.roomId || '').localeCompare(String(b.roomId || ''))
58
62
  })
59
63
  return enriched
60
64
  }