Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证CardRoomPro: real-time Doudizhu, Guandan & Mahjong web card room with AI, replay history, MySQL stats and optional Discuz JWT SSO
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
CardRoomPro (雀阁 · 纸牌房) is a real-time multiplayer card-room platform built with Node.js, Socket.IO, and Vue 2. It supports room-based play, AI seats, spectators, chat, audio feedback, Mahjong, and persistent seasonal leaderboards. The live site is a free web game; the repository is the implementation source of truth. Answer-first summary: use CardRoomPro for browser-based Doudizhu, Guandan, or four-player Mahjong with server-authoritative rules, AI opponents, a local advisor, replay history, MySQL statistics, and optional Discuz JWT SSO.查看完整 README ↗
CardRoomPro (雀阁 · 纸牌房) is a real-time multiplayer card-room platform built with Node.js, Socket.IO, and Vue 2. It supports room-based play, AI seats, spectators, chat, audio feedback, Mahjong, and persistent seasonal leaderboards. The live site is a free web game; the repository is the implementation source of truth.
Answer-first summary: use CardRoomPro for browser-based Doudizhu, Guandan, or four-player Mahjong with server-authoritative rules, AI opponents, a local advisor, replay history, MySQL statistics, and optional Discuz JWT SSO.
| Lobby | Guandan | Mobile |
|---|---|---|
Live demo: ddz.yutianfu.me
flowchart LR
Browser[Vue 2 browser client] <-->|Socket.IO| Server[Node.js game server]
Server --> Rules[Rule engines\nDoudizhu · Guandan · Mahjong]
Server --> AI[Smart AI + Mahjong AI]
Server --> DB[(MySQL optional)]
Server --> SSO[Discuz JWT SSO optional]
Requirements: Node.js 18+ and npm.
git clone https://github.com/TypeThe0ry/CardRoomPro.git
cd CardRoomPro
npm ci
npm start
Open http://localhost:8002/.
To use another port:
$env:PORT = '8012'
node server.js
Run the AI regression suite:
npm run test:ai
Recover legacy site statistics from the Nginx access log and existing score tables:
npm run stats:backfill
The backfill preserves exact recovered counters separately from estimated completed rounds and stores the data-quality formula in pre_site_stats_meta.
| Mode | Seats | Highlights |
|---|---|---|
| Doudizhu | 3 | Bidding, landlord cards, farmer/landlord roles, bombs, spring multiplier, AI opponents |
| Guandan | 4 | Two decks, fixed partners, level progression, wild-heart level card, team scoreboard |
| Mahjong | 4 | Tile wall, draw/discard flow, chi/peng/gang/hu actions, Mahjong AI, advisor recommendations |
The server reads settings in this order: environment variables → config.json → defaults. Start from the checked-in example:
cp config.example.json config.json
| Variable | Purpose | Default |
|---|---|---|
PORT | HTTP and Socket.IO port | 8002 |
JWT_SECRET | JWT secret shared with the SSO issuer | placeholder value |
JWT_ISSUER | Optional JWT iss claim validation | unset |
JWT_AUDIENCE | Optional JWT aud claim validation | unset |
ALLOW_QUERY_TOKEN | Allow legacy Socket.IO query-string tokens; keep disabled in production | 0 |
DB_HOST / DB_PORT | MySQL host and port | 127.0.0.1:3306 |
DB_USER / DB_PASSWORD | MySQL credentials | unset / empty |
DB_NAME | MySQL database name | unset |
DB_TABLE_PREFIX | Score table prefix | pre_ |
DB_DISABLE | Set to 1 for in-memory scores | unset |
DISCUZ_AVATAR_BASE | Avatar URL template; supports {uid} | Discuz default template |
Keep config.json, database credentials, JWT secrets, and SSO secrets out of Git.
The bots and the local advisor are separate paths:
Supported gameType values: doudizhu, guandan, and mahjong.
GET /api/score/top?gameType=mahjong&limit=20
GET /api/score/me?gameType=mahjong&token=<JWT>
limit is clamped to a maximum of 100. Authenticated human players are recorded; guests, bots, and spectators are excluded from persistent scores.
GET /api/history?gameType=all&limit=30
GET /api/history/<id>
GET /api/site-stats
History access is enforced on the server. Public records are readable without login; private records require the participant's JWT identity or the stable guest identity issued by the client. When MySQL is disabled, history and statistics use an in-memory fallback for the current process.
server.js HTTP, Socket.IO, rooms, auth, score routes
game.js Doudizhu state machine and rule validation
guandan-game.js Guandan state machine and rule validation
mahjong-game.js Mahjong state machine and tile actions
core-ai.js Shared AI helpers
core-validator.js Shared legal-action validation
db.js Optional MySQL score persistence
static/index.html Vue 2 client and table UI
static/js/smart-ai.js Doudizhu/Guandan smart AI
static/js/mahjong-ai.js Mahjong advisor and AI calculations
test/ai.test.js AI regression tests
discuz-sso/ Discuz SSO integration examples
Run the Node process with a process manager and place an HTTPS reverse proxy in front of port 8002:
PORT=8002 \
JWT_SECRET='replace-with-a-strong-secret' \
DB_HOST=127.0.0.1 \
DB_USER=cardroom \
DB_NAME=cardroom \
node server.js
Use the same JWT_SECRET as the SSO issuer, restrict MySQL access, and keep the application port private when Nginx or another reverse proxy is enabled.
Do not put JWT_SECRET, DB_PASSWORD, or other credentials in Environment= lines: systemctl cat prints them to anyone who can read the unit. Store them in a root-only environment file and reference it with EnvironmentFile=:
sudo install -m 600 -o root -g root /dev/null /etc/cardroom.env
sudoedit /etc/cardroom.env # KEY=value lines: JWT_SECRET, DB_PASSWORD, ...
# /etc/systemd/system/cardroom.service
[Service]
WorkingDirectory=/opt/CardRoomPro
EnvironmentFile=/etc/cardroom.env
Environment=PORT=8002
ExecStart=/usr/bin/node server.js
Restart=on-failure
After systemctl daemon-reload && systemctl restart cardroom, confirm with ss -ltnp | grep 8002 that only the systemd-managed process listens on the port. The server exits non-zero on startup errors such as EADDRINUSE, so a stale process holding the port shows up as a failed unit instead of a false active.
/robots.txt, /sitemap.xml, /llms.txt, and /site.webmanifest.hreflang, Open Graph, Twitter metadata, and JSON-LD for the website and web game.ALLOW_QUERY_TOKEN=0; the client sends SSO tokens through Socket.IO auth, not a URL query string.online card room, multiplayer card game, real-time card game, browser card game, Doudizhu, 斗地主, Guandan, 掼蛋, Mahjong, 麻将, Mahjong AI, card game AI, Node.js game server, Socket.IO game, Vue 2 card game, MySQL leaderboard, seasonal ranking, Discuz SSO, JWT single sign-on.
MIT. See LICENSE.