most-box 0.1.3 → 0.1.4
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/out/404/index.html +2 -2
- package/out/404.html +2 -2
- package/out/__next.__PAGE__.txt +5 -5
- package/out/__next._full.txt +13 -13
- package/out/__next._head.txt +3 -3
- package/out/__next._index.txt +6 -6
- package/out/__next._tree.txt +2 -2
- package/out/_next/static/chunks/02zzxfop_k6tl.css +1 -0
- package/out/_next/static/chunks/03gsbg0fr00ey.js +1 -0
- package/out/_next/static/chunks/06lttvu7563zo.css +1 -0
- package/out/_next/static/chunks/0fo9-h4knidcz.js +1 -0
- package/out/_next/static/chunks/0hyds~bp.auvh.js +1 -0
- package/out/_next/static/chunks/0i9sfdypwuw8~.js +1 -0
- package/out/_next/static/chunks/{0_0oph_z1az14.js → 0puk.7e.tr2zy.js} +1 -1
- package/out/_next/static/chunks/0s1k6rlwy02c2.js +1 -0
- package/out/_next/static/chunks/0sgltmtk_9s8p.css +1 -0
- package/out/_next/static/chunks/0snehvtvu1n4q.js +1 -0
- package/out/_next/static/chunks/{12nr19.nnn6s3.js → 0t_3xxx4zkerp.js} +2 -2
- package/out/_next/static/chunks/0u38kke9vhobe.js +1 -0
- package/out/_next/static/chunks/0vd4_a5x-wpdh.js +1 -0
- package/out/_next/static/chunks/0xx_10jns1.s7.css +1 -0
- package/out/_next/static/chunks/{0m_5nb6x8qy._.js → 10f-t2n4y1zx8.js} +1 -1
- package/out/_next/static/chunks/13jdyag9a-~kk.js +1 -0
- package/out/_not-found/__next._full.txt +11 -11
- package/out/_not-found/__next._head.txt +3 -3
- package/out/_not-found/__next._index.txt +6 -6
- package/out/_not-found/__next._not-found.__PAGE__.txt +4 -4
- package/out/_not-found/__next._not-found.txt +3 -3
- package/out/_not-found/__next._tree.txt +1 -1
- package/out/_not-found/index.html +2 -2
- package/out/_not-found/index.txt +11 -11
- package/out/admin/__next._full.txt +12 -12
- package/out/admin/__next._head.txt +3 -3
- package/out/admin/__next._index.txt +6 -6
- package/out/admin/__next._tree.txt +1 -1
- package/out/admin/__next.admin.__PAGE__.txt +4 -4
- package/out/admin/__next.admin.txt +3 -3
- package/out/admin/index.html +2 -2
- package/out/admin/index.txt +12 -12
- package/out/app/__next._full.txt +12 -12
- package/out/app/__next._head.txt +3 -3
- package/out/app/__next._index.txt +6 -6
- package/out/app/__next._tree.txt +1 -1
- package/out/app/__next.app.__PAGE__.txt +4 -4
- package/out/app/__next.app.txt +3 -3
- package/out/app/index.html +2 -2
- package/out/app/index.txt +12 -12
- package/out/chat/__next._full.txt +12 -12
- package/out/chat/__next._head.txt +3 -3
- package/out/chat/__next._index.txt +6 -6
- package/out/chat/__next._tree.txt +1 -1
- package/out/chat/__next.chat.__PAGE__.txt +4 -4
- package/out/chat/__next.chat.txt +3 -3
- package/out/chat/index.html +2 -2
- package/out/chat/index.txt +12 -12
- package/out/chat/join/__next._full.txt +12 -12
- package/out/chat/join/__next._head.txt +3 -3
- package/out/chat/join/__next._index.txt +6 -6
- package/out/chat/join/__next._tree.txt +1 -1
- package/out/chat/join/__next.chat.join.__PAGE__.txt +4 -4
- package/out/chat/join/__next.chat.join.txt +3 -3
- package/out/chat/join/__next.chat.txt +3 -3
- package/out/chat/join/index.html +2 -2
- package/out/chat/join/index.txt +12 -12
- package/out/download/__next._full.txt +16 -16
- package/out/download/__next._head.txt +3 -3
- package/out/download/__next._index.txt +6 -6
- package/out/download/__next._tree.txt +2 -2
- package/out/download/__next.download.__PAGE__.txt +6 -6
- package/out/download/__next.download.txt +3 -3
- package/out/download/index.html +2 -2
- package/out/download/index.txt +16 -16
- package/out/game/__next._full.txt +20 -0
- package/out/game/__next._head.txt +5 -0
- package/out/{gandengyan → game}/__next._index.txt +6 -6
- package/out/game/__next._tree.txt +5 -0
- package/out/game/__next.game.__PAGE__.txt +6 -0
- package/out/game/__next.game.txt +5 -0
- package/out/game/gandengyan/__next._full.txt +26 -0
- package/out/game/gandengyan/__next._head.txt +5 -0
- package/out/game/gandengyan/__next._index.txt +9 -0
- package/out/game/gandengyan/__next._tree.txt +6 -0
- package/out/game/gandengyan/__next.game.gandengyan.__PAGE__.txt +10 -0
- package/out/game/gandengyan/__next.game.gandengyan.txt +5 -0
- package/out/game/gandengyan/__next.game.txt +5 -0
- package/out/game/gandengyan/index.html +15 -0
- package/out/game/gandengyan/index.txt +26 -0
- package/out/game/index.html +1 -0
- package/out/game/index.txt +20 -0
- package/out/game/zhajinhua/__next._full.txt +25 -0
- package/out/game/zhajinhua/__next._head.txt +5 -0
- package/out/game/zhajinhua/__next._index.txt +9 -0
- package/out/game/zhajinhua/__next._tree.txt +5 -0
- package/out/game/zhajinhua/__next.game.txt +5 -0
- package/out/game/zhajinhua/__next.game.zhajinhua.__PAGE__.txt +9 -0
- package/out/game/zhajinhua/__next.game.zhajinhua.txt +5 -0
- package/out/game/zhajinhua/index.html +15 -0
- package/out/game/zhajinhua/index.txt +25 -0
- package/out/index.html +2 -2
- package/out/index.txt +13 -13
- package/out/note/__next._full.txt +12 -12
- package/out/note/__next._head.txt +3 -3
- package/out/note/__next._index.txt +6 -6
- package/out/note/__next._tree.txt +1 -1
- package/out/note/__next.note.__PAGE__.txt +4 -4
- package/out/note/__next.note.txt +3 -3
- package/out/note/index.html +2 -2
- package/out/note/index.txt +12 -12
- package/out/ping/__next._full.txt +12 -12
- package/out/ping/__next._head.txt +3 -3
- package/out/ping/__next._index.txt +6 -6
- package/out/ping/__next._tree.txt +1 -1
- package/out/ping/__next.ping.__PAGE__.txt +4 -4
- package/out/ping/__next.ping.txt +3 -3
- package/out/ping/index.html +2 -2
- package/out/ping/index.txt +12 -12
- package/out/web3/__next._full.txt +12 -12
- package/out/web3/__next._head.txt +3 -3
- package/out/web3/__next._index.txt +6 -6
- package/out/web3/__next._tree.txt +1 -1
- package/out/web3/__next.web3.__PAGE__.txt +4 -4
- package/out/web3/__next.web3.txt +3 -3
- package/out/web3/ed25519/__next._full.txt +10 -10
- package/out/web3/ed25519/__next._head.txt +3 -3
- package/out/web3/ed25519/__next._index.txt +6 -6
- package/out/web3/ed25519/__next._tree.txt +1 -1
- package/out/web3/ed25519/__next.web3.ed25519.__PAGE__.txt +2 -2
- package/out/web3/ed25519/__next.web3.ed25519.txt +3 -3
- package/out/web3/ed25519/__next.web3.txt +3 -3
- package/out/web3/ed25519/index.html +1 -1
- package/out/web3/ed25519/index.txt +10 -10
- package/out/web3/index.html +2 -2
- package/out/web3/index.txt +12 -12
- package/out/web3/tools/__next._full.txt +10 -10
- package/out/web3/tools/__next._head.txt +3 -3
- package/out/web3/tools/__next._index.txt +6 -6
- package/out/web3/tools/__next._tree.txt +1 -1
- package/out/web3/tools/__next.web3.tools.__PAGE__.txt +2 -2
- package/out/web3/tools/__next.web3.tools.txt +3 -3
- package/out/web3/tools/__next.web3.txt +3 -3
- package/out/web3/tools/index.html +1 -1
- package/out/web3/tools/index.txt +10 -10
- package/package.json +2 -1
- package/server/index.js +0 -8
- package/server/src/config.js +1 -1
- package/server/src/core/gameRoom.js +222 -0
- package/server/src/core/zhajinhua.js +563 -0
- package/server/src/games/gandengyan.js +348 -411
- package/server/src/http/app.js +7 -1
- package/server/src/index.js +9 -1
- package/out/_next/static/chunks/04mo7rr..0_1q.js +0 -1
- package/out/_next/static/chunks/06rf3qq5ggs6v.js +0 -1
- package/out/_next/static/chunks/07td.jq7xff84.css +0 -1
- package/out/_next/static/chunks/0cl7d~7abnk_p.css +0 -1
- package/out/_next/static/chunks/0d306t1wvjpdx.js +0 -1
- package/out/_next/static/chunks/0n.ayxmsar6e5.js +0 -1
- package/out/_next/static/chunks/0voe1.ttrh84k.css +0 -1
- package/out/_next/static/chunks/0wtf0xsiicxx6.js +0 -1
- package/out/_next/static/chunks/0x.ky97owcxxs.js +0 -1
- package/out/_next/static/chunks/0ysj5b94vu4ri.js +0 -1
- package/out/_next/static/chunks/184hxsuf-5c84.js +0 -1
- package/out/gandengyan/__next._full.txt +0 -25
- package/out/gandengyan/__next._head.txt +0 -5
- package/out/gandengyan/__next._tree.txt +0 -5
- package/out/gandengyan/__next.gandengyan.__PAGE__.txt +0 -10
- package/out/gandengyan/__next.gandengyan.txt +0 -5
- package/out/gandengyan/index.html +0 -15
- package/out/gandengyan/index.txt +0 -25
- /package/out/_next/static/{aPEZ4zaaR5W3WpSZ0dFsa → sSvbBrwXZY-4lBmcHshga}/_buildManifest.js +0 -0
- /package/out/_next/static/{aPEZ4zaaR5W3WpSZ0dFsa → sSvbBrwXZY-4lBmcHshga}/_clientMiddlewareManifest.js +0 -0
- /package/out/_next/static/{aPEZ4zaaR5W3WpSZ0dFsa → sSvbBrwXZY-4lBmcHshga}/_ssgManifest.js +0 -0
package/out/web3/tools/index.txt
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
1:"$Sreact.fragment"
|
|
2
|
-
2:I[14232,["/_next/static/chunks/
|
|
3
|
-
3:I[52925,["/_next/static/chunks/
|
|
4
|
-
4:I[39756,["/_next/static/chunks/
|
|
5
|
-
5:I[37457,["/_next/static/chunks/
|
|
6
|
-
6:I[36768,["/_next/static/chunks/
|
|
7
|
-
8:I[97367,["/_next/static/chunks/
|
|
2
|
+
2:I[14232,["/_next/static/chunks/0puk.7e.tr2zy.js","/_next/static/chunks/0snehvtvu1n4q.js","/_next/static/chunks/0t2xr05rlu96l.js","/_next/static/chunks/10f-t2n4y1zx8.js"],"ErrorBoundary"]
|
|
3
|
+
3:I[52925,["/_next/static/chunks/0puk.7e.tr2zy.js","/_next/static/chunks/0snehvtvu1n4q.js","/_next/static/chunks/0t2xr05rlu96l.js","/_next/static/chunks/10f-t2n4y1zx8.js"],"default"]
|
|
4
|
+
4:I[39756,["/_next/static/chunks/0puk.7e.tr2zy.js","/_next/static/chunks/0snehvtvu1n4q.js","/_next/static/chunks/0t2xr05rlu96l.js","/_next/static/chunks/10f-t2n4y1zx8.js"],"default"]
|
|
5
|
+
5:I[37457,["/_next/static/chunks/0puk.7e.tr2zy.js","/_next/static/chunks/0snehvtvu1n4q.js","/_next/static/chunks/0t2xr05rlu96l.js","/_next/static/chunks/10f-t2n4y1zx8.js"],"default"]
|
|
6
|
+
6:I[36768,["/_next/static/chunks/0puk.7e.tr2zy.js","/_next/static/chunks/0snehvtvu1n4q.js","/_next/static/chunks/0t2xr05rlu96l.js","/_next/static/chunks/10f-t2n4y1zx8.js","/_next/static/chunks/0ao1lbi4b.sfa.js"],"default"]
|
|
7
|
+
8:I[97367,["/_next/static/chunks/0puk.7e.tr2zy.js","/_next/static/chunks/0snehvtvu1n4q.js","/_next/static/chunks/0t2xr05rlu96l.js","/_next/static/chunks/10f-t2n4y1zx8.js"],"OutletBoundary"]
|
|
8
8
|
9:"$Sreact.suspense"
|
|
9
|
-
c:I[97367,["/_next/static/chunks/
|
|
10
|
-
e:I[97367,["/_next/static/chunks/
|
|
11
|
-
10:I[68027,["/_next/static/chunks/
|
|
9
|
+
c:I[97367,["/_next/static/chunks/0puk.7e.tr2zy.js","/_next/static/chunks/0snehvtvu1n4q.js","/_next/static/chunks/0t2xr05rlu96l.js","/_next/static/chunks/10f-t2n4y1zx8.js"],"ViewportBoundary"]
|
|
10
|
+
e:I[97367,["/_next/static/chunks/0puk.7e.tr2zy.js","/_next/static/chunks/0snehvtvu1n4q.js","/_next/static/chunks/0t2xr05rlu96l.js","/_next/static/chunks/10f-t2n4y1zx8.js"],"MetadataBoundary"]
|
|
11
|
+
10:I[68027,["/_next/static/chunks/0puk.7e.tr2zy.js","/_next/static/chunks/0snehvtvu1n4q.js","/_next/static/chunks/0t2xr05rlu96l.js","/_next/static/chunks/10f-t2n4y1zx8.js"],"default",1]
|
|
12
12
|
:HL["/_next/static/chunks/0adx~d-j05c9d.css","style"]
|
|
13
13
|
:HL["/_next/static/chunks/0xdwau5k2augv.css","style"]
|
|
14
14
|
:HL["/_next/static/chunks/0ukyg~tkm~h2m.css","style"]
|
|
15
15
|
:HC["/",""]
|
|
16
|
-
0:{"P":null,"c":["","web3","tools",""],"q":"","i":false,"f":[[["",{"children":["web3",{"children":["tools",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0adx~d-j05c9d.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","link","1",{"rel":"stylesheet","href":"/_next/static/chunks/0xdwau5k2augv.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/
|
|
16
|
+
0:{"P":null,"c":["","web3","tools",""],"q":"","i":false,"f":[[["",{"children":["web3",{"children":["tools",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0adx~d-j05c9d.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","link","1",{"rel":"stylesheet","href":"/_next/static/chunks/0xdwau5k2augv.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/0puk.7e.tr2zy.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/0snehvtvu1n4q.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/_next/static/chunks/0t2xr05rlu96l.js","async":true,"nonce":"$undefined"}],["$","script","script-3",{"src":"/_next/static/chunks/10f-t2n4y1zx8.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"zh-CN","suppressHydrationWarning":true,"data-scroll-behavior":"smooth","children":[["$","head",null,{"children":[["$","meta",null,{"charSet":"UTF-8"}],["$","meta",null,{"name":"viewport","content":"width=device-width, initial-scale=1.0"}],["$","link",null,{"rel":"icon","href":"/favicon.ico"}],["$","meta",null,{"name":"theme-color","content":"#5e6ad2"}],["$","script",null,{"dangerouslySetInnerHTML":{"__html":"\n (function() {\n var theme = localStorage.getItem('theme');\n if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {\n document.documentElement.setAttribute('data-theme', 'dark');\n }\n })();\n "}}]]}],["$","body",null,{"children":["$","$L2",null,{"children":[["$","$L3",null,{}],["$","script",null,{"dangerouslySetInnerHTML":{"__html":"\n window.onerror = function(message, source, lineno, colno, error) {\n console.error('[Global Error]', { message, source, lineno, colno, error });\n };\n window.onunhandledrejection = function(event) {\n console.error('[Unhandled Promise Rejection]', event.reason);\n };\n "}}],["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","$L6",null,{}],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]]}]}]]}]]}],{"children":[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0ukyg~tkm~h2m.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":["$L7",null,["$","$L8",null,{"children":["$","$9",null,{"name":"Next.MetadataOutlet","children":"$@a"}]}]]}],{},null,false,null]},null,false,"$@b"]},null,false,null]},null,false,null],["$","$1","h",{"children":[null,["$","$Lc",null,{"children":"$Ld"}],["$","div",null,{"hidden":true,"children":["$","$Le",null,{"children":["$","$9",null,{"name":"Next.Metadata","children":"$Lf"}]}]}],null]}],false]],"m":"$undefined","G":["$10",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0adx~d-j05c9d.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","link","1",{"rel":"stylesheet","href":"/_next/static/chunks/0xdwau5k2augv.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"sSvbBrwXZY-4lBmcHshga"}
|
|
17
17
|
7:E{"digest":"NEXT_REDIRECT;replace;/web3;307;"}
|
|
18
18
|
11:[]
|
|
19
19
|
b:"$W11"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "most-box",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "MostBox - P2P file sharing application",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "electron/main.js",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"typecheck": "tsc --noEmit",
|
|
29
29
|
"format": "npx prettier --write .",
|
|
30
30
|
"lint": "npx eslint .",
|
|
31
|
+
"r2:cors": "node scripts/configure-r2-cors.mjs",
|
|
31
32
|
"electron:dev": "concurrently \"npm run build\" \"wait-on out/index.html && electron .\"",
|
|
32
33
|
"electron:rebuild": "electron-rebuild -f -w sodium-native",
|
|
33
34
|
"electron:build": "npm run build && npm run electron:rebuild && electron-builder",
|
package/server/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import { fileURLToPath } from 'node:url'
|
|
|
4
4
|
import { WebSocketServer } from 'ws'
|
|
5
5
|
import { serve } from '@hono/node-server'
|
|
6
6
|
import { MostBoxEngine } from './src/index.js'
|
|
7
|
-
import { createGanDengYanSocketHandlers } from './src/games/gandengyan.js'
|
|
8
7
|
import {
|
|
9
8
|
DEFAULT_NODE_HOST,
|
|
10
9
|
DEFAULT_NODE_PORT,
|
|
@@ -133,13 +132,10 @@ function createWebSocketServer({
|
|
|
133
132
|
cleanupWsSubscriptions,
|
|
134
133
|
}) {
|
|
135
134
|
const wss = new WebSocketServer({ noServer: true })
|
|
136
|
-
const ganDengYan = createGanDengYanSocketHandlers()
|
|
137
135
|
|
|
138
136
|
wss.on('connection', ws => {
|
|
139
|
-
ganDengYan.bindClient(ws)
|
|
140
137
|
ws.on('error', () => {})
|
|
141
138
|
ws.on('close', () => {
|
|
142
|
-
ganDengYan.unbindClient(ws)
|
|
143
139
|
cleanupWsSubscriptions(ws)
|
|
144
140
|
})
|
|
145
141
|
ws.on('message', raw => {
|
|
@@ -147,10 +143,6 @@ function createWebSocketServer({
|
|
|
147
143
|
const msg = JSON.parse(raw)
|
|
148
144
|
const { event, data } = msg
|
|
149
145
|
|
|
150
|
-
if (ganDengYan.handleMessage(ws, event, data)) {
|
|
151
|
-
return
|
|
152
|
-
}
|
|
153
|
-
|
|
154
146
|
switch (event) {
|
|
155
147
|
case 'register':
|
|
156
148
|
ws.peerId = data.peerId
|
package/server/src/config.js
CHANGED
|
@@ -48,7 +48,7 @@ export const SWARM_BOOTSTRAP = [
|
|
|
48
48
|
]
|
|
49
49
|
|
|
50
50
|
export const CHANNEL_NAME_MIN_LENGTH = 3
|
|
51
|
-
export const CHANNEL_NAME_MAX_LENGTH =
|
|
51
|
+
export const CHANNEL_NAME_MAX_LENGTH = 30
|
|
52
52
|
export const CHANNEL_NAME_REGEX = /^[a-zA-Z0-9_-]+$/
|
|
53
53
|
export const CHANNEL_NAME_PREFIX = 'most-box-room-'
|
|
54
54
|
export const CHANNEL_MESSAGE_LIMIT = 100
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
export const GAME_CHANNEL_TYPE = 'game'
|
|
2
|
+
export const GAME_EVENT_KIND = 'mostbox.game.event'
|
|
3
|
+
export const GAME_EVENT_VERSION = 1
|
|
4
|
+
|
|
5
|
+
export const GAME_IDS = ['gandengyan', 'zhajinhua']
|
|
6
|
+
|
|
7
|
+
const ROOM_CODE_ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'
|
|
8
|
+
|
|
9
|
+
export function normalizeGameId(input) {
|
|
10
|
+
const value = String(input || '').trim().toLowerCase()
|
|
11
|
+
return GAME_IDS.includes(value) ? value : ''
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function normalizeGameRoomCode(input) {
|
|
15
|
+
return String(input || '')
|
|
16
|
+
.trim()
|
|
17
|
+
.toUpperCase()
|
|
18
|
+
.replace(/[^A-Z0-9]/g, '')
|
|
19
|
+
.slice(0, 8)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function isValidGameRoomCode(input) {
|
|
23
|
+
return /^[A-Z0-9]{4,8}$/.test(String(input || ''))
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createGameRoomCode() {
|
|
27
|
+
let code = ''
|
|
28
|
+
for (let i = 0; i < 6; i++) {
|
|
29
|
+
code += ROOM_CODE_ALPHABET[randomInt(ROOM_CODE_ALPHABET.length)]
|
|
30
|
+
}
|
|
31
|
+
return code
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function gameRoomCodeToChannelName(gameId, roomCode) {
|
|
35
|
+
const normalizedGameId = normalizeGameId(gameId)
|
|
36
|
+
const code = normalizeGameRoomCode(roomCode)
|
|
37
|
+
if (!normalizedGameId || !isValidGameRoomCode(code)) return ''
|
|
38
|
+
return `game-${normalizedGameId}-${code.toLowerCase()}`
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function channelNameToGameRoom(input) {
|
|
42
|
+
const value = String(input || '').trim().toLowerCase()
|
|
43
|
+
const match = /^game-([a-z0-9]+)-([a-z0-9]+)$/.exec(value)
|
|
44
|
+
if (!match) return null
|
|
45
|
+
const gameId = normalizeGameId(match[1])
|
|
46
|
+
const roomCode = normalizeGameRoomCode(match[2])
|
|
47
|
+
if (!gameId || !isValidGameRoomCode(roomCode)) return null
|
|
48
|
+
return { gameId, roomCode }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function createGameEvent({ gameId, roomCode, event, payload }) {
|
|
52
|
+
const normalizedGameId = normalizeGameId(gameId)
|
|
53
|
+
const code = normalizeGameRoomCode(roomCode)
|
|
54
|
+
return {
|
|
55
|
+
kind: GAME_EVENT_KIND,
|
|
56
|
+
version: GAME_EVENT_VERSION,
|
|
57
|
+
gameId: normalizedGameId,
|
|
58
|
+
roomCode: code,
|
|
59
|
+
event: String(event || ''),
|
|
60
|
+
eventId: createEventId(normalizedGameId || 'game'),
|
|
61
|
+
payload: payload || {},
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function parseGameEvent(content, options = {}) {
|
|
66
|
+
try {
|
|
67
|
+
const event = JSON.parse(String(content || ''))
|
|
68
|
+
if (
|
|
69
|
+
!event ||
|
|
70
|
+
event.kind !== GAME_EVENT_KIND ||
|
|
71
|
+
event.version !== GAME_EVENT_VERSION ||
|
|
72
|
+
typeof event.event !== 'string' ||
|
|
73
|
+
typeof event.eventId !== 'string'
|
|
74
|
+
) {
|
|
75
|
+
return null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const gameId = normalizeGameId(event.gameId)
|
|
79
|
+
const roomCode = normalizeGameRoomCode(event.roomCode)
|
|
80
|
+
if (!gameId || !isValidGameRoomCode(roomCode)) return null
|
|
81
|
+
if (options.gameId && gameId !== normalizeGameId(options.gameId)) return null
|
|
82
|
+
if (
|
|
83
|
+
options.roomCode &&
|
|
84
|
+
roomCode !== normalizeGameRoomCode(options.roomCode)
|
|
85
|
+
) {
|
|
86
|
+
return null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
...event,
|
|
91
|
+
gameId,
|
|
92
|
+
roomCode,
|
|
93
|
+
payload:
|
|
94
|
+
event.payload && typeof event.payload === 'object'
|
|
95
|
+
? event.payload
|
|
96
|
+
: {},
|
|
97
|
+
}
|
|
98
|
+
} catch {
|
|
99
|
+
return null
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function deriveGameRoomLobby(messages = [], options = {}) {
|
|
104
|
+
const players = []
|
|
105
|
+
const playerMap = new Map()
|
|
106
|
+
let hostAddress = ''
|
|
107
|
+
|
|
108
|
+
for (const message of sortMessages(messages)) {
|
|
109
|
+
const event = parseGameEvent(message.content, options)
|
|
110
|
+
if (!event) continue
|
|
111
|
+
|
|
112
|
+
if (event.event === 'room:create') {
|
|
113
|
+
const player = createPlayerFromPayload(event.payload?.player, message.author)
|
|
114
|
+
if (!player) continue
|
|
115
|
+
if (!hostAddress) hostAddress = player.address
|
|
116
|
+
upsertPlayer(players, playerMap, player)
|
|
117
|
+
continue
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (event.event === 'player:join') {
|
|
121
|
+
const player = createPlayerFromPayload(event.payload?.player, message.author)
|
|
122
|
+
if (player) upsertPlayer(players, playerMap, player)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
gameId: normalizeGameId(options.gameId),
|
|
128
|
+
roomCode: normalizeGameRoomCode(options.roomCode),
|
|
129
|
+
hostAddress,
|
|
130
|
+
players,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function getLatestGameState(messages = [], options = {}) {
|
|
135
|
+
let latest = null
|
|
136
|
+
for (const message of sortMessages(messages)) {
|
|
137
|
+
const event = parseGameEvent(message.content, options)
|
|
138
|
+
if (!event) continue
|
|
139
|
+
if (event.event !== 'room:state') continue
|
|
140
|
+
const seq = Number(event.payload?.seq || 0)
|
|
141
|
+
if (!latest || seq >= Number(latest.payload?.seq || 0)) {
|
|
142
|
+
latest = event
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return latest
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function createPlayerFromPayload(input, author) {
|
|
149
|
+
if (!input || typeof input !== 'object') return null
|
|
150
|
+
const address = normalizeAddress(input.address || author)
|
|
151
|
+
if (!address || normalizeAddress(author) !== address) return null
|
|
152
|
+
const name = String(input.name || '').trim().slice(0, 50) || shortAddress(address)
|
|
153
|
+
const publicKey = String(input.publicKey || '').trim()
|
|
154
|
+
return {
|
|
155
|
+
address,
|
|
156
|
+
name,
|
|
157
|
+
publicKey,
|
|
158
|
+
joinedAt: Number(input.joinedAt || Date.now()),
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function normalizeGamePlayer(input) {
|
|
163
|
+
if (!input || typeof input !== 'object') return null
|
|
164
|
+
const address = normalizeAddress(input.address)
|
|
165
|
+
if (!address) return null
|
|
166
|
+
return {
|
|
167
|
+
...input,
|
|
168
|
+
address,
|
|
169
|
+
name: String(input.name || shortAddress(address)).slice(0, 50),
|
|
170
|
+
publicKey: String(input.publicKey || ''),
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function normalizeAddress(value) {
|
|
175
|
+
const address = String(value || '').trim()
|
|
176
|
+
return /^0x[a-fA-F0-9]{40}$/.test(address) ? address.toLowerCase() : ''
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function upsertPlayer(players, playerMap, player) {
|
|
180
|
+
const existing = playerMap.get(player.address)
|
|
181
|
+
if (existing) {
|
|
182
|
+
Object.assign(existing, player)
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
players.push(player)
|
|
186
|
+
playerMap.set(player.address, player)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function sortMessages(messages) {
|
|
190
|
+
return [...messages].sort(
|
|
191
|
+
(a, b) => Number(a.timestamp || 0) - Number(b.timestamp || 0)
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function createEventId(prefix) {
|
|
196
|
+
return `${prefix}_${Date.now()}_${randomHex(4)}`
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function randomInt(max) {
|
|
200
|
+
if (globalThis.crypto?.getRandomValues) {
|
|
201
|
+
const value = new Uint32Array(1)
|
|
202
|
+
globalThis.crypto.getRandomValues(value)
|
|
203
|
+
return value[0] % max
|
|
204
|
+
}
|
|
205
|
+
return Math.floor(Math.random() * max)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function randomHex(byteLength) {
|
|
209
|
+
const bytes = new Uint8Array(byteLength)
|
|
210
|
+
if (globalThis.crypto?.getRandomValues) {
|
|
211
|
+
globalThis.crypto.getRandomValues(bytes)
|
|
212
|
+
} else {
|
|
213
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
214
|
+
bytes[i] = Math.floor(Math.random() * 256)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return [...bytes].map(byte => byte.toString(16).padStart(2, '0')).join('')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function shortAddress(address) {
|
|
221
|
+
return address ? `${address.slice(0, 6)}...${address.slice(-4)}` : ''
|
|
222
|
+
}
|