update mg1 and lobbya and B

This commit is contained in:
2026-06-27 05:28:21 +00:00
parent 2e20e87b45
commit cc9bc8dbf3
14 changed files with 4088 additions and 855 deletions
+55
View File
@@ -53,6 +53,8 @@
<a href="/Admin/justice-git.html" class="btn btn-ghost" style="text-decoration:none;margin-right:0.35rem;">อัป Git (justice)</a>
<a href="/gamelog/" target="_blank" rel="noopener noreferrer" class="btn btn-ghost" style="text-decoration:none;margin-right:0.35rem;">📊 Game Log</a>
<a href="/testcase/" target="_blank" rel="noopener noreferrer" class="btn btn-ghost" style="text-decoration:none;margin-right:0.35rem;">🐞 Test Case</a>
<button type="button" id="btn-lobby-dbg-hud" class="btn btn-ghost" style="margin-right:0.35rem;" title="เปิด/ปิด HUD โหลด LobbyA (Iron Man) ให้ผู้เล่นเห็น — dev เปิดเครื่องตัวเองด้วย ?dbg=1 ได้เสมอ">🔧 Lobby HUD: …</button>
<span id="capacity-indicator" class="btn btn-ghost" style="margin-right:0.35rem;cursor:default;border-color:#2b3a4a;" title="ผู้ใช้ออนไลน์ตอนนี้ เทียบเพดานความจุ (สบาย ≤300 · เริ่มหนัก ≥500) — ประเมินจาก 2 vCPU / socket fan-out">👥 …</span>
<span class="admin-user" id="admin-user-label"></span>
<button type="button" class="btn btn-ghost btn-logout" id="btn-logout">ออกจากระบบ</button>
</div>
@@ -1288,5 +1290,58 @@
</main>
</div>
<script src="admin.js?v=87"></script>
<script>
/* toggle: เปิด/ปิด HUD โหลด LobbyA (Iron Man) ให้ "ผู้เล่นทั่วไป" เห็น (เก็บใน game-timing.json: lobbyDebugHud)
— dev เปิดเครื่องตัวเองได้เสมอด้วย ?dbg=1 หรือ localStorage.lobbyDbg='1' โดยไม่ต้องใช้ปุ่มนี้ */
(function () {
var btn = document.getElementById('btn-lobby-dbg-hud');
if (!btn) return;
var GT = '/Game/api/game-timing';
function render(on) { btn.textContent = '🔧 Lobby HUD: ' + (on ? 'ON' : 'OFF'); btn.dataset.on = on ? '1' : '0'; btn.style.borderColor = on ? '#37e0ff' : ''; btn.style.color = on ? '#9fe8ff' : ''; }
function load() {
fetch(GT + '?_=' + Date.now(), { credentials: 'include', cache: 'no-store' })
.then(function (r) { return r.json(); })
.then(function (j) { render(!!(j && j.lobbyDebugHud)); })
.catch(function () { btn.textContent = '🔧 Lobby HUD: ?'; });
}
btn.addEventListener('click', function () {
var next = btn.dataset.on !== '1';
btn.textContent = '🔧 …';
fetch(GT, { method: 'PUT', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ lobbyDebugHud: next }) })
.then(function () { load(); })
.catch(function () { btn.textContent = '🔧 Lobby HUD: error'; });
});
load();
})();
/* ===== ตัวบ่งชี้ความจุ: ผู้ใช้ออนไลน์ตอนนี้ เทียบเพดาน (poll ทุก 10 วิ) ===== */
(function () {
var el = document.getElementById('capacity-indicator');
if (!el) return;
function paint() {
fetch('/Game/api/system-stats', { cache: 'no-store' })
.then(function (r) { return r.json(); })
.then(function (s) {
if (!s || !s.online) { el.innerHTML = '👥 —'; return; }
var p = s.online.players || 0, rooms = s.online.rooms || 0, sockets = s.online.sockets || 0;
var comf = (s.capacity && s.capacity.comfortable) || 300;
var strain = (s.capacity && s.capacity.strain) || 500;
var color, label;
if (p >= strain) { color = '#ff5a5a'; label = 'หนัก'; }
else if (p >= comf) { color = '#ffcc4d'; label = 'เริ่มหนัก'; }
else { color = '#4ade80'; label = 'สบาย'; }
var cpu = (s.cpu && s.cpu.loadPercent != null) ? s.cpu.loadPercent : ((s.cpu && s.cpu.percent) || 0);
el.innerHTML = '👥 <b style="color:' + color + '">' + p + '</b> / ' + strain + ' · ' + label;
el.style.borderColor = color;
el.title = 'ผู้เล่นออนไลน์: ' + p + ' คน · ห้อง: ' + rooms + ' · socket: ' + sockets
+ '\nเพดาน: สบาย ≤' + comf + ' · เริ่มหนัก ≥' + strain + ' (2 vCPU)'
+ '\nCPU load: ' + cpu + '% · RAM: ' + ((s.mem && s.mem.usedPercent) || 0) + '%';
})
.catch(function () { el.innerHTML = '👥 —'; });
}
paint();
setInterval(paint, 10000);
})();
</script>
</body>
</html>
+129 -53
View File
@@ -51,9 +51,9 @@
"providerUserId": "p_1775109142385_wq7wfy1p32j",
"notes": "auto: player-coins",
"blocked": false,
"coins": 2140,
"coins": 2256,
"createdAt": "2026-04-02T05:52:21+00:00",
"updatedAt": "2026-06-26T10:25:41+00:00",
"updatedAt": "2026-06-26T18:19:28+00:00",
"daily": {
"anchorMs": 1781197200000,
"claimedDays": [
@@ -67,13 +67,13 @@
],
"lockUntilMs": 0
},
"score": 86,
"score": 192,
"scoreByCase": {
"1": 16,
"10": 562,
"1": 26,
"10": 616,
"8": 296,
"11": 20,
"13": 234,
"13": 268,
"14": 30,
"9": 40,
"12": 408,
@@ -83,7 +83,7 @@
"7": 6,
"3": 142,
"6": 44,
"2": 90
"2": 98
},
"lbName": "Q",
"achievements": {
@@ -102,33 +102,36 @@
"providerUserId": "p_1775128666204_xzgg2n6x8h",
"notes": "auto: player-coins",
"blocked": false,
"coins": 86,
"coins": 165,
"createdAt": "2026-04-02T11:17:46+00:00",
"updatedAt": "2026-06-24T12:38:24+00:00",
"lobbyColorThemeIndex": 4,
"lobbySkinToneIndex": 2,
"updatedAt": "2026-06-26T12:12:46+00:00",
"lobbyColorThemeIndex": 1,
"lobbySkinToneIndex": 3,
"daily": {
"anchorMs": 1782234000000,
"claimedDays": [
true,
false,
true,
false,
false,
false,
false,
false
],
"lockUntilMs": 1782320400000
"lockUntilMs": 1782493200000
},
"score": 76,
"score": 140,
"scoreByCase": {
"6": 18,
"6": 30,
"13": 50,
"5": 8
"5": 8,
"12": 6,
"10": 36,
"3": 10
},
"lbName": "OHM",
"achievements": {
"d1_minigame_solver": 10,
"d1_minigame_solver": 19,
"a1_first_deduction": 1,
"a5_truth_hunter": 1
}
@@ -226,9 +229,9 @@
"providerUserId": "p_1780400804441_lsc3lqqvs0i",
"notes": "auto: player-coins",
"blocked": false,
"coins": 135,
"coins": 193,
"createdAt": "2026-06-02T11:46:46+00:00",
"updatedAt": "2026-06-24T12:38:36+00:00",
"updatedAt": "2026-06-26T12:12:46+00:00",
"daily": {
"anchorMs": 1781802000000,
"claimedDays": [
@@ -240,24 +243,26 @@
false,
false
],
"lockUntilMs": 1782320400000
"lockUntilMs": 0
},
"score": 90,
"score": 148,
"scoreByCase": {
"1": 4,
"7": 2,
"10": 26,
"6": 20,
"10": 52,
"6": 24,
"13": 32,
"5": 6
"5": 6,
"12": 10,
"3": 18
},
"lbName": "Pear",
"achievements": {
"d1_minigame_solver": 17,
"d1_minigame_solver": 20,
"a1_first_deduction": 1,
"a5_truth_hunter": 2
},
"lobbyColorThemeIndex": 6,
"lobbyColorThemeIndex": 8,
"lobbySkinToneIndex": 3
},
{
@@ -295,17 +300,22 @@
"providerUserId": "p_1781849622720_33zppelly7r",
"notes": "auto: player-coins",
"blocked": false,
"coins": 12,
"coins": 40,
"createdAt": "2026-06-19T06:13:44+00:00",
"updatedAt": "2026-06-19T07:10:26+00:00",
"score": 12,
"updatedAt": "2026-06-26T12:12:46+00:00",
"score": 40,
"scoreByCase": {
"1": 12
"1": 12,
"10": 6,
"6": 10,
"3": 12
},
"lbName": "Nutty",
"achievements": {
"d1_minigame_solver": 3
}
"d1_minigame_solver": 10
},
"lobbyColorThemeIndex": 7,
"lobbySkinToneIndex": 2
},
{
"id": "71f99e98ffa2e824b225af7c",
@@ -315,9 +325,9 @@
"providerUserId": "p_1781849642042_x2vt68wscm",
"notes": "auto: player-coins",
"blocked": false,
"coins": 136,
"coins": 148,
"createdAt": "2026-06-19T06:14:02+00:00",
"updatedAt": "2026-06-19T07:49:00+00:00",
"updatedAt": "2026-06-26T12:12:46+00:00",
"daily": {
"anchorMs": 1781802000000,
"claimedDays": [
@@ -329,18 +339,20 @@
false,
false
],
"lockUntilMs": 1781888400000
"lockUntilMs": 0
},
"score": 126,
"score": 138,
"scoreByCase": {
"1": 66,
"7": 10,
"5": 10,
"2": 40
"2": 40,
"6": 10,
"3": 2
},
"lbName": "tomato",
"achievements": {
"d1_minigame_solver": 14
"d1_minigame_solver": 18
}
},
{
@@ -651,20 +663,21 @@
"providerUserId": "p_1782016990238_0u37bv7pxlxs",
"notes": "auto: player-coins",
"blocked": false,
"coins": 368,
"coins": 510,
"createdAt": "2026-06-21T04:43:11+00:00",
"updatedAt": "2026-06-26T09:44:40+00:00",
"lobbyColorThemeIndex": 8,
"updatedAt": "2026-06-26T18:36:24+00:00",
"lobbyColorThemeIndex": 5,
"lobbySkinToneIndex": 1,
"score": 338,
"score": 470,
"scoreByCase": {
"13": 82,
"10": 172,
"13": 130,
"10": 238,
"6": 8,
"8": 20,
"2": 36,
"2": 46,
"3": 10,
"7": 10
"7": 10,
"1": 8
},
"lbName": "MONE",
"achievements": {
@@ -824,22 +837,37 @@
"providerUserId": "p_1782300287206_l5omneu1yeo",
"notes": "auto: player-coins",
"blocked": false,
"coins": 56,
"coins": 104,
"createdAt": "2026-06-24T11:24:48+00:00",
"updatedAt": "2026-06-24T12:38:36+00:00",
"lobbyColorThemeIndex": 7,
"updatedAt": "2026-06-26T12:12:46+00:00",
"lobbyColorThemeIndex": 3,
"lobbySkinToneIndex": 2,
"score": 56,
"score": 94,
"scoreByCase": {
"6": 14,
"6": 24,
"13": 26,
"5": 16
"5": 16,
"12": 8,
"3": 20
},
"lbName": "Nam",
"achievements": {
"d1_minigame_solver": 11,
"d1_minigame_solver": 17,
"a1_first_deduction": 1,
"a5_truth_hunter": 1
},
"daily": {
"anchorMs": 1782406800000,
"claimedDays": [
true,
false,
false,
false,
false,
false,
false
],
"lockUntilMs": 1782493200000
}
},
{
@@ -909,6 +937,54 @@
"achievements": {
"d1_minigame_solver": 9
}
},
{
"id": "e703a22c23c4152df9c12bdb",
"email": "",
"displayName": "Guest",
"loginType": "guest",
"providerUserId": "p_1782472333150_uuc91mrf9r8",
"notes": "auto: player-coins",
"blocked": false,
"coins": 0,
"createdAt": "2026-06-26T11:12:13+00:00",
"updatedAt": "2026-06-26T11:12:13+00:00"
},
{
"id": "bc0df0c0af13306a95e5359b",
"email": "",
"displayName": "MOOKIZ",
"loginType": "guest",
"providerUserId": "p_1782472374020_hlha51h8q2m",
"notes": "auto: player-coins",
"blocked": false,
"coins": 56,
"createdAt": "2026-06-26T11:12:52+00:00",
"updatedAt": "2026-06-26T12:12:46+00:00",
"lobbyColorThemeIndex": 6,
"lobbySkinToneIndex": 3,
"score": 56,
"scoreByCase": {
"10": 32,
"6": 8,
"3": 16
},
"lbName": "MOOKIZ",
"achievements": {
"d1_minigame_solver": 7
}
},
{
"id": "fcb97fd6e205c5ef88b7376c",
"email": "",
"displayName": "Guest",
"loginType": "guest",
"providerUserId": "p_1782472855815_uzyehie0hmf",
"notes": "auto: player-coins",
"blocked": false,
"coins": 0,
"createdAt": "2026-06-26T11:20:55+00:00",
"updatedAt": "2026-06-26T11:20:55+00:00"
}
]
}
+8 -11
View File
@@ -2,12 +2,7 @@
"gauntletTickMs": 220,
"gauntletJumpTicks": 16,
"gauntletTimeLimitSec": 0,
"gauntletLaneImageUrls": [
"/Game/img/gauntlet-assets/obstacles-2.png",
"/Game/img/gauntlet-assets/obstacles-3.png",
"/Game/img/gauntlet-assets/obstacles-4.png",
"/Game/img/gauntlet-assets/obstacles-5.png"
],
"gauntletLaneImageUrls": [],
"gauntletLaserTopUrl": "",
"gauntletLaserBottomUrl": "",
"gauntletLaserLineUrl": "",
@@ -74,7 +69,7 @@
"/Game/img/ViolentCrime/Meteo-3.png"
],
"spaceShooterAsteroidExplodeFrameMs": 60,
"spaceShooterAsteroidIntervalMs": 200,
"spaceShooterAsteroidIntervalMs": 300,
"spaceShooterShipDamageOverlayUrls": [
"/Game/img/ViolentCrime/Rocket-broke-1.png",
"/Game/img/ViolentCrime/Rocket-broke-2.png",
@@ -95,13 +90,15 @@
"balloonBossPlayerBalloonFallbackUrl": "/Game/img/MegaVirus/Artboard%209.png",
"balloonBossBalloonsPerPlayer": 3,
"forcedMinigameKeys": [
"stack",
"jump_survive",
"space_shooter"
"quiz",
"gauntlet",
"balloon_boss"
],
"testSpecialCardByMap": {},
"troublesomeForceOffer": false,
"specialQuizIconExpireSec": 20,
"pickVoteSec": 25,
"trialVoteSec": 30
"trialVoteSec": 30,
"lobbyDebugHud": true,
"lobbyDebugHudNames": []
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 KiB

+108 -12
View File
@@ -3483,6 +3483,10 @@
return pool[idx % pool.length] || humanId || roster[0];
}
const MOVE_SPEED = 0.15;
/* time-based movement: step=MOVE_SPEED 120fps 2 (/)
playDtMul = dt*60 (clamp 3 tunneling) ณเขาก step กท ความเรวเทากนท FPS */
let playDtMul = 1;
let playTickLastTs = 0;
/** Anti-stuck (MG1/MG4): ดันชน "เพื่อน" กี่เฟรมก่อนปลดล็อกเดินผ่าน + ช่วงเวลาที่ผ่านได้ต่อเนื่อง */
const ANTI_STUCK_PEER_TICKS = 13;
const ANTI_STUCK_WINDOW_MS = 650;
@@ -3519,7 +3523,7 @@
}
function moveSpeedTilesThisFrameForWalk() {
return MOVE_SPEED * (isQuizCarry() ? quizCarryWalkSpeedMultActive : 1);
return MOVE_SPEED * (isQuizCarry() ? quizCarryWalkSpeedMultActive : 1) * playDtMul;
}
function isMovementKey(code) {
@@ -3878,7 +3882,9 @@
const md = mapData;
const { cw, ch } = getCharacterFootprintWH(md);
const cxWorld = (axTile + cw * 0.5) * tileSize;
const cyBottomWorld = (ayTile + ch) * tileSize;
/* : anchor " tile" (ayTile) (ayTile+ch)
ไมอยลงทบโซนคำตอบ SAFE/SCAM (ตำแหนงจรงอยในโซน y4-6 แตเดมภาพหอยถ y7-8) */
const cyBottomWorld = ayTile * tileSize;
const [sx, sy] = w2s(cxWorld, cyBottomWorld);
/* ความสูง = สูง avatar บนจอ (สอดคล้องกับ drawAvatar: boxH = tileSize * zDraw * ch * 1.35) */
const sizeH = tileSize * zDrawIn * Math.max(ch, 1) * 1.35;
@@ -5921,6 +5927,7 @@
/** ช่วงตอบ: บอทสุ่มเดินไปโซนถูก/ผิด/เดินมั่ว ตามระดับ (ฉลาด/กลาง/พลาดบ่อย) */
function previewBotsPrepareAnswerRound() {
if (!playBotsEnabled() || !mapData || !isQuiz() || !previewQuizCurrent) return;
if (detectiveCaseFillBots) return; /* เกมจริง: server ตัดสินคำตอบบอทเอง */
const correctTrue = !!previewQuizCurrent.answerTrue;
const qt = mapData.quizTrueArea;
const qf = mapData.quizFalseArea;
@@ -8680,7 +8687,8 @@
}
const howtoBg = document.querySelector('#gauntlet-crown-howto-overlay .gch-bg');
if (howtoBg) {
howtoBg.src = questionMissionAssetUrl('popup-Howto.png');
/* MG1 ใช้ popup-Howtominigame1.png (รูป SAFE/SCAM) — popup-Howto.png เดิมเป็นดีไซน์ MG4 ใส่ผิดที่ */
howtoBg.src = questionMissionAssetUrl('popup-Howtominigame1.png');
howtoBg.onerror = function () {
this.onerror = null;
this.src = BASE + '/img/gauntlet-assets/popup-Howto.png';
@@ -9689,6 +9697,7 @@
function fbNum(v) { return (typeof v === 'number' && Number.isFinite(v)) ? Math.round(v * 100) / 100 : undefined; }
function broadcastFillBotState() {
if (!playBotsEnabled() || !isMePlayHost() || !mapData) return;
if (isQuiz() && detectiveCaseFillBots) return; /* quiz เกมจริง: server เป็นเจ้าของบอท (quiz-bot-move) → ห้าม host ส่งทับ = บอทวาป/ผีหลุด area */
const arr = [];
others.forEach((o, id) => {
if (!isPreviewBotId(id) || !o) return;
@@ -20343,6 +20352,8 @@
}
if (isMePlayHost()) return;
if (!data || !Array.isArray(data.bots)) return;
/* quiz เกมจริง: server เป็นเจ้าของบอท (quiz-bot-move) + roster (play-roster) → ไม่รับ fill-bot-state ทับ (กันบอทวาป/ผีหลุด) */
if (isQuiz() && detectiveCaseFillBots) return;
/* force "" host (peer host client reconnect/snapshot)
id-based (ไมชนช default). debounce 3 ครงต peer host งไมเหนชวคราวถกลบผ (self-heal) */
if (Array.isArray(data.humans)) {
@@ -20758,6 +20769,51 @@
if (isSpaceShooterMissionUiMapPlay() && spaceShooterMissionPhase === 'howto') updateSpaceShooterMissionHowtoHud();
});
/* (avatar 2 ): server roster 1.5s peer roster
(เด others เป add-only ไมเคย prune user-left หล/มาไม = วเกาคางเปนผขยบไมได)
ามบอท (ไมอยใน server roster) + ามตวเราเอง */
socket.on('play-roster', (d) => {
if (!d || !Array.isArray(d.ids)) return;
const live = new Set(d.ids.map(String));
let removed = 0;
[...others.keys()].forEach((id) => {
if (isPreviewBotId(id)) return;
if (myId != null && String(id) === String(myId)) return;
if (!live.has(String(id))) { others.delete(id); removed++; }
});
if (removed > 0 && typeof renderPlayQuizScoreboard === 'function' && isQuiz()) {
try { renderPlayQuizScoreboard(playLiveQuizScores); } catch (e) { /* ignore */ }
}
});
/* บอท MG1 quiz: server เป็นเจ้าของการเดิน (host หลุดก็ไม่หยุด) → รับตำแหน่ง แล้ว lerp ใน tick (o.tx/o.ty) */
socket.on('quiz-bot-move', (d) => {
if (!d || !Array.isArray(d.bots)) return;
if (!(isQuiz() && detectiveCaseFillBots)) return;
d.bots.forEach((rb) => {
if (!rb || typeof rb.id !== 'string') return;
const o = others.get(rb.id);
if (!o) return; /* บอทฝั่ง client ยังไม่ถูกสร้าง — รอ bot sync สร้างก่อน */
if (rb.elim) {
/* (eliminated): snap "warp" ( >1.5 tile ) ;
แต lerp การเดนเลกๆ ในโซนผ (นกระต) */
var jx = Number.isFinite(rb.x) ? rb.x - o.x : 0;
var jy = Number.isFinite(rb.y) ? rb.y - o.y : 0;
if (Math.hypot(jx, jy) > 1.5) {
if (Number.isFinite(rb.x)) o.x = rb.x;
if (Number.isFinite(rb.y)) o.y = rb.y;
}
if (Number.isFinite(rb.x)) o.tx = rb.x;
if (Number.isFinite(rb.y)) o.ty = rb.y;
} else {
if (Number.isFinite(rb.x)) o.tx = rb.x;
if (Number.isFinite(rb.y)) o.ty = rb.y;
}
if (rb.direction) o.direction = rb.direction;
o.botIsWalking = !!rb.isWalking;
});
});
/* ===== Disconnect grace + bot takeover (10 วิ รอ reconnect) ===== */
let _playGraceCountdownTimer = null;
function showDisconnectGraceBanner(nickname, seconds) {
@@ -21124,7 +21180,9 @@
}
/** : bot server HOST (/respawn/) broadcast fill-bot-state
(เดมท client ดสนเอง + respawn วย Math.random แยกก ตำแหน/อก/คะแนนบอทคนละแบบทกจอ) */
if (isQuiz() && Array.isArray(r.results) && playBotsEnabled() && isMePlayHost()) {
if (isQuiz() && Array.isArray(r.results) && playBotsEnabled() && isMePlayHost() && !detectiveCaseFillBots) {
/* (detectiveCaseFillBots): server (/ r.scores/r.results ) host scoring
คงไวเฉพาะ editor preview (previewFillBots) ไม server session */
const correctTrueBot = !!r.correctTrue;
others.forEach(function (o, id) {
if (!isPreviewBotId(id) || !o) return;
@@ -22436,7 +22494,7 @@
const pathStepMul = (previewFillBots && editorEmbedReturn)
? (isQuizCarry() ? baseEmbedCarryPathMul * (quizCarryWalkSpeedMultActive / QUIZ_CARRY_WALK_SPEED_MULT) : 0.56)
: 1;
const step = Math.min(MOVE_SPEED * 1.28 * pathStepMul * carryWalk, len);
const step = Math.min(MOVE_SPEED * 1.28 * pathStepMul * carryWalk * playDtMul, len); /* time-based */
const nx = o.x + (dx / len) * step;
const ny = o.y + (dy / len) * step;
if (Math.abs(dy) > Math.abs(dx)) o.direction = dy > 0 ? 'down' : 'up';
@@ -22509,6 +22567,7 @@
function stepPreviewBots() {
if (!playBotsEnabled() || !isMePlayHost() || !mapData || isFrogger() || isGauntlet() || isStack() || isJumpSurvive() || isSpaceShooter() || isBalloonBoss()) return;
if (isQuiz() && detectiveCaseFillBots) return; /* เกมจริง: server เดินบอท quiz เอง (host หลุดก็ไม่หยุด) */
if (isQuizCarry()) {
stepQuizCarryPreviewBots();
return;
@@ -22563,7 +22622,7 @@
dxq /= distq; dyq /= distq;
if (Math.abs(dyq) > Math.abs(dxq)) o.direction = dyq > 0 ? 'down' : 'up';
else o.direction = dxq > 0 ? 'right' : 'left';
const step = MOVE_SPEED;
const step = MOVE_SPEED * playDtMul; /* time-based: บอทเร็วเท่ากันทุก FPS ของ host */
const tox = o.x + dxq * step;
const toy = o.y + dyq * step;
const pathStrictW = isQuizBattle() && quizBattlePathModeActive(mapData);
@@ -25483,7 +25542,16 @@
return mv;
}
function tick() {
if (!mapData) { requestAnimationFrame(tick); return; }
if (!mapData) { playTickLastTs = 0; requestAnimationFrame(tick); return; }
/* dt frame (วินาที) → playDtMul = dt*60 (clamp 0.05s = step ≤0.45 tile กัน tunneling) ใช้ทำ movement time-based */
{
const _pnow = (typeof performance !== 'undefined' && performance.now) ? performance.now() : Date.now();
let _pdt = playTickLastTs ? (_pnow - playTickLastTs) / 1000 : (1 / 60);
if (!(_pdt > 0)) _pdt = 1 / 60;
if (_pdt > 0.05) _pdt = 0.05;
playTickLastTs = _pnow;
playDtMul = _pdt * 60;
}
/* (input/sim/timer)
นเวลาทกตวไปขางหนาเท delta กเฟรม countdown แสดงหยดนงจร */
if (specialQuizFreeze) {
@@ -25604,14 +25672,42 @@
}
/* บอท preview ขยับที่ o.x/o.y โดยตรง — ห้าม LERP กับ tx/ty เพราะ stepPreviewBots เคยตั้ง tx=ก่อนเดิน ทำให้โดนดึงถอย ~20%/เฟรม กระตุกและแทบไม่ไป */
others.forEach((o, id) => {
/* host เดินบอทเองตรงๆ (o.x/o.y) → ข้าม lerp; แต่ client อื่นต้อง lerp ตามตำแหน่งที่ host ส่งมา (o.tx/o.ty) */
if (playBotsEnabled() && isPreviewBotId(id) && isMePlayHost()) return;
/* host (o.x/o.y) lerp; client lerp host (o.tx/o.ty)
ยกเว quiz เกมจร: server เดนบอท กคน (รวม host) lerp ตาม server */
if (playBotsEnabled() && isPreviewBotId(id) && isMePlayHost() && !(isQuiz() && detectiveCaseFillBots)) return;
/* MG4 (quiz_carry) + MG1 (quiz mng8a80o) non-host lerp 0.2 host ~1-2 ("")
เร lerp เฉพาะบอท quiz/quiz_carry ใหตามตำแหน host นข (ไมแตะเกมอ/เลนจร) */
const lerpF = (isPreviewBotId(id) && (isQuizCarry() || isQuiz())) ? 0.5 : LERP;
if (o.tx != null) o.x += (o.tx - o.x) * lerpF;
if (o.ty != null) o.y += (o.ty - o.y) * lerpF;
/* บอท MG1 server-driven: server ส่งทุก 60ms → lerp นุ่ม 0.22 (เดิม 0.5 = ถึงเป้าใน 1-2 เฟรมแล้วค้าง = กระตุก) */
const serverDrivenQuizBot = isPreviewBotId(id) && isQuiz() && detectiveCaseFillBots;
const lerpF = serverDrivenQuizBot ? 0.22 : ((isPreviewBotId(id) && (isQuizCarry() || isQuiz())) ? 0.5 : LERP);
const lerpFN = 1 - Math.pow(1 - lerpF, playDtMul); /* frame-rate-normalized → นุ่มเท่ากันทุก FPS */
if (o.tx != null) o.x += (o.tx - o.x) * lerpFN;
if (o.ty != null) o.y += (o.ty - o.y) * lerpFN;
});
/* client guard: (eliminated) "" snap
ใช single-tile check (ตรงก server) าอยในชองผแลวปลอยใหนตาม server (นวาปวนจากเดมทใช footprint+)
(เด confine อยใน stepPreviewBots ดไปสำหร quiz ายมาเป guard สระ) */
if (isQuiz() && detectiveCaseFillBots) {
const _gg = quizGhostAreaGridPlay();
if (_gg) {
others.forEach((o, id) => {
if (!isPreviewBotId(id) || !o) return;
const isGhostBot = !!playQuizEverWrong[String(id)] || (o.quizCannotTrue && o.quizCannotFalse);
if (!isGhostBot) return;
const tx = Math.floor(o.x), ty = Math.floor(o.y);
if (_gg[ty] && _gg[ty][tx] === 1) return; /* ช่องที่ยืนเป็นช่องผีแล้ว → ปล่อย (ตรงกับ server) */
/* หลุดจริง → หาช่องผีใกล้สุด snap (deterministic ไม่สุ่ม) */
let best = null, bd = Infinity;
for (let y = 0; y < _gg.length; y++) {
const row = _gg[y] || [];
for (let x = 0; x < row.length; x++) {
if (row[x] === 1) { const d = Math.abs(x - o.x) + Math.abs(y - o.y); if (d < bd) { bd = d; best = { x: x, y: y }; } }
}
}
if (best) { o.x = best.x + 0.5; o.y = best.y + 0.5; o.tx = o.x; o.ty = o.y; }
});
}
}
tickQuizCarryEmbedCountdown();
tickQuizCarryRoundTimers();
updateQuizCarryCarryPhaseHud();
+151 -32
View File
@@ -25,6 +25,79 @@
} catch (e) { /* ignore */ }
}
lobbyLog('lobby-open', 'space=' + spaceId);
/* ===== DEV HUD Iron Man: real-time LobbyA //% 3 :
(1) ?dbg=1 (2) localStorage.lobbyDbg='1' (3) admin: game-timing.json {lobbyDebugHud:true, lobbyDebugHudNames:[...]}
default (เลนจรงไมเห). โหลดเสร fade หาย ===== */
var _dbgForced = (function () { try { return new URLSearchParams(location.search).get('dbg') === '1' || localStorage.getItem('lobbyDbg') === '1'; } catch (e) { return false; } })();
var _dbgAdmin = false;
function dbgOn() { return _dbgForced || _dbgAdmin; }
var _dbgState = { steps: [
{ k: 'manifest', label: 'MANIFEST', pct: 0, st: 'wait' },
{ k: 'colors', label: 'RESOLVE COLOR', pct: 0, st: 'wait' },
{ k: 'join', label: 'JOIN ROOM', pct: 0, st: 'wait' },
{ k: 'mychar', label: 'MY CHARACTER', pct: 0, st: 'wait' },
{ k: 'occ', label: 'OCCUPANTS', pct: 0, st: 'wait', sub: '' },
], t0: Date.now() };
function _dbgStep(k) { for (var i = 0; i < _dbgState.steps.length; i++) if (_dbgState.steps[i].k === k) return _dbgState.steps[i]; return null; }
function dbgSet(k, pct, st, sub) {
var s = _dbgStep(k); if (!s) return;
if (pct != null) s.pct = Math.max(0, Math.min(100, Math.round(pct)));
if (st) s.st = st; if (sub != null) s.sub = sub;
if (dbgOn()) { dbgEnsure(); dbgRender(); }
}
function dbgEnsure() {
if (!dbgOn() || document.getElementById('lobby-dbg-hud')) return;
if (!document.getElementById('lobby-dbg-css')) {
var st = document.createElement('style'); st.id = 'lobby-dbg-css';
st.textContent = '#lobby-dbg-hud{position:fixed;top:14px;left:14px;z-index:100000;min-width:248px;padding:12px 14px 11px;'
+ 'font:600 11px/1.5 "Share Tech Mono",ui-monospace,monospace;color:#7ff3ff;background:linear-gradient(160deg,rgba(6,20,34,.92),rgba(4,12,22,.92));'
+ 'border:1px solid rgba(64,224,255,.5);border-radius:10px;box-shadow:0 0 22px rgba(40,200,255,.25),inset 0 0 18px rgba(40,200,255,.08);'
+ 'backdrop-filter:blur(2px);letter-spacing:.5px;transition:opacity .4s ease;pointer-events:none;text-shadow:0 0 6px rgba(64,224,255,.5)}'
+ '#lobby-dbg-hud .ttl{display:flex;justify-content:space-between;color:#ffb152;font-size:12px;border-bottom:1px solid rgba(255,177,82,.3);padding-bottom:5px;margin-bottom:7px;text-shadow:0 0 6px rgba(255,160,60,.5)}'
+ '#lobby-dbg-hud .row{display:flex;align-items:center;gap:7px;margin:3px 0}'
+ '#lobby-dbg-hud .ic{width:13px;text-align:center}'
+ '#lobby-dbg-hud .lb{flex:0 0 96px;opacity:.92}'
+ '#lobby-dbg-hud .br{flex:1;height:7px;border-radius:4px;background:rgba(64,224,255,.12);overflow:hidden;box-shadow:inset 0 0 4px rgba(0,0,0,.5)}'
+ '#lobby-dbg-hud .bf{height:100%;width:0;background:linear-gradient(90deg,#1fbfff,#7ff3ff);box-shadow:0 0 8px rgba(80,220,255,.8);transition:width .15s}'
+ '#lobby-dbg-hud .pc{flex:0 0 34px;text-align:right;opacity:.85}'
+ '#lobby-dbg-hud .sub{font-size:10px;color:#9fe8ff;opacity:.7;margin:1px 0 2px 20px}'
+ '#lobby-dbg-hud .ok{color:#5effa6}#lobby-dbg-hud .run .ic{color:#ffd166;animation:dbgpulse .8s infinite}#lobby-dbg-hud .wait{opacity:.4}'
+ '@keyframes dbgpulse{50%{opacity:.3}}';
document.head.appendChild(st);
}
var el = document.createElement('div'); el.id = 'lobby-dbg-hud';
document.body.appendChild(el); dbgRender();
}
function dbgRender() {
var el = document.getElementById('lobby-dbg-hud'); if (!el) return;
var ms = Date.now() - _dbgState.t0;
var h = '<div class="ttl"><span>◢ LOBBY LOAD</span><span>' + (ms / 1000).toFixed(1) + 's</span></div>';
_dbgState.steps.forEach(function (s) {
var ic = s.st === 'done' ? '✓' : (s.st === 'run' ? '⟳' : '·');
h += '<div class="row ' + s.st + '"><span class="ic">' + ic + '</span><span class="lb">' + s.label + '</span>'
+ '<span class="br"><span class="bf" style="width:' + s.pct + '%"></span></span><span class="pc">' + s.pct + '%</span></div>';
if (s.sub) h += '<div class="sub">▸ ' + s.sub + '</div>';
});
el.innerHTML = h;
}
function dbgFinish() {
var el = document.getElementById('lobby-dbg-hud'); if (!el) return;
_dbgState.steps.forEach(function (s) { s.st = 'done'; s.pct = 100; });
dbgRender();
setTimeout(function () { el.style.opacity = '0'; setTimeout(function () { if (el.parentNode) el.parentNode.removeChild(el); }, 450); }, 600);
}
/* อ่าน flag จาก admin (game-timing.json) — เปิด HUD ให้ทุกคน หรือเฉพาะชื่อที่ระบุ */
try {
fetch(BASE + '/data/game-timing.json?_=' + Date.now()).then(function (r) { return r.json(); }).then(function (g) {
if (!g || !g.lobbyDebugHud) return;
var names = Array.isArray(g.lobbyDebugHudNames) ? g.lobbyDebugHudNames.map(function (s) { return String(s).trim().toLowerCase(); }).filter(Boolean) : [];
var me = ''; try { me = (getProfileDisplayName() || '').trim().toLowerCase(); } catch (e) { /* ignore */ }
_dbgAdmin = (names.length === 0) || names.indexOf(me) >= 0;
if (dbgOn()) { dbgEnsure(); dbgRender(); }
}).catch(function () {});
} catch (e) { /* ignore */ }
if (_dbgForced) { dbgEnsure(); }
const DESIGN_MENU = typeof designMainMenuHref === 'function' ? designMainMenuHref() : '/Main-Menu/';
if (!spaceId) { location.href = DESIGN_MENU; return; }
const roomIdValueEl = document.getElementById('room-id-value');
@@ -506,18 +579,18 @@
function injectRoomLoadingOverlay() {
if (document.getElementById('room-loading-overlay')) {
setTimeout(hideRoomLoading, 12000); /* overlay เป็น static ใน html แล้ว — ตั้ง safety กันค้างถาวรถ้า preload แฮงค์ */
setTimeout(hideRoomLoading, 30000); /* overlay เป็น static ใน html แล้ว — ตั้ง safety กันค้างถาวรถ้า preload แฮงค์ (occupants นานขึ้น) */
return;
}
var style = document.createElement('style');
style.textContent = '#room-loading-overlay{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:18px;background:radial-gradient(circle at 50% 38%, #0b1430, #060818);color:#cfe9ff;font-family:Kanit,Sarabun,system-ui,sans-serif;transition:opacity .45s ease}#room-loading-overlay.is-hidden{opacity:0;pointer-events:none}#room-loading-spinner{width:56px;height:56px;border:5px solid rgba(34,211,238,.22);border-top-color:#22d3ee;border-radius:50%;animation:rlspin 1s linear infinite}@keyframes rlspin{to{transform:rotate(360deg)}}#room-loading-overlay .rl-txt{font-size:1.1rem;letter-spacing:.04em;opacity:.9}';
style.textContent = '#room-loading-overlay{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:18px;background:rgba(0,0,0,0.9);color:#cfe9ff;font-family:Kanit,Sarabun,system-ui,sans-serif;transition:opacity .45s ease}#room-loading-overlay.is-hidden{opacity:0;pointer-events:none}#room-loading-spinner{width:56px;height:56px;border:5px solid rgba(34,211,238,.22);border-top-color:#22d3ee;border-radius:50%;animation:rlspin 1s linear infinite}@keyframes rlspin{to{transform:rotate(360deg)}}#room-loading-overlay .rl-txt{font-size:1.1rem;letter-spacing:.04em;opacity:.9}';
document.head.appendChild(style);
var ov = document.createElement('div');
ov.id = 'room-loading-overlay';
ov.innerHTML = '<div id="room-loading-spinner"></div><div class="rl-txt">กำลังโหลดตัวละคร…</div>';
(document.body || document.documentElement).appendChild(ov);
/* safety: กัน overlay ค้างถาวรถ้า preload/manifest แฮงค์ (ไม่มี roomPreloadReady) */
setTimeout(hideRoomLoading, 12000);
/* safety: กัน overlay ค้างถาวรถ้า preload/manifest แฮงค์ (ไม่มี roomPreloadReady) — occupants นานขึ้น */
setTimeout(hideRoomLoading, 30000);
}
function hideRoomLoading() {
@@ -542,7 +615,7 @@
if (ov) { ov.classList.remove('is-hidden'); ov.style.opacity = ''; }
var t = ov && ov.querySelector('.rl-txt');
if (t) t.textContent = text || 'กำลังโหลด…';
if (!(opts && opts.persist)) setTimeout(hideRoomLoading, 12000);
if (!(opts && opts.persist)) setTimeout(hideRoomLoading, 30000);
}
/* แสดง % บนหน้าโหลด LobbyB (ตอนกลับจากมินิเกม) — ตามความคืบหน้า preload ตัวละคร */
@@ -554,7 +627,7 @@
el.textContent = 'กำลังโหลดตัวละคร… ' + p + '%';
}
function preloadLobbyTintedCharacter(id, theme, skin, cb) {
function preloadLobbyTintedCharacter(id, theme, skin, cb, onFrame) {
if (!id || (!theme && !skin)) { if (cb) cb(); return; }
var dirs = ['down', 'up', 'left', 'right'];
var suffixes = ['idle', '0', '1', '2', '3'];
@@ -563,6 +636,7 @@
var finished = false;
function one() {
doneCount++;
if (onFrame) { try { onFrame(doneCount, total, id); } catch (e) { /* ignore */ } }
if (!finished && doneCount >= total) {
finished = true;
if (cb) cb();
@@ -589,8 +663,8 @@
});
}
function preloadMyTintedCharacter(cb) {
preloadLobbyTintedCharacter(getStoredCharacterId(), myTintTheme, myTintSkin, cb);
function preloadMyTintedCharacter(cb, onFrame) {
preloadLobbyTintedCharacter(getStoredCharacterId(), myTintTheme, myTintSkin, cb, onFrame);
}
/** อุ่น tint บอท + peer ที่มีสี — กันกระตุกตอนบอทเดิน/idle ครั้งแรก */
@@ -616,8 +690,10 @@
tasks.forEach(function (t) {
preloadLobbyTintedCharacter(t[0], t[1], t[2], function () {
done++;
if (onProgress) onProgress(done, total);
if (onProgress) onProgress(done, total, t[0], 1, 1);
if (done >= total && cb) cb();
}, function (fd, ft, cid) {
if (onProgress) onProgress(done, total, cid, fd, ft);
});
});
}
@@ -1170,6 +1246,10 @@
const keys = {};
const MOVE_SPEED = 0.15;
/* L2 time-based movement: step=MOVE_SPEED 120fps 2 ()
เปลยนเป units/นาท (0.15/เฟรม × 60fps = 9 u/s) แลวค dt กเครองเรวเทากนไมนก FPS */
const MOVE_SPEED_PER_SEC = MOVE_SPEED * 60;
let lobbyLastTickTs = 0; /* timestamp เฟรมก่อน (ms) ใช้คำนวณ dt */
let lastMoveSend = 0;
const moveCodes = ['KeyW', 'KeyA', 'KeyS', 'KeyD', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'];
let lobbyInteractPulse = null;
@@ -2398,29 +2478,36 @@
if (arr.length) socket.emit('lobby-bot-move', { bots: arr });
}
function lerpLobbyBots() {
function lerpLobbyBots(factor) {
const f = (typeof factor === 'number' && factor > 0) ? factor : LERP;
lobbyBots.forEach((b) => {
if (typeof b.botSyncTX === 'number') b.x += (b.botSyncTX - b.x) * LERP;
if (typeof b.botSyncTY === 'number') b.y += (b.botSyncTY - b.y) * LERP;
if (typeof b.botSyncTX === 'number') b.x += (b.botSyncTX - b.x) * f;
if (typeof b.botSyncTY === 'number') b.y += (b.botSyncTY - b.y) * f;
});
}
function lobbyTick() {
const me = peers.get(socket.id);
if (!mapData || !me) { requestAnimationFrame(lobbyTick); return; }
if (!mapData || !me) { lobbyLastTickTs = 0; requestAnimationFrame(lobbyTick); return; }
/* dt = () clamp 0.05s /
เฟรมแรก (ts0===0) ใช 60fps มาตรฐาน */
const _now = Date.now();
let dt = lobbyLastTickTs ? (_now - lobbyLastTickTs) / 1000 : (1 / 60);
if (!(dt > 0)) dt = 1 / 60;
if (dt > 0.05) dt = 0.05;
lobbyLastTickTs = _now;
/* LERP remote avatar แบบ frame-rate-normalized → ความนุ่มเท่ากันทุก FPS (เดิม 0.2/เฟรม = 120fps ลู่เร็วเกิน) */
const lerpA = 1 - Math.pow(1 - LERP, dt * 60);
peers.forEach((p, id) => {
if (id !== socket.id && (p.tx != null || p.ty != null)) {
if (p.tx != null) p.x += (p.tx - p.x) * LERP;
if (p.ty != null) p.y += (p.ty - p.y) * LERP;
if (p.tx != null) p.x += (p.tx - p.x) * lerpA;
if (p.ty != null) p.y += (p.ty - p.y) * lerpA;
}
});
if (lobbyBotSlotCount > 0) {
if (hostId === socket.id) {
if (!suspectPickOverlayOpen) stepLobbyCaseBots();
broadcastLobbyBotPositions(); /* host เดินจริง → ส่งตำแหน่งให้ทุกคน */
} else {
lerpLobbyBots(); /* client อื่น: ตามตำแหน่งจาก host (ไม่สุ่มเดินเอง) */
}
/* L1: server lobby client ( host) lerp server
(เด host เดนเอง frame-based บอทวงเรวชาตางกนตาม FPS/host) */
lerpLobbyBots(lerpA);
}
const w = mapData.width || 20, h = mapData.height || 15;
const preWalkX = me.x, preWalkY = me.y;
@@ -2464,7 +2551,7 @@
}
if (accX !== 0 || accY !== 0) {
const len = Math.sqrt(accX * accX + accY * accY) || 1;
const step = Math.min(MOVE_SPEED, len);
const step = Math.min(MOVE_SPEED_PER_SEC * dt, len); /* time-based: เร็วเท่ากันทุก FPS */
const nx = me.x + (accX / len) * step;
const ny = me.y + (accY / len) * step;
if (canWalkLobby(nx, ny, me.x, me.y)) {
@@ -3232,6 +3319,7 @@
socket.on('connect', () => {
lobbyLog('socket-connect', '');
dbgSet('join', 40, 'run', 'socket connected · waiting server…');
/* ส่งค่าสีที่เลือกใน Main-Lobby ติดไปด้วย — server จะใช้ค่านี้ถ้ายังว่าง (กันโชว์สีแดง default ตอนเข้าใหม่) */
var savedThemeIdx = null;
var savedSkinIdx = null;
@@ -3264,6 +3352,7 @@
roomJoinReady = true;
clientLobbyMapId = res.mapId != null ? res.mapId : null;
lobbyLog('join-ok', 'peers=' + (res.peers || []).length + ' host=' + (res.hostId === socket.id ? 'me' : 'other') + ' map=' + res.mapId + ' bots=' + (res.botSlotCount != null ? res.botSlotCount : '?'));
dbgSet('join', 100, 'done', 'peers ' + (res.peers || []).length + ' · bots ' + (res.botSlotCount != null ? res.botSlotCount : '?'));
/* ไอคอนกุญแจ 🔒 โชว์เฉพาะห้อง private (จาก res.isPrivate) — public ไม่โชว์ */
try {
const lockEl = document.getElementById('room-id-lock');
@@ -4042,9 +4131,9 @@
} catch (err) { console.warn('WebRTC signal error', err); }
});
/* รับตำแหน่งบอทจาก host (เฉพาะ client ที่ไม่ใช่ host) → เก็บเป็นเป้า lerp ใน lobbyTick */
/* server (L1: server lobby) lerp lobbyTick
client บเหมอนกนรวม host (เด host เดนเอง กยายมา server แล) */
socket.on('lobby-bot-move', (data) => {
if (hostId === socket.id) return; /* host เป็นเจ้าของเอง ไม่ต้องรับ */
if (!data || !Array.isArray(data.bots)) return;
data.bots.forEach((rb) => {
if (!rb || typeof rb.id !== 'string') return;
@@ -4057,6 +4146,27 @@
});
});
/* L3 : server roster peer
(เดมพ user-left อยางเดยว event หล/มาไม = างถาวรใน LobbyA/B) */
socket.on('lobby-roster', (data) => {
if (!data || !Array.isArray(data.ids)) return;
const live = new Set(data.ids.map(String));
let removed = 0;
[...peers.keys()].forEach((id) => {
if (String(id) === String(socket.id)) return; /* ตัวเราเองไม่ตัด */
if (!live.has(String(id))) {
if (typeof closePeer === 'function') closePeer(id);
peers.delete(id);
removed++;
}
});
if (removed > 0) {
updatePlayersHud();
renderPeers();
redrawLobbyMap();
}
});
socket.on('host-changed', (data) => {
hostId = data.hostId || null;
const isHost = hostId === socket.id;
@@ -7605,24 +7715,33 @@
updateLobbyProfileAvatar();
setupRoomCustomize();
lobbyLog('preload-start', '');
dbgSet('manifest', 0, 'run');
rlEnsureManifest(function () {
lobbyLog('manifest-done', '');
dbgSet('manifest', 100, 'done'); dbgSet('colors', 0, 'run');
rlResolveMyColors(function () {
lobbyLog('colors-resolved', '');
dbgSet('colors', 100, 'done'); dbgSet('mychar', 0, 'run');
updateRoomProfileAvatarTinted();
preloadMyTintedCharacter(function () {
lobbyLog('mychar-tinted', 'roomJoinReady=' + roomJoinReady);
/* tint "" ( tint = ~12 )
tint คนอนโหลด background avatar คนอนโผลตามทหลงนดหนอย (ยอมรบได) */
roomPreloadReady = true;
setRoomLoadingPct(100);
lobbyLog('preload-ready(mychar)', '');
maybeHideRoomLoading();
dbgSet('mychar', 100, 'done'); dbgSet('occ', 0, 'run');
/* overlay ( 0.9) occupants = "" (+) %
นเห avatar คนอนโผลนสหล (เดมซอน overlay หลงตวเรา occupants โหลด background ไม loading) */
setRoomLoadingPct(0);
preloadAllLobbyTintedOccupants(function () {
lobbyLog('preload-occupants-done(bg)', '');
}, function (d, t) {
lobbyLog('preload-occupants-done', '');
dbgSet('occ', 100, 'done'); dbgFinish();
roomPreloadReady = true;
setRoomLoadingPct(100);
lobbyLog('preload-ready(occupants)', '');
maybeHideRoomLoading();
}, function (d, t, cid, fd, ft) {
setRoomLoadingPct(t ? (d / t) * 100 : 100);
dbgSet('occ', t ? (d / t) * 100 : 100, 'run', 'char ' + d + '/' + t + (cid ? ' · ' + String(cid).slice(0, 12) + (ft ? ' ' + Math.round((fd / ft) * 100) + '%' : '') : ''));
});
}, function (fd, ft) {
dbgSet('mychar', ft ? (fd / ft) * 100 : 0, 'run', 'frame ' + fd + '/' + ft);
});
});
});
+15 -1
View File
@@ -3926,6 +3926,20 @@
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .btn-gch-ready:active {
transform: translateY(2px);
}
/* MG1 quiz — ปุ่ม READY 2 สถานะ:
ยังไม่กด = cyan เต็ม (รูป2 btn-ready.png · override greyscale global) · กดแล้ว = เขียว+✓ (รูป3 btn-ready-on.png) */
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .btn-gch-ready:not(.is-me-ready):not(.is-start-phase),
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .btn-gch-ready:not(.is-me-ready):not(.is-start-phase) img {
filter: drop-shadow(0 0 18px rgba(120, 220, 255, 0.65)) !important; /* cyan เต็ม ไม่ย้อมเทา */
}
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .btn-gch-ready.is-me-ready:not(.is-start-phase) {
background-image: url('/Game/img/QUESTION/btn-ready-active.png') !important; /* รูปเขียว READY ✓ (มี check ในรูปแล้ว) */
filter: drop-shadow(0 0 16px rgba(74, 222, 128, 0.7)) !important;
}
#gauntlet-crown-howto-overlay.gch-quiz-tf-mock .gch-inner.gch-inner--art .btn-gch-ready.is-me-ready:not(.is-start-phase):hover {
transform: translateY(-3px);
filter: drop-shadow(0 0 26px rgba(74, 222, 128, 0.95)) !important;
}
/* Minigame-2 mno9kb07 — HOW TO PLAY บน canvas (แทน mg-bg ใน mock 01-howto) */
#gauntlet-crown-howto-overlay.gch-mg2-mock {
display: block;
@@ -5412,7 +5426,7 @@
<script src="/app-base.js?v=2"></script>
<script src="/Game/socket.io/socket.io.js"></script>
<script src="js/version.js?v=0.0306"></script>
<script src="js/play.js?v=0.006260120"></script>
<script src="js/play.js?v=0.006260129"></script>
<div class="version-tag">v —</div>
<style id="qc-howto-mg2-fix">
/* HOW TO PLAY ของ quiz_carry (Minigame-4) -> ให้เหมือน Minigame-2 (gch-mg2-mock)
+2 -2
View File
@@ -1110,7 +1110,7 @@
<body class="room-lobby-page">
<!-- Loading overlay แบบ static (อยู่ใน HTML ตั้งแต่แรก) — กันเห็นฉากเก่าแว่บก่อน JS รัน (โดยเฉพาะตอนเกม→LobbyB) -->
<style>
#room-loading-overlay{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:18px;background:radial-gradient(circle at 50% 38%, #0b1430, #060818);color:#cfe9ff;font-family:Kanit,Sarabun,system-ui,sans-serif;transition:opacity .45s ease}
#room-loading-overlay{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;flex-direction:column;gap:18px;background:rgba(0,0,0,0.9);color:#cfe9ff;font-family:Kanit,Sarabun,system-ui,sans-serif;transition:opacity .45s ease}
#room-loading-overlay.is-hidden{opacity:0;pointer-events:none}
#room-loading-spinner{width:56px;height:56px;border:5px solid rgba(34,211,238,.22);border-top-color:#22d3ee;border-radius:50%;animation:rlspin 1s linear infinite}
@keyframes rlspin{to{transform:rotate(360deg)}}
@@ -1648,7 +1648,7 @@
<script src="js/version.js?v=0.0122"></script>
<script src="js/customize-popup.js?v=40" data-customize-triggers="" data-customize-asset-base="img/03-5-Customize"></script>
<script src="js/achievements.js?v=0.002" data-asset-base="img/03-6-Profile"></script>
<script src="js/room-lobby.js?v=0.0326"></script>
<script src="js/room-lobby.js?v=0.0329"></script>
<div class="version-tag">v —</div>
</body>
</html>
+440 -34
View File
@@ -437,6 +437,19 @@ function getDiskStats() {
return { total, free: avail, used, usedPercent: Math.round((used / total) * 100) };
} catch (e) { return null; }
}
/* จำนวนผู้เล่น/ห้อง/socket ออนไลน์ตอนนี้ — โชว์ในหน้า Admin เทียบกับเพดานความจุ */
function getOnlineStats() {
let players = 0, rooms = 0;
try {
for (const [, sp] of spaces) {
if (sp && sp.peers) { players += sp.peers.size; rooms++; }
}
} catch (e) { /* ignore */ }
let sockets = 0;
try { sockets = (io && io.engine && io.engine.clientsCount) || 0; } catch (e) { /* ignore */ }
return { sockets, players, rooms };
}
function getSystemStats() {
const totalMem = os.totalmem();
const freeMem = os.freemem();
@@ -470,6 +483,9 @@ function getSystemStats() {
uptime: Math.round(process.uptime()),
},
uptime: { os: Math.round(os.uptime()), process: Math.round(process.uptime()) },
/* ผู้ใช้ออนไลน์ + เพดานความจุ (ประเมินจาก 2 vCPU / socket fan-out): สบาย ≤300 · เริ่มหนัก ≥500 */
online: getOnlineStats(),
capacity: { comfortable: 300, strain: 500 },
hostname: os.hostname(),
platform: os.platform(),
ts: Date.now(),
@@ -2844,6 +2860,13 @@ function saveGameTimingToFile(d) {
trialVoteSec: Object.prototype.hasOwnProperty.call(d, 'trialVoteSec')
? Math.max(5, Math.min(180, Math.floor(Number(d.trialVoteSec)) || 30))
: (prev.trialVoteSec != null ? Math.max(5, Math.min(180, Math.floor(Number(prev.trialVoteSec)) || 30)) : 30),
/* DEV: เปิด HUD โหลด LobbyA (Iron Man) — admin toggle. preserve ค่าเดิมถ้า request ไม่ส่งมา */
lobbyDebugHud: Object.prototype.hasOwnProperty.call(d, 'lobbyDebugHud')
? !!d.lobbyDebugHud
: !!prev.lobbyDebugHud,
lobbyDebugHudNames: Object.prototype.hasOwnProperty.call(d, 'lobbyDebugHudNames')
? (Array.isArray(d.lobbyDebugHudNames) ? d.lobbyDebugHudNames.slice(0, 30).map((s) => String(s).slice(0, 40)) : [])
: (Array.isArray(prev.lobbyDebugHudNames) ? prev.lobbyDebugHudNames : []),
};
fs.writeFileSync(GAME_TIMING_PATH, JSON.stringify(out, null, 2), 'utf8');
runtimeGameTiming = out;
@@ -3399,6 +3422,42 @@ function crownLobbySyncPayload(space) {
};
}
/* เช็คว่าพร้อมเริ่มมินิเกม crown-lobby ไหม: ยังไม่เริ่ม + เข้าครบ + ทุกคน (ไม่นับ banned) กด Ready */
function crownLobbyAllReadyToStart(space) {
const gr = space && space.gauntletRun;
if (!gr || !gr.crownRunHeld || gr.lobbyStarted) return false;
const rm = space.gauntletCrownLobbyReady || {};
const humanIds = [...space.peers.keys()].filter((id) => !isBannedPeerForRun(space, id));
if (humanIds.length === 0) return false;
const expectedActive = space.minigameExpectedActiveCount || 0;
if (expectedActive > 0 && humanIds.length < expectedActive) return false;
return humanIds.every((id) => rm[id]);
}
/* crown-lobby (server ) idempotent gr.lobbyStarted ( gr )
ใช host กด START และ auto-start เมอทกคน ready (Track B: MG1 ไมองพ host) */
function performCrownLobbyStart(sid, space) {
const gr = space && space.gauntletRun;
if (!gr || !gr.crownRunHeld || gr.lobbyStarted) return false;
gr.lobbyStarted = true;
const liveBeginsAt = Date.now() + LIVE_COUNTDOWN_MS;
space.missionLiveBeginsAt = liveBeginsAt;
if (isQuizQuestionMissionShellSpace(space)) {
/* quiz: เลื่อน server timer ไปเริ่มที่ liveBeginsAt (ตรงกับตอน client จบ 3-2-1) */
setTimeout(() => {
const sp = spaces.get(sid);
if (!sp) return;
const md2 = maps.get(sp.mapId) || sp.mapData;
if (md2 && md2.gameType === 'quiz') {
clearSpaceQuizTimers(sp);
startQuizGame(sid, sp, md2);
}
}, LIVE_COUNTDOWN_MS);
}
io.to(sid).emit('gauntlet-crown-lobby-started', { liveBeginsAt });
return true;
}
/** สุ่ม 3 minigame จาก pool 7 แบบ — เรียกครั้งเดียวตอนเข้า LobbyB (ล็อกบน space) */
/** แมปเก่า (กบ frogger) → Minigame-2 Gauntlet ตาม Admin */
function normalizeDetectiveCardEntry(entry) {
@@ -4365,6 +4424,9 @@ function scheduleQuizAnswerPhase(sid, space, md) {
endsAt: sess.phaseEndsAt,
});
emitQuizPlayerStates(sid, space);
/* บอท: server ตัดสินคำตอบข้อนี้ + ตั้งเป้าเดินไปโซน (server tick เดินให้ในช่วง answer) */
const qCur = sess.questions[sess.qIndex];
if (qCur) quizBotsDecideAnswers(space, sess.quizMapMd || md, !!qCur.answerTrue);
const t = setTimeout(() => resolveQuizRound(sid, space, md), answerMs);
space.quizTimers.push(t);
}
@@ -4453,6 +4515,29 @@ function resolveQuizRound(sid, space, md) {
scores[peerId] = st && typeof st.score === 'number' ? st.score : 0;
});
/* บอท: server เป็นเจ้าของคะแนน (จากคำตอบที่ตัดสินไว้) + คัดออกถ้าผิด (กฎเดียวกับคน "ตอบผิดถูกคัดออก") */
if (sess.bots) {
sess.bots.forEach((b, botId) => {
if (!b.eliminated) {
if (b.answerRight) {
b.score += QUIZ_TF_POINTS_PER_CORRECT;
} else {
b.eliminated = true;
/* คัดออก → วาร์ปเข้าโซนผีทันที (เหมือนคนจริง) */
const gc = quizRandomCellInZone(mdLive.quizGhostArea, mdLive);
if (gc) { b.x = gc.x + 0.5; b.y = gc.y + 0.5; }
b.wanderTX = null; b.retargetAt = 0;
}
}
scores[botId] = b.score;
results.push({
id: botId, nickname: 'บอท', right: !!b.answerRight, choice: b.choice,
eliminated: !!b.eliminated, score: b.score,
});
b.tx = null; b.ty = null; /* รีเซ็ตเป้า → เดินมั่วจนข้อถัดไป */
});
}
io.to(sid).emit('quiz-result', {
questionIndex: idx + 1,
correctTrue,
@@ -4505,9 +4590,141 @@ function startQuizGame(sid, space, md) {
players,
quizMapMd: md,
};
space.quizSession.bots = createQuizBots(space, md);
scheduleQuizReadPhase(sid, space, md);
}
/* ===== MG1 quiz bots server-authoritative (roster + + + ) =====
เด host เด+ดคะแนนบอทเอง host หล = บอทหย + คะแนนเพยน. ายมา server บอทเดนเอง time-based + คะแนน server เปนเจาของ
id `__pv_bot_<slot>` 0..N-1 (N = effectiveBotSlotCount) ตรงก client */
const QUIZ_BOT_PREFIX = '__pv_bot_';
const QUIZ_BOT_SPEED_PER_SEC = 0.15 * 1.28 * 60; /* ~11.5 u/s ใกล้ความเร็วบอทเดิม */
function quizBotTierForSlot(i) {
const r = ((i * 73 + 17) % 100) / 100; /* deterministic per slot */
if (r < 0.30) return 'sharp';
if (r < 0.75) return 'avg';
return 'weak';
}
function quizBotCorrectProb(tier) {
return tier === 'sharp' ? 0.84 : tier === 'weak' ? 0.22 : 0.52;
}
function quizTileWalkableServer(md, x, y) {
const w = md.width || 20, h = md.height || 15;
const tx = Math.floor(x), ty = Math.floor(y);
if (tx < 0 || tx >= w || ty < 0 || ty >= h) return false;
const ob = md.objects && md.objects[ty] ? md.objects[ty][tx] : 0;
return ob !== 1;
}
function quizCellInGrid(grid, x, y) {
if (!Array.isArray(grid)) return false;
const tx = Math.floor(x), ty = Math.floor(y);
return !!(grid[ty] && Number(grid[ty][tx]) === 1);
}
function quizRandomCellInZone(grid, md) {
if (!Array.isArray(grid)) return null;
const w = md.width || 20, h = md.height || 15;
const pool = [];
for (let y = 0; y < h; y++) {
const row = grid[y];
if (!row) continue;
for (let x = 0; x < w; x++) {
if (Number(row[x]) === 1 && quizTileWalkableServer(md, x + 0.5, y + 0.5)) pool.push({ x, y });
}
}
if (!pool.length) return null;
return pool[Math.floor(Math.random() * pool.length)];
}
function createQuizBots(space, md) {
const botCount = effectiveBotSlotCount(space);
const humans = space.peers ? space.peers.size : 0;
const bots = new Map();
for (let i = 0; i < botCount; i++) {
const id = QUIZ_BOT_PREFIX + i;
const sp = quizWrongAnswerRespawnPosition(md, humans + i);
bots.set(id, {
tier: quizBotTierForSlot(i),
x: Number(sp.x), y: Number(sp.y), dir: 'down', isWalking: false,
score: 0, eliminated: false, choice: null, answerRight: false,
tx: null, ty: null, wanderTX: null, wanderTY: null, retargetAt: 0,
});
}
return bots;
}
/* ตัดสินคำตอบบอทแต่ละข้อ (สุ่มตาม tier เดิม) + ตั้งเป้าเดินไปโซนนั้น — ข้ามบอทที่ถูกคัดออกแล้ว */
function quizBotsDecideAnswers(space, md, correctTrue) {
const sess = space.quizSession;
if (!sess || !sess.bots) return;
const tGrid = md.quizTrueArea || [], fGrid = md.quizFalseArea || [];
sess.bots.forEach((b) => {
b.choice = null; b.answerRight = false; b.tx = null; b.ty = null;
if (b.eliminated) return;
if (Math.random() < 0.14) return; /* เดินมั่ว = ไม่ตอบ = ผิด */
const wantsCorrect = Math.random() < quizBotCorrectProb(b.tier);
const targetTrue = wantsCorrect ? correctTrue : !correctTrue;
b.choice = targetTrue;
b.answerRight = (targetTrue === correctTrue);
const cell = quizRandomCellInZone(targetTrue ? tGrid : fGrid, md);
if (cell) { b.tx = cell.x + 0.5; b.ty = cell.y + 0.5; }
});
}
function stepQuizBots(sid, space, dt, now) {
const sess = space.quizSession;
if (!sess || !sess.active || !sess.bots || sess.bots.size === 0) return;
const md = sess.quizMapMd;
if (!md) return;
const w = md.width || 20, h = md.height || 15;
const step = QUIZ_BOT_SPEED_PER_SEC * dt;
const answering = sess.phase === 'answer';
const ghostGrid = md.quizGhostArea;
sess.bots.forEach((b) => {
/* บอทถูกคัดออก (ตอบผิด) = "ผี" → ขังในโซนผี เดินออกไม่ได้ (เหมือนคนจริง) */
const confineGhost = b.eliminated && Array.isArray(ghostGrid);
const canWalk = (x, y) => quizTileWalkableServer(md, x, y) && (!confineGhost || quizCellInGrid(ghostGrid, x, y));
/* hard-snap: ถ้าผีอยู่นอกโซนผี (warp พลาด/ติดขอบ) → ดึงกลับเข้าโซนทันทีทุก tick (กันผีหลุดออกสนาม) */
if (confineGhost && !quizCellInGrid(ghostGrid, b.x, b.y)) {
const gc = quizRandomCellInZone(ghostGrid, md);
if (gc) { b.x = gc.x + 0.5; b.y = gc.y + 0.5; b.wanderTX = null; b.retargetAt = 0; }
}
let tgtX = b.tx, tgtY = b.ty;
if (b.eliminated || !answering || tgtX == null) {
/* ถูกคัดออก / ไม่ใช่ช่วงตอบ / บอทไม่ตอบ → เดินมั่ว (ผี = มั่วในโซนผี) */
const arrived = (typeof b.wanderTX === 'number') && Math.hypot(b.wanderTX - b.x, b.wanderTY - b.y) < 0.5;
if (typeof b.wanderTX !== 'number' || arrived || now >= b.retargetAt) {
if (confineGhost) {
const c = quizRandomCellInZone(ghostGrid, md);
b.wanderTX = c ? c.x + 0.5 : b.x;
b.wanderTY = c ? c.y + 0.5 : b.y;
} else {
b.wanderTX = 1 + Math.random() * Math.max(1, w - 2);
b.wanderTY = 1 + Math.random() * Math.max(1, h - 2);
}
b.retargetAt = now + 2000 + Math.floor(Math.random() * 3000);
}
tgtX = b.wanderTX; tgtY = b.wanderTY;
}
let dx = tgtX - b.x, dy = tgtY - b.y;
const dist = Math.hypot(dx, dy);
if (dist < 0.05) { b.isWalking = false; return; }
dx /= dist; dy /= dist;
if (Math.abs(dy) > Math.abs(dx)) b.dir = dy > 0 ? 'down' : 'up';
else b.dir = dx > 0 ? 'right' : 'left';
const sx = Math.min(step, dist);
const ox = b.x, oy = b.y;
const nx = b.x + dx * sx, ny = b.y + dy * sx;
if (canWalk(nx, ny)) { b.x = nx; b.y = ny; }
else if (canWalk(nx, b.y)) { b.x = nx; }
else if (canWalk(b.x, ny)) { b.y = ny; }
b.isWalking = Math.abs(b.x - ox) > 1e-5 || Math.abs(b.y - oy) > 1e-5;
});
const arr = [];
sess.bots.forEach((b, id) => arr.push({
id, x: Math.round(b.x * 1000) / 1000, y: Math.round(b.y * 1000) / 1000,
direction: b.dir || 'down', isWalking: !!b.isWalking, elim: !!b.eliminated,
}));
if (arr.length) io.to(sid).emit('quiz-bot-move', { bots: arr });
}
function safeMapId(id) {
return (id || '').replace(/[^a-z0-9_-]/gi, '') || null;
}
@@ -6717,6 +6934,202 @@ function findFallbackLobbyMapForGauntletEnd() {
return null;
}
/* ===== Lobby authoritative (server LobbyA/B) =====================
เด: บอท lobby เดนบน "host client" (frame-based) แล broadcast บอทวงเรวชาตางกนตาม FPS/host
+ เลนออกแล client นไมได user-left = าง
ใหม: server เดนบอทเอง (time-based, ความเรวเดยวทกเครอง) + roster snapshot ให client reconcile (าผ)
bot id = '__lobby_bot_<slot>' (ตรงก client LOBBY_BOT_PREFIX) client map /วละครไดกต */
const LOBBY_BOT_PREFIX = '__lobby_bot_';
const LOBBY_MOVE_SPEED_PER_SEC = 0.15 * 60; /* ตรงกับ client MOVE_SPEED_PER_SEC (0.15/เฟรม × 60fps) */
function lobbyMapOfSpace(space) {
const md = (space.mapId && maps.get(space.mapId)) || space.mapData;
return (md && md.gameType === 'lobby') ? md : null;
}
/* จุดเกิดผู้เล่น 6 ช่อง (mirror client parseLobbyPlayerSpawnsFromMapLobby) — บอทเกิดที่ช่องเดียวกับคน */
function parseLobbyPlayerSpawnsServer(md) {
const w = md.width || 20, h = md.height || 15;
const out = [null, null, null, null, null, null];
const raw = md && md.lobbyPlayerSpawns;
if (!Array.isArray(raw)) return out;
for (let i = 0; i < 6 && i < raw.length; i++) {
const cell = raw[i];
if (!cell || typeof cell !== 'object') continue;
const x = Math.floor(Number(cell.x));
const y = Math.floor(Number(cell.y));
if (!Number.isFinite(x) || !Number.isFinite(y)) continue;
if (x < 0 || x >= w || y < 0 || y >= h) continue;
out[i] = { x, y };
}
return out;
}
/* mirror client canWalkLobbyBot : objects===1 ( tile );
tile blockPlayer===1 = ามท peer/บอทตวอ (tile ปกตบได)
หมายเหต: ามจำกดดวย spawnArea นค "จุดเกิด" ไมใช "พื้นที่เดิน" (เคยทำใหบอทตดอยบท) */
function lobbyTileWalkable(md, space, x, y, selfBotId) {
const w = md.width || 20, h = md.height || 15;
const tx = Math.floor(x), ty = Math.floor(y);
if (tx < 0 || tx >= w || ty < 0 || ty >= h) return false;
const ob = md.objects && md.objects[ty] ? md.objects[ty][tx] : 0;
if (ob === 1) return false;
const bp = md.blockPlayer;
if (bp && bp[ty] && bp[ty][tx] === 1) {
for (const p of space.peers.values()) {
if (p && Math.floor(p.x) === tx && Math.floor(p.y) === ty) return false;
}
if (space.lobbyBots) {
for (const [bid, b] of space.lobbyBots) {
if (bid === selfBotId) continue;
if (Math.floor(b.x) === tx && Math.floor(b.y) === ty) return false;
}
}
}
return true;
}
/* "" (slotOrd = humans + botIndex , )
mirror client pickLobbySpawnForJoin: slots6 lobbyPlayerSpawns[j], fixed md.spawn */
function pickLobbyBotSpawnServer(md, space, slotOrd) {
const w = md.width || 20, h = md.height || 15;
const mode = md.lobbySpawnMode;
const ord = slotOrd | 0;
if (mode === 'slots6') {
const j = Math.min(Math.max(0, ord), 5);
const slots = parseLobbyPlayerSpawnsServer(md);
const pick = slots[j];
if (pick) return { x: pick.x, y: pick.y };
} else if (mode === 'fixed' && md.spawn) {
const fx = Math.floor(Number(md.spawn.x));
const fy = Math.floor(Number(md.spawn.y));
if (Number.isFinite(fx) && Number.isFinite(fy)) return { x: Math.max(0, Math.min(w - 1, fx)), y: Math.max(0, Math.min(h - 1, fy)) };
}
/* fallback: หาช่อง spawn ที่ define ไว้ตัวแรก ๆ แล้วค่อยสุ่ม tile ที่ไม่ใช่กำแพง */
const slots = parseLobbyPlayerSpawnsServer(md);
const defined = slots.filter(Boolean);
if (defined.length) { const s = defined[Math.min(ord, defined.length - 1)]; return { x: s.x, y: s.y }; }
for (let i = 0; i < 24; i++) {
const x = 1 + Math.floor(Math.random() * Math.max(1, w - 2));
const y = 1 + Math.floor(Math.random() * Math.max(1, h - 2));
if (lobbyTileWalkable(md, space, x, y, null)) return { x, y };
}
const sp = md.spawn;
if (sp && Number.isFinite(Number(sp.x)) && Number.isFinite(Number(sp.y))) return { x: Math.floor(Number(sp.x)), y: Math.floor(Number(sp.y)) };
return { x: 1, y: 1 };
}
/* เดินบอท lobby ของ space เดียว (เรียกจาก sweeper ทุก ~60ms) — time-based, ความเร็วคงที่ */
function stepLobbyBotsForSpace(sid, space, dt, nowMs) {
const md = lobbyMapOfSpace(space);
const botCount = md ? effectiveBotSlotCount(space) : 0;
const humans = space.peers ? space.peers.size : 0;
if (!md || botCount <= 0 || humans <= 0) {
if (space.lobbyBots) space.lobbyBots = null;
return;
}
if (!space.lobbyBots) space.lobbyBots = new Map();
const bots = space.lobbyBots;
/* ปรับจำนวนบอทให้ตรง botCount (id ตาม slot) — เกิดที่ช่องผู้เล่น humans+i (ไม่ทับคน/ไม่ทับกัน) */
for (let i = 0; i < botCount; i++) {
const id = LOBBY_BOT_PREFIX + i;
if (!bots.has(id)) {
const sp = pickLobbyBotSpawnServer(md, space, humans + i);
bots.set(id, { x: sp.x, y: sp.y, direction: 'down', isWalking: false, wTX: null, wTY: null, retargetAt: 0, pauseUntil: 0 });
}
}
for (const id of [...bots.keys()]) {
const slot = parseInt(id.slice(LOBBY_BOT_PREFIX.length), 10);
if (!(slot >= 0 && slot < botCount)) bots.delete(id);
}
const w = md.width || 20, h = md.height || 15;
const step = LOBBY_MOVE_SPEED_PER_SEC * dt;
bots.forEach((b, id) => {
const arrived = (typeof b.wTX === 'number') && Math.hypot(b.wTX - b.x, b.wTY - b.y) < 0.5;
if (typeof b.wTX !== 'number' || arrived || nowMs >= b.retargetAt) {
/* เป้า wander = สุ่มทั้งแมป (เหมือน client เดิม) — การเดินถูกจำกัดด้วยกำแพงอยู่แล้ว */
b.wTX = 1 + Math.random() * Math.max(1, w - 2);
b.wTY = 1 + Math.random() * Math.max(1, h - 2);
b.retargetAt = nowMs + 3000 + Math.floor(Math.random() * 4500);
b.pauseUntil = (arrived && Math.random() < 0.45) ? nowMs + 500 + Math.floor(Math.random() * 1600) : 0;
}
if (b.pauseUntil && nowMs < b.pauseUntil) { b.isWalking = false; return; }
let dx = b.wTX - b.x, dy = b.wTY - b.y;
const dist = Math.hypot(dx, dy) || 1;
dx /= dist; dy /= dist;
if (Math.abs(dy) > Math.abs(dx)) b.direction = dy > 0 ? 'down' : 'up';
else b.direction = dx > 0 ? 'right' : 'left';
const ox = b.x, oy = b.y;
const nx = b.x + dx * step, ny = b.y + dy * step;
if (lobbyTileWalkable(md, space, nx, ny, id)) { b.x = nx; b.y = ny; }
else if (lobbyTileWalkable(md, space, nx, b.y, id)) { b.x = nx; }
else if (lobbyTileWalkable(md, space, b.x, ny, id)) { b.y = ny; }
else { b.retargetAt = 0; } /* ติด → หาเป้าใหม่เฟรมหน้า */
b.x = Math.max(0, Math.min(w - 0.01, b.x));
b.y = Math.max(0, Math.min(h - 0.01, b.y));
b.isWalking = Math.abs(b.x - ox) > 1e-5 || Math.abs(b.y - oy) > 1e-5;
});
const arr = [];
bots.forEach((b, id) => arr.push({
id,
x: Math.round(b.x * 1000) / 1000,
y: Math.round(b.y * 1000) / 1000,
direction: b.direction || 'down',
isWalking: !!b.isWalking,
}));
if (arr.length) io.to(sid).emit('lobby-bot-move', { bots: arr });
/* roster snapshot (L3 ฆ่าผี) — ทุก ~1.5s ส่ง id ผู้เล่นจริงทั้งหมด ให้ client ตัดตัวที่ไม่อยู่ทิ้ง */
if (!space.lobbyRosterSyncTs || nowMs - space.lobbyRosterSyncTs > 1500) {
space.lobbyRosterSyncTs = nowMs;
emitLobbyRosterSync(sid, space);
}
}
function emitLobbyRosterSync(sid, space) {
if (!space || !space.peers) return;
const ids = [...space.peers.keys()];
io.to(sid).emit('lobby-roster', { ids });
}
let lobbyBotSweeperTs = 0;
function lobbyBotSweepTick() {
const now = Date.now();
let dt = lobbyBotSweeperTs ? (now - lobbyBotSweeperTs) / 1000 : 0.06;
if (!(dt > 0)) dt = 0.06;
if (dt > 0.2) dt = 0.2;
lobbyBotSweeperTs = now;
for (const [sid, space] of spaces) {
try { stepLobbyBotsForSpace(sid, space, dt, now); } catch (e) { /* กัน 1 ห้องพังทั้ง sweeper */ }
}
}
setInterval(lobbyBotSweepTick, 60);
/* roster heartbeat (gameType != lobby) client (play.js) "" (peer roster )
แก: คนเดยวม avatar 2 (นเกาคางตอน reconnect/ออก เพราะ others เป add-only ไมเคย prune) */
setInterval(() => {
for (const [sid, space] of spaces) {
if (!space || !space.peers || space.peers.size === 0) continue;
const md = (space.mapId && maps.get(space.mapId)) || space.mapData;
if (!md || md.gameType === 'lobby') continue; /* lobby ใช้ lobby-roster แยก */
try { io.to(sid).emit('play-roster', { ids: [...space.peers.keys()] }); } catch (e) { /* กัน 1 ห้องล้ม */ }
}
}, 1500);
/* เดินบอท MG1 quiz บน server (time-based) → บอทเดินเองไม่พึ่ง host (host หลุดก็ไม่หยุด) */
let quizBotSweepTs = 0;
setInterval(() => {
const now = Date.now();
let dt = quizBotSweepTs ? (now - quizBotSweepTs) / 1000 : 0.06;
if (!(dt > 0)) dt = 0.06;
if (dt > 0.2) dt = 0.2;
quizBotSweepTs = now;
for (const [sid, space] of spaces) {
const sess = space && space.quizSession;
if (!sess || !sess.active || !sess.bots || sess.bots.size === 0) continue;
try { stepQuizBots(sid, space, dt, now); } catch (e) { /* กัน 1 ห้องล้ม */ }
}
}, 60);
/** หมดเวลา Gauntlet — หยุด tick, คืนแผนที่ lobby, แจ้งไคลเอนต์ */
function endGauntletGame(sid, space, reason) {
const md = (space.mapId && maps.get(space.mapId)) || space.mapData;
@@ -8129,24 +8542,9 @@ io.on('connection', (socket) => {
/* lobby client: host relay
( desync จากการทแตละเครองสมเดนบอทแยกก) */
socket.on('lobby-bot-move', (data) => {
const sid = socket.data.spaceId;
const space = sid ? spaces.get(sid) : null;
if (!space || space.hostId !== socket.id) return; /* เฉพาะ host เท่านั้น */
if (!data || !Array.isArray(data.bots) || data.bots.length > 16) return;
const bots = [];
for (const b of data.bots) {
if (!b || typeof b.id !== 'string' || b.id.length > 40) continue;
const x = Number(b.x), y = Number(b.y);
if (!Number.isFinite(x) || !Number.isFinite(y)) continue;
bots.push({
id: b.id, x, y,
direction: typeof b.direction === 'string' ? b.direction.slice(0, 5) : 'down',
isWalking: !!b.isWalking,
});
}
if (bots.length) socket.to(sid).emit('lobby-bot-move', { bots });
});
/* DEPRECATED: server lobby (stepLobbyBotsForSpace/lobbyBotSweepTick)
ไม relay ตำแหนงบอทจาก client ( host เวอรนเกาฉดตำแหนงชนก server tick = บอทกระต/2 แหล) */
socket.on('lobby-bot-move', () => { /* no-op: server-authoritative */ });
/* fill-bot 7 : host state relay
( desync จากการทแตละเครองจำลองบอทแยกก) */
@@ -9254,6 +9652,7 @@ io.on('connection', (socket) => {
}
space.gauntletCrownLobbyReady[socket.id] = !!(data && data.ready);
io.to(sid).emit('gauntlet-crown-lobby-sync', crownLobbySyncPayload(space));
/* หมายเหตุ: host (ผู้เล่นจริง) เป็นคนกด START เอง — ไม่ auto-start (ตามที่ต้องการให้ host คุมจังหวะเริ่ม) */
});
socket.on('gauntlet-crown-lobby-start', (_data, cb) => {
@@ -9275,22 +9674,7 @@ io.on('connection', (socket) => {
}
const allReady = humanIds.length > 0 && humanIds.every((id) => rm[id]);
if (!allReady) return reply({ ok: false, error: 'ยังมีผู้เล่นที่ยังไม่ Ready' });
/* เวลาเริ่มเล่นจริงร่วมกัน (server epoch) → ทุก client นับ 3-2-1 ไปหาจุดนี้ → GO พร้อมกัน */
const liveBeginsAt = Date.now() + LIVE_COUNTDOWN_MS;
space.missionLiveBeginsAt = liveBeginsAt;
if (isQuizQuestionMissionShellSpace(space)) {
/* quiz: เลื่อน server timer ไปเริ่มที่ liveBeginsAt (ไม่ใช่ทันที) ให้ตรงกับตอน client จบ 3-2-1 */
setTimeout(() => {
const sp = spaces.get(sid);
if (!sp) return;
const md2 = maps.get(sp.mapId) || sp.mapData;
if (md2 && md2.gameType === 'quiz') {
clearSpaceQuizTimers(sp);
startQuizGame(sid, sp, md2);
}
}, LIVE_COUNTDOWN_MS);
}
io.to(sid).emit('gauntlet-crown-lobby-started', { liveBeginsAt });
performCrownLobbyStart(sid, space);
reply({ ok: true });
});
@@ -9426,6 +9810,28 @@ io.on('connection', (socket) => {
if (sc !== (p.quizCarryScore | 0)) moveForceEmit = true;
p.quizCarryScore = sc;
}
/* L2 server clamp ( lobby): move /
เผ jitter/lag burst วย factor 3 + ฐาน 0.5 (move ปกต ~12.5Hz เดนแค ~0.72u อยใตเพดานสบาย)
ไมแตะมเกม (กสตก/กระโดดเรวกวาน) */
if (p && md && md.gameType === 'lobby') {
const tnow = Date.now();
const tlast = (typeof p.lastLobbyMoveTs === 'number') ? p.lastLobbyMoveTs : 0;
let edt = tlast ? (tnow - tlast) / 1000 : 0.1;
if (!(edt > 0)) edt = 0.1;
if (edt > 0.5) edt = 0.5;
p.lastLobbyMoveTs = tnow;
const maxDist = LOBBY_MOVE_SPEED_PER_SEC * edt * 3 + 0.5;
const ddx = Number(nx) - Number(p.x);
const ddy = Number(ny) - Number(p.y);
if (Number.isFinite(ddx) && Number.isFinite(ddy)) {
const dlen = Math.hypot(ddx, ddy);
if (dlen > maxDist && dlen > 0) {
const s = maxDist / dlen;
nx = Number(p.x) + ddx * s;
ny = Number(p.y) + ddy * s;
}
}
}
if (p) {
const prevX = Number(p.x);
const prevY = Number(p.y);
+756
View File
@@ -0,0 +1,756 @@
{"t":1782485466232,"cat":"LobbyA","room":"asdasd-1782485463133","who":"ผู้เล่น","ev":"lobby-open","detail":"space=asdasd-1782485463133 [+0ms]","src":"client"}
{"t":1782485466270,"cat":"LobbyA","room":"asdasd-1782485463133","who":"ผู้เล่น","ev":"preload-start","detail":" [+42ms]","src":"client"}
{"t":1782485466281,"cat":"LobbyA","room":"asdasd-1782485463133","who":"ผู้เล่น","ev":"manifest-done","detail":" [+44ms]","src":"client"}
{"t":1782485466299,"cat":"LobbyA","room":"asdasd-1782485463133","who":"ผู้เล่น","ev":"colors-resolved","detail":" [+48ms]","src":"client"}
{"t":1782485466301,"cat":"LobbyA","room":"asdasd-1782485463133","who":"ผู้เล่น","ev":"mychar-tinted","detail":"roomJoinReady=false [+50ms]","src":"client"}
{"t":1782485466311,"cat":"LobbyA","room":"asdasd-1782485463133","who":"ผู้เล่น","ev":"preload-ready(mychar)","detail":" [+51ms]","src":"client"}
{"t":1782485466316,"cat":"LobbyA","room":"asdasd-1782485463133","who":"ผู้เล่น","ev":"preload-occupants-done(bg)","detail":" [+52ms]","src":"client"}
{"t":1782485466396,"cat":"LobbyA","room":"asdasd-1782485463133","who":"ผู้เล่น","ev":"socket-connect","detail":" [+167ms]","src":"client"}
{"t":1782485466415,"cat":"LobbyA","room":"asdasd","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 5","src":"server"}
{"t":1782485467132,"cat":"LobbyA","room":"asdasd-1782485463133","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+897ms]","src":"client"}
{"t":1782485467133,"cat":"LobbyA","room":"asdasd-1782485463133","who":"ผู้เล่น","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=5 [+896ms]","src":"client"}
{"t":1782485921260,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"lobby-open","detail":"space=ฟหก-1782485917846 [+1ms]","src":"client"}
{"t":1782485921326,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"colors-resolved","detail":" [+22ms]","src":"client"}
{"t":1782485921327,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"manifest-done","detail":" [+21ms]","src":"client"}
{"t":1782485921328,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-start","detail":" [+21ms]","src":"client"}
{"t":1782485921372,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"mychar-tinted","detail":"roomJoinReady=false [+22ms]","src":"client"}
{"t":1782485921373,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-occupants-done(bg)","detail":" [+23ms]","src":"client"}
{"t":1782485921373,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-ready(mychar)","detail":" [+23ms]","src":"client"}
{"t":1782485921502,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"socket-connect","detail":" [+248ms]","src":"client"}
{"t":1782485921510,"cat":"LobbyA","room":"ฟหก","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 5","src":"server"}
{"t":1782485922760,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=5 [+1484ms]","src":"client"}
{"t":1782485922763,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1484ms]","src":"client"}
{"t":1782485952586,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+31334ms]","src":"client"}
{"t":1782485955632,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+34378ms]","src":"client"}
{"t":1782485970680,"cat":"MG1","room":"ฟหก","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782485971170,"cat":"MG1","room":"ฟหก","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 5","src":"server"}
{"t":1782487276421,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"lobby-open","detail":"space=ฟหก-1782485917846 [+0ms]","src":"client"}
{"t":1782487276467,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-start","detail":" [+25ms]","src":"client"}
{"t":1782487276468,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"manifest-done","detail":" [+26ms]","src":"client"}
{"t":1782487276468,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"colors-resolved","detail":" [+26ms]","src":"client"}
{"t":1782487276472,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"mychar-tinted","detail":"roomJoinReady=false [+27ms]","src":"client"}
{"t":1782487276476,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-ready(mychar)","detail":" [+27ms]","src":"client"}
{"t":1782487276508,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-occupants-done(bg)","detail":" [+28ms]","src":"client"}
{"t":1782487276587,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"socket-connect","detail":" [+152ms]","src":"client"}
{"t":1782487276631,"cat":"LobbyB","room":"ฟหก","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 5","src":"server"}
{"t":1782487277781,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1354ms]","src":"client"}
{"t":1782487277782,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"join-ok","detail":"peers=1 host=me map=mn8nx46h bots=5 [+1354ms]","src":"client"}
{"t":1782487329748,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"socket-connect","detail":" [+53325ms]","src":"client"}
{"t":1782487329751,"cat":"LobbyB","room":"ฟหก","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 5","src":"server"}
{"t":1782487330460,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"join-ok","detail":"peers=1 host=me map=mn8nx46h bots=5 [+54038ms]","src":"client"}
{"t":1782487448009,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"socket-connect","detail":" [+171590ms]","src":"client"}
{"t":1782487448050,"cat":"LobbyB","room":"ฟหก","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 5","src":"server"}
{"t":1782487457911,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"join-ok","detail":"peers=1 host=me map=mn8nx46h bots=5 [+181490ms]","src":"client"}
{"t":1782487468620,"cat":"MG1","room":"ฟหก","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782487469106,"cat":"MG1","room":"ฟหก","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 5","src":"server"}
{"t":1782487553205,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"lobby-open","detail":"space=ฟหก-1782485917846 [+1ms]","src":"client"}
{"t":1782487553247,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-start","detail":" [+32ms]","src":"client"}
{"t":1782487553248,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"manifest-done","detail":" [+33ms]","src":"client"}
{"t":1782487553265,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"colors-resolved","detail":" [+34ms]","src":"client"}
{"t":1782487553284,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"mychar-tinted","detail":"roomJoinReady=false [+34ms]","src":"client"}
{"t":1782487553289,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-ready(mychar)","detail":" [+35ms]","src":"client"}
{"t":1782487553292,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-occupants-done(bg)","detail":" [+35ms]","src":"client"}
{"t":1782487553356,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"socket-connect","detail":" [+152ms]","src":"client"}
{"t":1782487553363,"cat":"LobbyB","room":"ฟหก","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 5","src":"server"}
{"t":1782487554264,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"join-ok","detail":"peers=1 host=me map=mn8nx46h bots=5 [+1058ms]","src":"client"}
{"t":1782487554282,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1058ms]","src":"client"}
{"t":1782487567925,"cat":"MG1","room":"ฟหก","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782487568405,"cat":"MG1","room":"ฟหก","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 5","src":"server"}
{"t":1782487736092,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"lobby-open","detail":"space=ฟหก-1782485917846 [+1ms]","src":"client"}
{"t":1782487736130,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-start","detail":" [+41ms]","src":"client"}
{"t":1782487736147,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"manifest-done","detail":" [+41ms]","src":"client"}
{"t":1782487736151,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"colors-resolved","detail":" [+43ms]","src":"client"}
{"t":1782487736154,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"mychar-tinted","detail":"roomJoinReady=false [+43ms]","src":"client"}
{"t":1782487736165,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-ready(mychar)","detail":" [+43ms]","src":"client"}
{"t":1782487736171,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"preload-occupants-done(bg)","detail":" [+44ms]","src":"client"}
{"t":1782487736267,"cat":"LobbyA","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"socket-connect","detail":" [+148ms]","src":"client"}
{"t":1782487736281,"cat":"LobbyB","room":"ฟหก","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 5","src":"server"}
{"t":1782487737039,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"join-ok","detail":"peers=1 host=me map=mn8nx46h bots=5 [+932ms]","src":"client"}
{"t":1782487737040,"cat":"LobbyB","room":"ฟหก-1782485917846","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+933ms]","src":"client"}
{"t":1782487755234,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"lobby-open","detail":"space=aaa-1782487752214 [+0ms]","src":"client"}
{"t":1782487755281,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"preload-start","detail":" [+19ms]","src":"client"}
{"t":1782487755340,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"manifest-done","detail":" [+113ms]","src":"client"}
{"t":1782487755356,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"colors-resolved","detail":" [+114ms]","src":"client"}
{"t":1782487755369,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"socket-connect","detail":" [+139ms]","src":"client"}
{"t":1782487755372,"cat":"LobbyA","room":"aaa","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 4","src":"server"}
{"t":1782487756339,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=4 [+1069ms]","src":"client"}
{"t":1782487761813,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"preload-ready(mychar)","detail":" [+6594ms]","src":"client"}
{"t":1782487761814,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+6593ms]","src":"client"}
{"t":1782487761814,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+6594ms]","src":"client"}
{"t":1782487764807,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"lobby-open","detail":"space=aaa-1782487752214 [+0ms]","src":"client"}
{"t":1782487764913,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"preload-start","detail":" [+95ms]","src":"client"}
{"t":1782487764917,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"colors-resolved","detail":" [+96ms]","src":"client"}
{"t":1782487764917,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"manifest-done","detail":" [+95ms]","src":"client"}
{"t":1782487764919,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+97ms]","src":"client"}
{"t":1782487764928,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"preload-ready(mychar)","detail":" [+97ms]","src":"client"}
{"t":1782487764957,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"preload-occupants-done(bg)","detail":" [+98ms]","src":"client"}
{"t":1782487765013,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"socket-connect","detail":" [+216ms]","src":"client"}
{"t":1782487765038,"cat":"LobbyA","room":"aaa","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782487767767,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=4 [+2968ms]","src":"client"}
{"t":1782487767768,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+2972ms]","src":"client"}
{"t":1782487770369,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"preload-occupants-done(bg)","detail":" [+15150ms]","src":"client"}
{"t":1782487793240,"cat":"LobbyA","room":"aaa-1782487752214","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+28445ms]","src":"client"}
{"t":1782487793244,"cat":"LobbyA","room":"aaa-1782487752214","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+38024ms]","src":"client"}
{"t":1782487797143,"cat":"LobbyB","room":"aaa-1782487752214","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+41925ms]","src":"client"}
{"t":1782487798748,"cat":"LobbyB","room":"aaa-1782487752214","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+33953ms]","src":"client"}
{"t":1782487800364,"cat":"MG1","room":"aaa","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782487800484,"cat":"MG1","room":"aaa","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782487800485,"cat":"MG1","room":"aaa","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782487800749,"cat":"MG1","room":"aaa","who":"MONE","ev":"join","detail":"สี#5 · คน 1 + บอท 4","src":"server"}
{"t":1782487800842,"cat":"MG1","room":"aaa","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782488777338,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"lobby-open","detail":"space=ฟฟ-1782488774092 [+0ms]","src":"client"}
{"t":1782488777343,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"preload-start","detail":" [+34ms]","src":"client"}
{"t":1782488777377,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"manifest-done","detail":" [+35ms]","src":"client"}
{"t":1782488777381,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"colors-resolved","detail":" [+37ms]","src":"client"}
{"t":1782488777388,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"preload-occupants-done(bg)","detail":" [+40ms]","src":"client"}
{"t":1782488777389,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"mychar-tinted","detail":"roomJoinReady=false [+39ms]","src":"client"}
{"t":1782488777389,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"preload-ready(mychar)","detail":" [+39ms]","src":"client"}
{"t":1782488777482,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"socket-connect","detail":" [+162ms]","src":"client"}
{"t":1782488777501,"cat":"LobbyA","room":"ฟฟ","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 4","src":"server"}
{"t":1782488778591,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=4 [+1280ms]","src":"client"}
{"t":1782488778594,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1281ms]","src":"client"}
{"t":1782488778907,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"lobby-open","detail":"space=ฟฟ-1782488774092 [+0ms]","src":"client"}
{"t":1782488778952,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"preload-start","detail":" [+55ms]","src":"client"}
{"t":1782488779022,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"manifest-done","detail":" [+119ms]","src":"client"}
{"t":1782488779025,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"colors-resolved","detail":" [+120ms]","src":"client"}
{"t":1782488779043,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"socket-connect","detail":" [+145ms]","src":"client"}
{"t":1782488779065,"cat":"LobbyA","room":"ฟฟ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782488779963,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=4 [+1057ms]","src":"client"}
{"t":1782488787594,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+8693ms]","src":"client"}
{"t":1782488787598,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"preload-ready(mychar)","detail":" [+8693ms]","src":"client"}
{"t":1782488787599,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+8693ms]","src":"client"}
{"t":1782488799933,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"preload-occupants-done(bg)","detail":" [+21030ms]","src":"client"}
{"t":1782488812517,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+33618ms]","src":"client"}
{"t":1782488812531,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+35221ms]","src":"client"}
{"t":1782488816357,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+39049ms]","src":"client"}
{"t":1782488817616,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+38716ms]","src":"client"}
{"t":1782488819547,"cat":"MG1","room":"ฟฟ","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782488819655,"cat":"MG1","room":"ฟฟ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782488820027,"cat":"MG1","room":"ฟฟ","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 4","src":"server"}
{"t":1782488820284,"cat":"MG1","room":"ฟฟ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782488905740,"cat":"LobbyB","room":"ฟฟ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782488906089,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"lobby-open","detail":"space=ฟฟ-1782488774092 [+0ms]","src":"client"}
{"t":1782488906110,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"preload-start","detail":" [+15ms]","src":"client"}
{"t":1782488906170,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"manifest-done","detail":" [+101ms]","src":"client"}
{"t":1782488906172,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"colors-resolved","detail":" [+101ms]","src":"client"}
{"t":1782488906196,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"Q","ev":"socket-connect","detail":" [+126ms]","src":"client"}
{"t":1782488906243,"cat":"LobbyB","room":"ฟฟ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782488907119,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"Q","ev":"join-ok","detail":"peers=2 host=other map=mn8nx46h bots=4 [+1025ms]","src":"client"}
{"t":1782488907254,"cat":"LobbyB","room":"ฟฟ","who":"ผู้เล่น","ev":"host-change","detail":"host ใหม่ → Q","src":"server"}
{"t":1782488907254,"cat":"LobbyB","room":"ฟฟ","who":"ผู้เล่น","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782488907673,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"lobby-open","detail":"space=ฟฟ-1782488774092 [+0ms]","src":"client"}
{"t":1782488907713,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"preload-start","detail":" [+29ms]","src":"client"}
{"t":1782488907717,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"manifest-done","detail":" [+30ms]","src":"client"}
{"t":1782488907720,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"colors-resolved","detail":" [+30ms]","src":"client"}
{"t":1782488907752,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"mychar-tinted","detail":"roomJoinReady=false [+31ms]","src":"client"}
{"t":1782488907753,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"preload-occupants-done(bg)","detail":" [+31ms]","src":"client"}
{"t":1782488907753,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"preload-ready(mychar)","detail":" [+31ms]","src":"client"}
{"t":1782488907817,"cat":"LobbyA","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"socket-connect","detail":" [+146ms]","src":"client"}
{"t":1782488907870,"cat":"LobbyB","room":"ฟฟ","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782488908590,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+879ms]","src":"client"}
{"t":1782488908592,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"join-ok","detail":"peers=2 host=me map=mn8nx46h bots=4 [+878ms]","src":"client"}
{"t":1782488912393,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+6319ms]","src":"client"}
{"t":1782488912393,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"Q","ev":"preload-ready(mychar)","detail":" [+6320ms]","src":"client"}
{"t":1782488912399,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+6320ms]","src":"client"}
{"t":1782488919231,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"Q","ev":"preload-occupants-done(bg)","detail":" [+13153ms]","src":"client"}
{"t":1782490717978,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"ผู้เล่น","ev":"socket-connect","detail":" [+1810313ms]","src":"client"}
{"t":1782490718111,"cat":"LobbyB","room":"ฟฟ-1782488774092","who":"Q","ev":"socket-connect","detail":" [+1812043ms]","src":"client"}
{"t":1782490870250,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"lobby-open","detail":"space=addd-1782490867179 [+0ms]","src":"client"}
{"t":1782490870331,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"preload-start","detail":" [+83ms]","src":"client"}
{"t":1782490870331,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"manifest-done","detail":" [+84ms]","src":"client"}
{"t":1782490870349,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"colors-resolved","detail":" [+85ms]","src":"client"}
{"t":1782490870350,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"mychar-tinted","detail":"roomJoinReady=false [+86ms]","src":"client"}
{"t":1782490870362,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"preload-ready(mychar)","detail":" [+86ms]","src":"client"}
{"t":1782490870369,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"preload-occupants-done(bg)","detail":" [+87ms]","src":"client"}
{"t":1782490870437,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"socket-connect","detail":" [+188ms]","src":"client"}
{"t":1782490870442,"cat":"LobbyA","room":"addd","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 3","src":"server"}
{"t":1782490871242,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+994ms]","src":"client"}
{"t":1782490871245,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=3 [+994ms]","src":"client"}
{"t":1782490876810,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"lobby-open","detail":"space=addd-1782490867179 [+0ms]","src":"client"}
{"t":1782490876853,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"preload-start","detail":" [+14ms]","src":"client"}
{"t":1782490876906,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"manifest-done","detail":" [+97ms]","src":"client"}
{"t":1782490876929,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"colors-resolved","detail":" [+97ms]","src":"client"}
{"t":1782490876951,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"socket-connect","detail":" [+141ms]","src":"client"}
{"t":1782490876950,"cat":"LobbyA","room":"addd","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782490877858,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=3 [+1035ms]","src":"client"}
{"t":1782490881939,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+5130ms]","src":"client"}
{"t":1782490881940,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+5130ms]","src":"client"}
{"t":1782490881941,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"preload-ready(mychar)","detail":" [+5130ms]","src":"client"}
{"t":1782490891731,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"preload-occupants-done(bg)","detail":" [+14920ms]","src":"client"}
{"t":1782490899421,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+22614ms]","src":"client"}
{"t":1782490900859,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+30582ms]","src":"client"}
{"t":1782490902100,"cat":"LobbyB","room":"addd-1782490867179","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+25289ms]","src":"client"}
{"t":1782490906626,"cat":"LobbyB","room":"addd-1782490867179","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+36375ms]","src":"client"}
{"t":1782490915541,"cat":"MG1","room":"addd","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782490915662,"cat":"MG1","room":"addd","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782490915970,"cat":"MG1","room":"addd","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 3","src":"server"}
{"t":1782490916005,"cat":"MG1","room":"addd","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782491000516,"cat":"LobbyB","room":"addd","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782491000771,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"lobby-open","detail":"space=addd-1782490867179 [+0ms]","src":"client"}
{"t":1782491000796,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"preload-start","detail":" [+17ms]","src":"client"}
{"t":1782491000859,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"manifest-done","detail":" [+109ms]","src":"client"}
{"t":1782491000861,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"colors-resolved","detail":" [+109ms]","src":"client"}
{"t":1782491000905,"cat":"LobbyA","room":"addd-1782490867179","who":"Q","ev":"socket-connect","detail":" [+136ms]","src":"client"}
{"t":1782491000953,"cat":"LobbyB","room":"addd","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782491001976,"cat":"LobbyB","room":"addd-1782490867179","who":"Q","ev":"join-ok","detail":"peers=2 host=other map=mn8nx46h bots=3 [+1215ms]","src":"client"}
{"t":1782491006068,"cat":"LobbyB","room":"addd-1782490867179","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+5311ms]","src":"client"}
{"t":1782491006068,"cat":"LobbyB","room":"addd-1782490867179","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+5311ms]","src":"client"}
{"t":1782491006070,"cat":"LobbyB","room":"addd-1782490867179","who":"Q","ev":"preload-ready(mychar)","detail":" [+5311ms]","src":"client"}
{"t":1782491007055,"cat":"LobbyB","room":"addd","who":"ผู้เล่น","ev":"host-change","detail":"host ใหม่ → Q","src":"server"}
{"t":1782491007055,"cat":"LobbyB","room":"addd","who":"ผู้เล่น","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782491007445,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"lobby-open","detail":"space=addd-1782490867179 [+0ms]","src":"client"}
{"t":1782491007509,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"preload-start","detail":" [+70ms]","src":"client"}
{"t":1782491007511,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"manifest-done","detail":" [+70ms]","src":"client"}
{"t":1782491007515,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"colors-resolved","detail":" [+72ms]","src":"client"}
{"t":1782491007519,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"mychar-tinted","detail":"roomJoinReady=false [+72ms]","src":"client"}
{"t":1782491007522,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"preload-ready(mychar)","detail":" [+73ms]","src":"client"}
{"t":1782491007549,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"preload-occupants-done(bg)","detail":" [+73ms]","src":"client"}
{"t":1782491007610,"cat":"LobbyA","room":"addd-1782490867179","who":"ผู้เล่น","ev":"socket-connect","detail":" [+160ms]","src":"client"}
{"t":1782491007611,"cat":"LobbyB","room":"addd","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782491008394,"cat":"LobbyB","room":"addd-1782490867179","who":"ผู้เล่น","ev":"join-ok","detail":"peers=2 host=me map=mn8nx46h bots=3 [+917ms]","src":"client"}
{"t":1782491008396,"cat":"LobbyB","room":"addd-1782490867179","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+918ms]","src":"client"}
{"t":1782491014645,"cat":"LobbyB","room":"addd-1782490867179","who":"Q","ev":"preload-occupants-done(bg)","detail":" [+13893ms]","src":"client"}
{"t":1782491159652,"cat":"LobbyB","room":"addd","who":"ผู้เล่น","ev":"host-change","detail":"host ใหม่ → Q","src":"server"}
{"t":1782491159652,"cat":"LobbyB","room":"addd","who":"ผู้เล่น","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782491169652,"cat":"LobbyB","room":"addd","who":"ผู้เล่น","ev":"bot-takeover","detail":"หลุดเกิน 10วิ → บอทแทน (สีตามคนออก)","src":"server"}
{"t":1782491244614,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"lobby-open","detail":"space=dasd-1782491241553 [+0ms]","src":"client"}
{"t":1782491244684,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"preload-start","detail":" [+63ms]","src":"client"}
{"t":1782491244684,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"manifest-done","detail":" [+64ms]","src":"client"}
{"t":1782491244692,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"colors-resolved","detail":" [+64ms]","src":"client"}
{"t":1782491244696,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"mychar-tinted","detail":"roomJoinReady=false [+65ms]","src":"client"}
{"t":1782491244702,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"preload-ready(mychar)","detail":" [+65ms]","src":"client"}
{"t":1782491244723,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"preload-occupants-done(bg)","detail":" [+65ms]","src":"client"}
{"t":1782491244822,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"socket-connect","detail":" [+178ms]","src":"client"}
{"t":1782491244826,"cat":"LobbyA","room":"dasd","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 1 + บอท 3","src":"server"}
{"t":1782491247892,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=3 [+3281ms]","src":"client"}
{"t":1782491247892,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+3281ms]","src":"client"}
{"t":1782491254234,"cat":"LobbyA","room":"asd-1782491251180","who":"Q","ev":"lobby-open","detail":"space=asd-1782491251180 [+0ms]","src":"client"}
{"t":1782491254268,"cat":"LobbyA","room":"asd-1782491251180","who":"Q","ev":"preload-start","detail":" [+25ms]","src":"client"}
{"t":1782491254330,"cat":"LobbyA","room":"asd-1782491251180","who":"Q","ev":"colors-resolved","detail":" [+101ms]","src":"client"}
{"t":1782491254333,"cat":"LobbyA","room":"asd-1782491251180","who":"Q","ev":"manifest-done","detail":" [+100ms]","src":"client"}
{"t":1782491254367,"cat":"LobbyA","room":"asd-1782491251180","who":"Q","ev":"socket-connect","detail":" [+139ms]","src":"client"}
{"t":1782491254374,"cat":"LobbyA","room":"asd","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 3","src":"server"}
{"t":1782491255384,"cat":"LobbyA","room":"asd-1782491251180","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=3 [+1151ms]","src":"client"}
{"t":1782491258757,"cat":"LobbyA","room":"asd-1782491251180","who":"Q","ev":"preload-ready(mychar)","detail":" [+4528ms]","src":"client"}
{"t":1782491258757,"cat":"LobbyA","room":"asd-1782491251180","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+4528ms]","src":"client"}
{"t":1782491258761,"cat":"LobbyA","room":"asd-1782491251180","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+4528ms]","src":"client"}
{"t":1782491267446,"cat":"LobbyA","room":"asd-1782491251180","who":"Q","ev":"preload-occupants-done(bg)","detail":" [+13217ms]","src":"client"}
{"t":1782491276462,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"lobby-open","detail":"space=dasd-1782491241553 [+0ms]","src":"client"}
{"t":1782491276495,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"preload-start","detail":" [+12ms]","src":"client"}
{"t":1782491276549,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"manifest-done","detail":" [+91ms]","src":"client"}
{"t":1782491276576,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"colors-resolved","detail":" [+92ms]","src":"client"}
{"t":1782491276590,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"socket-connect","detail":" [+123ms]","src":"client"}
{"t":1782491276612,"cat":"LobbyA","room":"dasd","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782491277373,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=3 [+903ms]","src":"client"}
{"t":1782491279840,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"preload-ready(mychar)","detail":" [+3386ms]","src":"client"}
{"t":1782491279841,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+3386ms]","src":"client"}
{"t":1782491279844,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+3386ms]","src":"client"}
{"t":1782491290165,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"preload-occupants-done(bg)","detail":" [+13705ms]","src":"client"}
{"t":1782491295875,"cat":"LobbyA","room":"dasd-1782491241553","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+19415ms]","src":"client"}
{"t":1782491295891,"cat":"LobbyA","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+51271ms]","src":"client"}
{"t":1782491299433,"cat":"LobbyB","room":"dasd-1782491241553","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+22973ms]","src":"client"}
{"t":1782491300843,"cat":"LobbyB","room":"dasd-1782491241553","who":"ผู้เล่น","ev":"loading-hide","detail":"เริ่มเล่นได้ [+56229ms]","src":"client"}
{"t":1782491303552,"cat":"MG1","room":"dasd","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782491303669,"cat":"MG1","room":"dasd","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782491303990,"cat":"MG1","room":"dasd","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 3","src":"server"}
{"t":1782491304066,"cat":"MG1","room":"dasd","who":"ผู้เล่น","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782491311793,"cat":"MG1","room":"dasd","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782491312194,"cat":"MG1","room":"dasd","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782491318987,"cat":"MG1","room":"dasd","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782491319318,"cat":"MG1","room":"dasd","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782491416267,"cat":"MG1","room":"dasd","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782491426268,"cat":"MG1","room":"dasd","who":"Q","ev":"bot-takeover","detail":"หลุดเกิน 10วิ → บอทแทน (สีตามคนออก)","src":"server"}
{"t":1782491886278,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"lobby-open","detail":"space=aaa-1782491883242 [+0ms]","src":"client"}
{"t":1782491886338,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"preload-start","detail":" [+44ms]","src":"client"}
{"t":1782491886414,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"manifest-done","detail":" [+116ms]","src":"client"}
{"t":1782491886415,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"colors-resolved","detail":" [+117ms]","src":"client"}
{"t":1782491886433,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"socket-connect","detail":" [+142ms]","src":"client"}
{"t":1782491886427,"cat":"LobbyA","room":"aaa","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 4","src":"server"}
{"t":1782491887375,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=4 [+1089ms]","src":"client"}
{"t":1782491889931,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+3638ms]","src":"client"}
{"t":1782491889938,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"preload-ready(mychar)","detail":" [+3638ms]","src":"client"}
{"t":1782491889938,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+3638ms]","src":"client"}
{"t":1782491894753,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"preload-occupants-done(bg)","detail":" [+8476ms]","src":"client"}
{"t":1782491908235,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"lobby-open","detail":"space=aaa-1782491883242 [+0ms]","src":"client"}
{"t":1782491908286,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"preload-start","detail":" [+60ms]","src":"client"}
{"t":1782491908304,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"manifest-done","detail":" [+60ms]","src":"client"}
{"t":1782491908306,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"colors-resolved","detail":" [+61ms]","src":"client"}
{"t":1782491908311,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+62ms]","src":"client"}
{"t":1782491908315,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"preload-ready(mychar)","detail":" [+62ms]","src":"client"}
{"t":1782491908325,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"preload-occupants-done(bg)","detail":" [+63ms]","src":"client"}
{"t":1782491908388,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"socket-connect","detail":" [+160ms]","src":"client"}
{"t":1782491908393,"cat":"LobbyA","room":"aaa","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782491910994,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=4 [+2762ms]","src":"client"}
{"t":1782491910995,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+2765ms]","src":"client"}
{"t":1782491928536,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+42253ms]","src":"client"}
{"t":1782491928558,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+20317ms]","src":"client"}
{"t":1782491931137,"cat":"LobbyB","room":"aaa-1782491883242","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+44858ms]","src":"client"}
{"t":1782491932589,"cat":"LobbyB","room":"aaa-1782491883242","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+24357ms]","src":"client"}
{"t":1782491935613,"cat":"MG1","room":"aaa","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782491935721,"cat":"MG1","room":"aaa","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782491935721,"cat":"MG1","room":"aaa","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782491936015,"cat":"MG1","room":"aaa","who":"MONE","ev":"join","detail":"สี#5 · คน 1 + บอท 4","src":"server"}
{"t":1782491936136,"cat":"MG1","room":"aaa","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782491946608,"cat":"MG1","room":"aaa","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782491946608,"cat":"MG1","room":"aaa","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782491946961,"cat":"MG1","room":"aaa","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782492117098,"cat":"LobbyB","room":"aaa","who":"MONE","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782492117512,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"lobby-open","detail":"space=aaa-1782491883242 [+0ms]","src":"client"}
{"t":1782492117549,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"preload-start","detail":" [+64ms]","src":"client"}
{"t":1782492117550,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"manifest-done","detail":" [+64ms]","src":"client"}
{"t":1782492117553,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"colors-resolved","detail":" [+65ms]","src":"client"}
{"t":1782492117555,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+66ms]","src":"client"}
{"t":1782492117569,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"preload-ready(mychar)","detail":" [+66ms]","src":"client"}
{"t":1782492117587,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"preload-occupants-done(bg)","detail":" [+66ms]","src":"client"}
{"t":1782492117637,"cat":"LobbyA","room":"aaa-1782491883242","who":"MONE","ev":"socket-connect","detail":" [+152ms]","src":"client"}
{"t":1782492117704,"cat":"LobbyB","room":"aaa","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782492121092,"cat":"LobbyB","room":"aaa-1782491883242","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mn8nx46h bots=4 [+3608ms]","src":"client"}
{"t":1782492121093,"cat":"LobbyB","room":"aaa-1782491883242","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+3609ms]","src":"client"}
{"t":1782492663115,"cat":"LobbyB","room":"aaa","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782492663115,"cat":"LobbyB","room":"aaa","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782492663360,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"lobby-open","detail":"space=aaa-1782491883242 [+0ms]","src":"client"}
{"t":1782492663402,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"preload-start","detail":" [+49ms]","src":"client"}
{"t":1782492663495,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"socket-connect","detail":" [+127ms]","src":"client"}
{"t":1782492663497,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"colors-resolved","detail":" [+129ms]","src":"client"}
{"t":1782492663498,"cat":"LobbyA","room":"aaa-1782491883242","who":"Q","ev":"manifest-done","detail":" [+128ms]","src":"client"}
{"t":1782492663498,"cat":"LobbyB","room":"aaa","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782492664388,"cat":"LobbyB","room":"aaa-1782491883242","who":"Q","ev":"join-ok","detail":"peers=2 host=me map=mn8nx46h bots=4 [+992ms]","src":"client"}
{"t":1782492672866,"cat":"LobbyB","room":"aaa-1782491883242","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+9535ms]","src":"client"}
{"t":1782492672866,"cat":"LobbyB","room":"aaa-1782491883242","who":"Q","ev":"preload-ready(mychar)","detail":" [+9535ms]","src":"client"}
{"t":1782492672866,"cat":"LobbyB","room":"aaa-1782491883242","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+9534ms]","src":"client"}
{"t":1782492683489,"cat":"LobbyB","room":"aaa-1782491883242","who":"Q","ev":"preload-occupants-done(bg)","detail":" [+20157ms]","src":"client"}
{"t":1782492684358,"cat":"MG1","room":"aaa","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782492684473,"cat":"MG1","room":"aaa","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782492684473,"cat":"MG1","room":"aaa","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782492684732,"cat":"MG1","room":"aaa","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 4","src":"server"}
{"t":1782492685023,"cat":"MG1","room":"aaa","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782492736650,"cat":"MG1","room":"aaa","who":"MONE","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782493112477,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"lobby-open","detail":"space=ผผผผ-1782493109334 [+0ms]","src":"client"}
{"t":1782493112520,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"preload-start","detail":" [+13ms]","src":"client"}
{"t":1782493112565,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"colors-resolved","detail":" [+89ms]","src":"client"}
{"t":1782493112567,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"manifest-done","detail":" [+88ms]","src":"client"}
{"t":1782493112602,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"socket-connect","detail":" [+115ms]","src":"client"}
{"t":1782493112599,"cat":"LobbyA","room":"ผผผผ","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 3","src":"server"}
{"t":1782493113383,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=3 [+903ms]","src":"client"}
{"t":1782493116771,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+4294ms]","src":"client"}
{"t":1782493125210,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"preload-occupants-done","detail":" [+12729ms]","src":"client"}
{"t":1782493125214,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"preload-ready(occupants)","detail":" [+12729ms]","src":"client"}
{"t":1782493125216,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+12730ms]","src":"client"}
{"t":1782493136404,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"lobby-open","detail":"space=ผผผผ-1782493109334 [+1ms]","src":"client"}
{"t":1782493136455,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"preload-start","detail":" [+52ms]","src":"client"}
{"t":1782493136466,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"manifest-done","detail":" [+53ms]","src":"client"}
{"t":1782493136468,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"colors-resolved","detail":" [+53ms]","src":"client"}
{"t":1782493136473,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+54ms]","src":"client"}
{"t":1782493136479,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"preload-occupants-done","detail":" [+54ms]","src":"client"}
{"t":1782493136495,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"preload-ready(occupants)","detail":" [+54ms]","src":"client"}
{"t":1782493136552,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"socket-connect","detail":" [+151ms]","src":"client"}
{"t":1782493136553,"cat":"LobbyA","room":"ผผผผ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782493138144,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=3 [+1742ms]","src":"client"}
{"t":1782493138154,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1743ms]","src":"client"}
{"t":1782493157397,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+44920ms]","src":"client"}
{"t":1782493157431,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+21004ms]","src":"client"}
{"t":1782493160415,"cat":"LobbyB","room":"ผผผผ-1782493109334","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+47931ms]","src":"client"}
{"t":1782493161601,"cat":"LobbyB","room":"ผผผผ-1782493109334","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+25202ms]","src":"client"}
{"t":1782493163305,"cat":"MG1","room":"ผผผผ","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782493163419,"cat":"MG1","room":"ผผผผ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782493163419,"cat":"MG1","room":"ผผผผ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782493163705,"cat":"MG1","room":"ผผผผ","who":"MONE","ev":"join","detail":"สี#5 · คน 1 + บอท 3","src":"server"}
{"t":1782493163732,"cat":"MG1","room":"ผผผผ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782493641066,"cat":"LobbyB","room":"ผผผผ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782493641067,"cat":"LobbyB","room":"ผผผผ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782493641431,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"lobby-open","detail":"space=ผผผผ-1782493109334 [+0ms]","src":"client"}
{"t":1782493641471,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"preload-start","detail":" [+14ms]","src":"client"}
{"t":1782493641526,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"manifest-done","detail":" [+134ms]","src":"client"}
{"t":1782493641532,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"colors-resolved","detail":" [+135ms]","src":"client"}
{"t":1782493641569,"cat":"LobbyA","room":"ผผผผ-1782493109334","who":"Q","ev":"socket-connect","detail":" [+163ms]","src":"client"}
{"t":1782493641615,"cat":"LobbyB","room":"ผผผผ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782493642528,"cat":"LobbyB","room":"ผผผผ-1782493109334","who":"Q","ev":"join-ok","detail":"peers=2 host=me map=mn8nx46h bots=3 [+1131ms]","src":"client"}
{"t":1782493648014,"cat":"LobbyB","room":"ผผผผ-1782493109334","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+6623ms]","src":"client"}
{"t":1782493650047,"cat":"LobbyB","room":"ผผผผ-1782493109334","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+8652ms]","src":"client"}
{"t":1782493653088,"cat":"LobbyB","room":"ผผผผ-1782493109334","who":"Q","ev":"preload-occupants-done","detail":" [+11693ms]","src":"client"}
{"t":1782493653092,"cat":"LobbyB","room":"ผผผผ-1782493109334","who":"Q","ev":"preload-ready(occupants)","detail":" [+11693ms]","src":"client"}
{"t":1782493718102,"cat":"LobbyB","room":"ผผผผ-1782493109334","who":"Q","ev":"socket-connect","detail":" [+76710ms]","src":"client"}
{"t":1782493755866,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"lobby-open","detail":"space=ผผผ-1782493752787 [+0ms]","src":"client"}
{"t":1782493755898,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"preload-start","detail":" [+13ms]","src":"client"}
{"t":1782493755957,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"colors-resolved","detail":" [+95ms]","src":"client"}
{"t":1782493755959,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"manifest-done","detail":" [+95ms]","src":"client"}
{"t":1782493755993,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"socket-connect","detail":" [+120ms]","src":"client"}
{"t":1782493755983,"cat":"LobbyA","room":"ผผผ","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 3","src":"server"}
{"t":1782493756720,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=3 [+827ms]","src":"client"}
{"t":1782493759512,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"lobby-open","detail":"space=ผผผ-1782493752787 [+0ms]","src":"client"}
{"t":1782493759558,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"preload-start","detail":" [+56ms]","src":"client"}
{"t":1782493759562,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"manifest-done","detail":" [+57ms]","src":"client"}
{"t":1782493759565,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+61ms]","src":"client"}
{"t":1782493759569,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"colors-resolved","detail":" [+59ms]","src":"client"}
{"t":1782493759575,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"preload-occupants-done","detail":" [+63ms]","src":"client"}
{"t":1782493759600,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"preload-ready(occupants)","detail":" [+65ms]","src":"client"}
{"t":1782493759632,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+3765ms]","src":"client"}
{"t":1782493759651,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"socket-connect","detail":" [+160ms]","src":"client"}
{"t":1782493759654,"cat":"LobbyA","room":"ผผผ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782493760446,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=3 [+958ms]","src":"client"}
{"t":1782493760450,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+958ms]","src":"client"}
{"t":1782493766757,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+10891ms]","src":"client"}
{"t":1782493766759,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"preload-occupants-done","detail":" [+10890ms]","src":"client"}
{"t":1782493766759,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"preload-ready(occupants)","detail":" [+10891ms]","src":"client"}
{"t":1782493798164,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+42292ms]","src":"client"}
{"t":1782493798225,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+38735ms]","src":"client"}
{"t":1782493805704,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+49840ms]","src":"client"}
{"t":1782493807157,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+47664ms]","src":"client"}
{"t":1782493808626,"cat":"MG1","room":"ผผผ","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782493808740,"cat":"MG1","room":"ผผผ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782493808740,"cat":"MG1","room":"ผผผ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782493809062,"cat":"MG1","room":"ผผผ","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 3","src":"server"}
{"t":1782493809117,"cat":"MG1","room":"ผผผ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782493921793,"cat":"LobbyB","room":"ผผผ","who":"MONE","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782493922221,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"lobby-open","detail":"space=ผผผ-1782493752787 [+0ms]","src":"client"}
{"t":1782493922305,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"preload-start","detail":" [+85ms]","src":"client"}
{"t":1782493922308,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+90ms]","src":"client"}
{"t":1782493922309,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"manifest-done","detail":" [+87ms]","src":"client"}
{"t":1782493922310,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"colors-resolved","detail":" [+89ms]","src":"client"}
{"t":1782493922311,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"preload-occupants-done","detail":" [+91ms]","src":"client"}
{"t":1782493922341,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"preload-ready(occupants)","detail":" [+93ms]","src":"client"}
{"t":1782493922404,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"socket-connect","detail":" [+184ms]","src":"client"}
{"t":1782493922448,"cat":"LobbyB","room":"ผผผ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782493923308,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mn8nx46h bots=3 [+1050ms]","src":"client"}
{"t":1782493923312,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1051ms]","src":"client"}
{"t":1782493928197,"cat":"LobbyB","room":"ผผผ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782493928197,"cat":"LobbyB","room":"ผผผ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782493928423,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"lobby-open","detail":"space=ผผผ-1782493752787 [+0ms]","src":"client"}
{"t":1782493928506,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"preload-start","detail":" [+53ms]","src":"client"}
{"t":1782493928556,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"manifest-done","detail":" [+133ms]","src":"client"}
{"t":1782493928557,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"colors-resolved","detail":" [+133ms]","src":"client"}
{"t":1782493928602,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"socket-connect","detail":" [+158ms]","src":"client"}
{"t":1782493928636,"cat":"LobbyB","room":"ผผผ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782493929368,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"join-ok","detail":"peers=2 host=me map=mn8nx46h bots=3 [+912ms]","src":"client"}
{"t":1782493933735,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+5307ms]","src":"client"}
{"t":1782493946276,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"preload-occupants-done","detail":" [+17846ms]","src":"client"}
{"t":1782493946277,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+17846ms]","src":"client"}
{"t":1782493946277,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"preload-ready(occupants)","detail":" [+17846ms]","src":"client"}
{"t":1782494857195,"cat":"MG1","room":"ผผผ","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782494857318,"cat":"MG1","room":"ผผผ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782494857318,"cat":"MG1","room":"ผผผ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782494857870,"cat":"MG1","room":"ผผผ","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 3","src":"server"}
{"t":1782494858190,"cat":"MG1","room":"ผผผ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782494967799,"cat":"LobbyB","room":"ผผผ","who":"MONE","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782494968205,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"lobby-open","detail":"space=ผผผ-1782493752787 [+0ms]","src":"client"}
{"t":1782494968286,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"manifest-done","detail":" [+70ms]","src":"client"}
{"t":1782494968286,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"preload-start","detail":" [+70ms]","src":"client"}
{"t":1782494968290,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"colors-resolved","detail":" [+72ms]","src":"client"}
{"t":1782494968295,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+73ms]","src":"client"}
{"t":1782494968298,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"preload-occupants-done","detail":" [+74ms]","src":"client"}
{"t":1782494968311,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"preload-ready(occupants)","detail":" [+75ms]","src":"client"}
{"t":1782494968395,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"MONE","ev":"socket-connect","detail":" [+183ms]","src":"client"}
{"t":1782494968461,"cat":"LobbyB","room":"ผผผ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782494968958,"cat":"LobbyB","room":"ผผผ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782494968958,"cat":"LobbyB","room":"ผผผ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782494969199,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"lobby-open","detail":"space=ผผผ-1782493752787 [+0ms]","src":"client"}
{"t":1782494969238,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"preload-start","detail":" [+32ms]","src":"client"}
{"t":1782494969296,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"colors-resolved","detail":" [+103ms]","src":"client"}
{"t":1782494969297,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"manifest-done","detail":" [+102ms]","src":"client"}
{"t":1782494969337,"cat":"LobbyA","room":"ผผผ-1782493752787","who":"Q","ev":"socket-connect","detail":" [+131ms]","src":"client"}
{"t":1782494969376,"cat":"LobbyB","room":"ผผผ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782494970368,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"join-ok","detail":"peers=2 host=me map=mn8nx46h bots=3 [+1149ms]","src":"client"}
{"t":1782494971598,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+3399ms]","src":"client"}
{"t":1782494971601,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mn8nx46h bots=3 [+3398ms]","src":"client"}
{"t":1782494975415,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+6217ms]","src":"client"}
{"t":1782494990040,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"preload-occupants-done","detail":" [+20844ms]","src":"client"}
{"t":1782494990041,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"preload-ready(occupants)","detail":" [+20845ms]","src":"client"}
{"t":1782494990044,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+20845ms]","src":"client"}
{"t":1782495443870,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"MONE","ev":"socket-connect","detail":" [+475661ms]","src":"client"}
{"t":1782495444114,"cat":"LobbyB","room":"ผผผ-1782493752787","who":"Q","ev":"socket-connect","detail":" [+474921ms]","src":"client"}
{"t":1782495696360,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"lobby-open","detail":"space=zzz-1782495693193 [+0ms]","src":"client"}
{"t":1782495696393,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"preload-start","detail":" [+24ms]","src":"client"}
{"t":1782495696459,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"manifest-done","detail":" [+108ms]","src":"client"}
{"t":1782495696461,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"colors-resolved","detail":" [+109ms]","src":"client"}
{"t":1782495696488,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"socket-connect","detail":" [+135ms]","src":"client"}
{"t":1782495696492,"cat":"LobbyA","room":"zzz","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 3","src":"server"}
{"t":1782495697430,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=3 [+1057ms]","src":"client"}
{"t":1782495701215,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+4859ms]","src":"client"}
{"t":1782495705916,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"lobby-open","detail":"space=zzz-1782495693193 [+0ms]","src":"client"}
{"t":1782495705989,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"preload-start","detail":" [+70ms]","src":"client"}
{"t":1782495705997,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"manifest-done","detail":" [+70ms]","src":"client"}
{"t":1782495705999,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+72ms]","src":"client"}
{"t":1782495706002,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"colors-resolved","detail":" [+71ms]","src":"client"}
{"t":1782495706005,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"preload-occupants-done","detail":" [+72ms]","src":"client"}
{"t":1782495706034,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"preload-ready(occupants)","detail":" [+73ms]","src":"client"}
{"t":1782495706092,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"socket-connect","detail":" [+180ms]","src":"client"}
{"t":1782495706097,"cat":"LobbyA","room":"zzz","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782495707650,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=3 [+1734ms]","src":"client"}
{"t":1782495707671,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1734ms]","src":"client"}
{"t":1782495710052,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"preload-ready(occupants)","detail":" [+13700ms]","src":"client"}
{"t":1782495710052,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"preload-occupants-done","detail":" [+13700ms]","src":"client"}
{"t":1782495710054,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+13700ms]","src":"client"}
{"t":1782495725024,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+28671ms]","src":"client"}
{"t":1782495725029,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+19116ms]","src":"client"}
{"t":1782495728406,"cat":"LobbyB","room":"zzz-1782495693193","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+32054ms]","src":"client"}
{"t":1782495729749,"cat":"LobbyB","room":"zzz-1782495693193","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+23834ms]","src":"client"}
{"t":1782495732158,"cat":"MG1","room":"zzz","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782495732276,"cat":"MG1","room":"zzz","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782495732276,"cat":"MG1","room":"zzz","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782495732610,"cat":"MG1","room":"zzz","who":"MONE","ev":"join","detail":"สี#5 · คน 1 + บอท 3","src":"server"}
{"t":1782495732633,"cat":"MG1","room":"zzz","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782495799141,"cat":"LobbyB","room":"zzz","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782495799142,"cat":"LobbyB","room":"zzz","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782495799384,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"lobby-open","detail":"space=zzz-1782495693193 [+0ms]","src":"client"}
{"t":1782495799430,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"preload-start","detail":" [+45ms]","src":"client"}
{"t":1782495799505,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"manifest-done","detail":" [+121ms]","src":"client"}
{"t":1782495799505,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"colors-resolved","detail":" [+122ms]","src":"client"}
{"t":1782495799548,"cat":"LobbyA","room":"zzz-1782495693193","who":"Q","ev":"socket-connect","detail":" [+148ms]","src":"client"}
{"t":1782495799593,"cat":"LobbyB","room":"zzz","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782495800024,"cat":"LobbyB","room":"zzz","who":"MONE","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782495800260,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"lobby-open","detail":"space=zzz-1782495693193 [+0ms]","src":"client"}
{"t":1782495800292,"cat":"LobbyB","room":"zzz-1782495693193","who":"Q","ev":"join-ok","detail":"peers=2 host=me map=mn8nx46h bots=3 [+886ms]","src":"client"}
{"t":1782495800334,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"preload-start","detail":" [+67ms]","src":"client"}
{"t":1782495800362,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"preload-occupants-done","detail":" [+69ms]","src":"client"}
{"t":1782495800363,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"colors-resolved","detail":" [+69ms]","src":"client"}
{"t":1782495800363,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+69ms]","src":"client"}
{"t":1782495800364,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"manifest-done","detail":" [+68ms]","src":"client"}
{"t":1782495800382,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"preload-ready(occupants)","detail":" [+70ms]","src":"client"}
{"t":1782495800477,"cat":"LobbyA","room":"zzz-1782495693193","who":"MONE","ev":"socket-connect","detail":" [+219ms]","src":"client"}
{"t":1782495800523,"cat":"LobbyB","room":"zzz","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782495803210,"cat":"LobbyB","room":"zzz-1782495693193","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+2959ms]","src":"client"}
{"t":1782495803211,"cat":"LobbyB","room":"zzz-1782495693193","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mn8nx46h bots=3 [+2958ms]","src":"client"}
{"t":1782495804765,"cat":"LobbyB","room":"zzz-1782495693193","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+5381ms]","src":"client"}
{"t":1782495822724,"cat":"LobbyB","room":"zzz-1782495693193","who":"Q","ev":"preload-occupants-done","detail":" [+23340ms]","src":"client"}
{"t":1782495822727,"cat":"LobbyB","room":"zzz-1782495693193","who":"Q","ev":"preload-ready(occupants)","detail":" [+23340ms]","src":"client"}
{"t":1782495822730,"cat":"LobbyB","room":"zzz-1782495693193","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+23341ms]","src":"client"}
{"t":1782496149878,"cat":"LobbyB","room":"zzz-1782495693193","who":"MONE","ev":"socket-connect","detail":" [+349625ms]","src":"client"}
{"t":1782496150113,"cat":"LobbyB","room":"zzz-1782495693193","who":"Q","ev":"socket-connect","detail":" [+350733ms]","src":"client"}
{"t":1782496392268,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"lobby-open","detail":"space=ผผผ-1782496389120 [+0ms]","src":"client"}
{"t":1782496392309,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"preload-start","detail":" [+25ms]","src":"client"}
{"t":1782496392361,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"colors-resolved","detail":" [+97ms]","src":"client"}
{"t":1782496392364,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"manifest-done","detail":" [+97ms]","src":"client"}
{"t":1782496392394,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"socket-connect","detail":" [+124ms]","src":"client"}
{"t":1782496392401,"cat":"LobbyA","room":"ผผผ","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 3","src":"server"}
{"t":1782496393354,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=3 [+1052ms]","src":"client"}
{"t":1782496396866,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+4594ms]","src":"client"}
{"t":1782496400171,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"lobby-open","detail":"space=ผผผ-1782496389120 [+0ms]","src":"client"}
{"t":1782496400246,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"preload-start","detail":" [+84ms]","src":"client"}
{"t":1782496400250,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"manifest-done","detail":" [+85ms]","src":"client"}
{"t":1782496400272,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"colors-resolved","detail":" [+86ms]","src":"client"}
{"t":1782496400272,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+87ms]","src":"client"}
{"t":1782496400283,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"preload-occupants-done","detail":" [+88ms]","src":"client"}
{"t":1782496400291,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"preload-ready(occupants)","detail":" [+89ms]","src":"client"}
{"t":1782496400350,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"socket-connect","detail":" [+182ms]","src":"client"}
{"t":1782496400351,"cat":"LobbyA","room":"ผผผ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 3","src":"server"}
{"t":1782496401391,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=3 [+1225ms]","src":"client"}
{"t":1782496401392,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1226ms]","src":"client"}
{"t":1782496404407,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"preload-ready(occupants)","detail":" [+12138ms]","src":"client"}
{"t":1782496404408,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"preload-occupants-done","detail":" [+12137ms]","src":"client"}
{"t":1782496404411,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+12138ms]","src":"client"}
{"t":1782496444915,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+52647ms]","src":"client"}
{"t":1782496444926,"cat":"LobbyA","room":"ผผผ-1782496389120","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+44761ms]","src":"client"}
{"t":1782496447550,"cat":"LobbyB","room":"ผผผ-1782496389120","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+55279ms]","src":"client"}
{"t":1782496448659,"cat":"LobbyB","room":"ผผผ-1782496389120","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+48494ms]","src":"client"}
{"t":1782496449834,"cat":"MG1","room":"ผผผ","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782496449956,"cat":"MG1","room":"ผผผ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782496449957,"cat":"MG1","room":"ผผผ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782496450321,"cat":"MG1","room":"ผผผ","who":"MONE","ev":"join","detail":"สี#5 · คน 1 + บอท 3","src":"server"}
{"t":1782496450406,"cat":"MG1","room":"ผผผ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 3","src":"server"}
{"t":1782496887270,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"lobby-open","detail":"space=asd-1782496884280 [+1ms]","src":"client"}
{"t":1782496887311,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"preload-start","detail":" [+26ms]","src":"client"}
{"t":1782496887379,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"manifest-done","detail":" [+114ms]","src":"client"}
{"t":1782496887384,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"colors-resolved","detail":" [+115ms]","src":"client"}
{"t":1782496887404,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"socket-connect","detail":" [+141ms]","src":"client"}
{"t":1782496887419,"cat":"LobbyA","room":"asd","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 4","src":"server"}
{"t":1782496888339,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=4 [+1067ms]","src":"client"}
{"t":1782496894213,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+6943ms]","src":"client"}
{"t":1782496903553,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"preload-occupants-done","detail":" [+16286ms]","src":"client"}
{"t":1782496903554,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+16286ms]","src":"client"}
{"t":1782496903555,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"preload-ready(occupants)","detail":" [+16286ms]","src":"client"}
{"t":1782496908295,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"lobby-open","detail":"space=asd-1782496884280 [+0ms]","src":"client"}
{"t":1782496908322,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"preload-start","detail":" [+20ms]","src":"client"}
{"t":1782496908339,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"manifest-done","detail":" [+21ms]","src":"client"}
{"t":1782496908348,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"colors-resolved","detail":" [+21ms]","src":"client"}
{"t":1782496908359,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+22ms]","src":"client"}
{"t":1782496908362,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"preload-occupants-done","detail":" [+22ms]","src":"client"}
{"t":1782496908363,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"preload-ready(occupants)","detail":" [+23ms]","src":"client"}
{"t":1782496908502,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"socket-connect","detail":" [+182ms]","src":"client"}
{"t":1782496908503,"cat":"LobbyA","room":"asd","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782496909392,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=4 [+1106ms]","src":"client"}
{"t":1782496909398,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1109ms]","src":"client"}
{"t":1782496935190,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+47925ms]","src":"client"}
{"t":1782496935203,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+26913ms]","src":"client"}
{"t":1782496947231,"cat":"LobbyB","room":"asd-1782496884280","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+59967ms]","src":"client"}
{"t":1782496948564,"cat":"LobbyB","room":"asd-1782496884280","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+40280ms]","src":"client"}
{"t":1782496950131,"cat":"MG1","room":"asd","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782496950250,"cat":"MG1","room":"asd","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782496950250,"cat":"MG1","room":"asd","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782496950552,"cat":"MG1","room":"asd","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 4","src":"server"}
{"t":1782496950640,"cat":"MG1","room":"asd","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782497041053,"cat":"LobbyB","room":"asd","who":"MONE","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782497041518,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"lobby-open","detail":"space=asd-1782496884280 [+0ms]","src":"client"}
{"t":1782497041566,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"preload-start","detail":" [+43ms]","src":"client"}
{"t":1782497041573,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"manifest-done","detail":" [+43ms]","src":"client"}
{"t":1782497041581,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"colors-resolved","detail":" [+44ms]","src":"client"}
{"t":1782497041600,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+45ms]","src":"client"}
{"t":1782497041607,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"preload-occupants-done","detail":" [+46ms]","src":"client"}
{"t":1782497041621,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"preload-ready(occupants)","detail":" [+47ms]","src":"client"}
{"t":1782497041694,"cat":"LobbyA","room":"asd-1782496884280","who":"MONE","ev":"socket-connect","detail":" [+168ms]","src":"client"}
{"t":1782497041746,"cat":"LobbyB","room":"asd","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782497042657,"cat":"LobbyB","room":"asd-1782496884280","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mn8nx46h bots=4 [+1101ms]","src":"client"}
{"t":1782497042659,"cat":"LobbyB","room":"asd-1782496884280","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1101ms]","src":"client"}
{"t":1782497061069,"cat":"LobbyB","room":"asd","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782497061069,"cat":"LobbyB","room":"asd","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782497061417,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"lobby-open","detail":"space=asd-1782496884280 [+0ms]","src":"client"}
{"t":1782497061495,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"preload-start","detail":" [+21ms]","src":"client"}
{"t":1782497061546,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"colors-resolved","detail":" [+129ms]","src":"client"}
{"t":1782497061546,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"manifest-done","detail":" [+128ms]","src":"client"}
{"t":1782497061591,"cat":"LobbyA","room":"asd-1782496884280","who":"Q","ev":"socket-connect","detail":" [+145ms]","src":"client"}
{"t":1782497061615,"cat":"LobbyB","room":"asd","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782497062521,"cat":"LobbyB","room":"asd-1782496884280","who":"Q","ev":"join-ok","detail":"peers=2 host=me map=mn8nx46h bots=4 [+1102ms]","src":"client"}
{"t":1782497068156,"cat":"LobbyB","room":"asd-1782496884280","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+6736ms]","src":"client"}
{"t":1782497070364,"cat":"LobbyB","room":"asd-1782496884280","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+8944ms]","src":"client"}
{"t":1782497074052,"cat":"LobbyB","room":"asd-1782496884280","who":"Q","ev":"preload-occupants-done","detail":" [+12633ms]","src":"client"}
{"t":1782497074054,"cat":"LobbyB","room":"asd-1782496884280","who":"Q","ev":"preload-ready(occupants)","detail":" [+12634ms]","src":"client"}
{"t":1782497075234,"cat":"LobbyB","room":"asd","who":"MONE","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782497085235,"cat":"LobbyB","room":"asd","who":"MONE","ev":"bot-takeover","detail":"หลุดเกิน 10วิ → บอทแทน (สีตามคนออก)","src":"server"}
{"t":1782497200527,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"lobby-open","detail":"space=ฟฟฟฟ-1782497197296 [+0ms]","src":"client"}
{"t":1782497200543,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"preload-start","detail":" [+14ms]","src":"client"}
{"t":1782497200615,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"manifest-done","detail":" [+123ms]","src":"client"}
{"t":1782497200619,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"colors-resolved","detail":" [+123ms]","src":"client"}
{"t":1782497200650,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"socket-connect","detail":" [+153ms]","src":"client"}
{"t":1782497200654,"cat":"LobbyA","room":"ฟฟฟฟ","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 4","src":"server"}
{"t":1782497201388,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=4 [+888ms]","src":"client"}
{"t":1782497204341,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+3839ms]","src":"client"}
{"t":1782497211078,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"preload-occupants-done","detail":" [+10577ms]","src":"client"}
{"t":1782497211079,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+10578ms]","src":"client"}
{"t":1782497211080,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"preload-ready(occupants)","detail":" [+10578ms]","src":"client"}
{"t":1782497268770,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"lobby-open","detail":"space=ฟฟฟฟ-1782497197296 [+0ms]","src":"client"}
{"t":1782497268806,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"preload-start","detail":" [+24ms]","src":"client"}
{"t":1782497268814,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"manifest-done","detail":" [+25ms]","src":"client"}
{"t":1782497268814,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"colors-resolved","detail":" [+26ms]","src":"client"}
{"t":1782497268816,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+26ms]","src":"client"}
{"t":1782497268825,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"preload-occupants-done","detail":" [+26ms]","src":"client"}
{"t":1782497268837,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"preload-ready(occupants)","detail":" [+27ms]","src":"client"}
{"t":1782497268915,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"socket-connect","detail":" [+162ms]","src":"client"}
{"t":1782497268919,"cat":"LobbyA","room":"ฟฟฟฟ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782497269672,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=4 [+911ms]","src":"client"}
{"t":1782497269686,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+912ms]","src":"client"}
{"t":1782497290108,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+89609ms]","src":"client"}
{"t":1782497290126,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+21361ms]","src":"client"}
{"t":1782497296572,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+96071ms]","src":"client"}
{"t":1782497297661,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+28910ms]","src":"client"}
{"t":1782497299048,"cat":"MG1","room":"ฟฟฟฟ","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782497299171,"cat":"MG1","room":"ฟฟฟฟ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782497299171,"cat":"MG1","room":"ฟฟฟฟ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782497299485,"cat":"MG1","room":"ฟฟฟฟ","who":"MONE","ev":"join","detail":"สี#5 · คน 1 + บอท 4","src":"server"}
{"t":1782497299513,"cat":"MG1","room":"ฟฟฟฟ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782497405281,"cat":"LobbyB","room":"ฟฟฟฟ","who":"MONE","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782497405716,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"lobby-open","detail":"space=ฟฟฟฟ-1782497197296 [+1ms]","src":"client"}
{"t":1782497405759,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"preload-start","detail":" [+25ms]","src":"client"}
{"t":1782497405778,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"colors-resolved","detail":" [+26ms]","src":"client"}
{"t":1782497405779,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"manifest-done","detail":" [+25ms]","src":"client"}
{"t":1782497405783,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+27ms]","src":"client"}
{"t":1782497405789,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"preload-occupants-done","detail":" [+27ms]","src":"client"}
{"t":1782497405789,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"preload-ready(occupants)","detail":" [+29ms]","src":"client"}
{"t":1782497405915,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"socket-connect","detail":" [+185ms]","src":"client"}
{"t":1782497405996,"cat":"LobbyB","room":"ฟฟฟฟ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782497406741,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mn8nx46h bots=4 [+1030ms]","src":"client"}
{"t":1782497406748,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1031ms]","src":"client"}
{"t":1782497443001,"cat":"LobbyB","room":"ฟฟฟฟ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782497443001,"cat":"LobbyB","room":"ฟฟฟฟ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782497443453,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"lobby-open","detail":"space=ฟฟฟฟ-1782497197296 [+0ms]","src":"client"}
{"t":1782497443500,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"preload-start","detail":" [+48ms]","src":"client"}
{"t":1782497443554,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"socket-connect","detail":" [+107ms]","src":"client"}
{"t":1782497443566,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"manifest-done","detail":" [+114ms]","src":"client"}
{"t":1782497443582,"cat":"LobbyA","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"colors-resolved","detail":" [+115ms]","src":"client"}
{"t":1782497443564,"cat":"LobbyB","room":"ฟฟฟฟ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782497444551,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"join-ok","detail":"peers=2 host=me map=mn8nx46h bots=4 [+1084ms]","src":"client"}
{"t":1782497448500,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+5050ms]","src":"client"}
{"t":1782497464323,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+20875ms]","src":"client"}
{"t":1782497464323,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"preload-ready(occupants)","detail":" [+20875ms]","src":"client"}
{"t":1782497464324,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"preload-occupants-done","detail":" [+20874ms]","src":"client"}
{"t":1782497770847,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"MONE","ev":"socket-connect","detail":" [+365152ms]","src":"client"}
{"t":1782497771113,"cat":"LobbyB","room":"ฟฟฟฟ-1782497197296","who":"Q","ev":"socket-connect","detail":" [+327668ms]","src":"client"}
{"t":1782497823919,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"lobby-open","detail":"space=ออ-1782497820821 [+0ms]","src":"client"}
{"t":1782497823959,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"preload-start","detail":" [+21ms]","src":"client"}
{"t":1782497824033,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"manifest-done","detail":" [+111ms]","src":"client"}
{"t":1782497824034,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"colors-resolved","detail":" [+112ms]","src":"client"}
{"t":1782497824064,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"socket-connect","detail":" [+139ms]","src":"client"}
{"t":1782497824067,"cat":"LobbyA","room":"ออ","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 4","src":"server"}
{"t":1782497824932,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=4 [+985ms]","src":"client"}
{"t":1782497829309,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+5362ms]","src":"client"}
{"t":1782497837377,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"lobby-open","detail":"space=ออ-1782497820821 [+0ms]","src":"client"}
{"t":1782497837418,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"preload-start","detail":" [+37ms]","src":"client"}
{"t":1782497837422,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"manifest-done","detail":" [+38ms]","src":"client"}
{"t":1782497837436,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"colors-resolved","detail":" [+41ms]","src":"client"}
{"t":1782497837438,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+41ms]","src":"client"}
{"t":1782497837442,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"preload-occupants-done","detail":" [+43ms]","src":"client"}
{"t":1782497837456,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"preload-ready(occupants)","detail":" [+44ms]","src":"client"}
{"t":1782497837546,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"socket-connect","detail":" [+169ms]","src":"client"}
{"t":1782497837550,"cat":"LobbyA","room":"ออ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782497838380,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+1012ms]","src":"client"}
{"t":1782497838381,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=4 [+1011ms]","src":"client"}
{"t":1782497839221,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"preload-ready(occupants)","detail":" [+15295ms]","src":"client"}
{"t":1782497839223,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+15295ms]","src":"client"}
{"t":1782497839223,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"preload-occupants-done","detail":" [+15294ms]","src":"client"}
{"t":1782497857055,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+33132ms]","src":"client"}
{"t":1782497857061,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+19705ms]","src":"client"}
{"t":1782497873771,"cat":"LobbyB","room":"ออ-1782497820821","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+49850ms]","src":"client"}
{"t":1782497875305,"cat":"LobbyB","room":"ออ-1782497820821","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+37949ms]","src":"client"}
{"t":1782497876292,"cat":"MG1","room":"ออ","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782497876413,"cat":"MG1","room":"ออ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782497876413,"cat":"MG1","room":"ออ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782497876720,"cat":"MG1","room":"ออ","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 4","src":"server"}
{"t":1782497876807,"cat":"MG1","room":"ออ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782497973120,"cat":"LobbyB","room":"ออ","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782497973120,"cat":"LobbyB","room":"ออ","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782497973544,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"lobby-open","detail":"space=ออ-1782497820821 [+0ms]","src":"client"}
{"t":1782497973594,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"preload-start","detail":" [+45ms]","src":"client"}
{"t":1782497973644,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"manifest-done","detail":" [+98ms]","src":"client"}
{"t":1782497973652,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"colors-resolved","detail":" [+98ms]","src":"client"}
{"t":1782497973675,"cat":"LobbyA","room":"ออ-1782497820821","who":"Q","ev":"socket-connect","detail":" [+126ms]","src":"client"}
{"t":1782497973723,"cat":"LobbyB","room":"ออ","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782497974440,"cat":"LobbyB","room":"ออ","who":"MONE","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782497974543,"cat":"LobbyB","room":"ออ-1782497820821","who":"Q","ev":"join-ok","detail":"peers=2 host=me map=mn8nx46h bots=4 [+994ms]","src":"client"}
{"t":1782497974827,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"lobby-open","detail":"space=ออ-1782497820821 [+0ms]","src":"client"}
{"t":1782497974874,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"preload-start","detail":" [+29ms]","src":"client"}
{"t":1782497974876,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"manifest-done","detail":" [+30ms]","src":"client"}
{"t":1782497974879,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"colors-resolved","detail":" [+32ms]","src":"client"}
{"t":1782497974892,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+32ms]","src":"client"}
{"t":1782497974902,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"preload-occupants-done","detail":" [+33ms]","src":"client"}
{"t":1782497974916,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"preload-ready(occupants)","detail":" [+33ms]","src":"client"}
{"t":1782497974971,"cat":"LobbyA","room":"ออ-1782497820821","who":"MONE","ev":"socket-connect","detail":" [+148ms]","src":"client"}
{"t":1782497975029,"cat":"LobbyB","room":"ออ","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782497975784,"cat":"LobbyB","room":"ออ-1782497820821","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mn8nx46h bots=4 [+922ms]","src":"client"}
{"t":1782497975787,"cat":"LobbyB","room":"ออ-1782497820821","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+922ms]","src":"client"}
{"t":1782497979040,"cat":"LobbyB","room":"ออ-1782497820821","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+5482ms]","src":"client"}
{"t":1782497986083,"cat":"LobbyB","room":"ออ-1782497820821","who":"Q","ev":"preload-occupants-done","detail":" [+12533ms]","src":"client"}
{"t":1782497986087,"cat":"LobbyB","room":"ออ-1782497820821","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+12533ms]","src":"client"}
{"t":1782497986090,"cat":"LobbyB","room":"ออ-1782497820821","who":"Q","ev":"preload-ready(occupants)","detail":" [+12533ms]","src":"client"}
{"t":1782498298051,"cat":"LobbyB","room":"ออ-1782497820821","who":"MONE","ev":"socket-connect","detail":" [+323224ms]","src":"client"}
{"t":1782498298102,"cat":"LobbyB","room":"ออ-1782497820821","who":"Q","ev":"socket-connect","detail":" [+324555ms]","src":"client"}
{"t":1782498388994,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"lobby-open","detail":"space=aasd-1782498385865 [+0ms]","src":"client"}
{"t":1782498389025,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"preload-start","detail":" [+13ms]","src":"client"}
{"t":1782498389083,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"manifest-done","detail":" [+101ms]","src":"client"}
{"t":1782498389084,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"colors-resolved","detail":" [+102ms]","src":"client"}
{"t":1782498389109,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"socket-connect","detail":" [+130ms]","src":"client"}
{"t":1782498389114,"cat":"LobbyA","room":"aasd","who":"Q","ev":"join","detail":"สี#7 · คน 1 + บอท 4","src":"server"}
{"t":1782498390305,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"join-ok","detail":"peers=1 host=me map=mlsbbxfe bots=4 [+1304ms]","src":"client"}
{"t":1782498394418,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"mychar-tinted","detail":"roomJoinReady=true [+5432ms]","src":"client"}
{"t":1782498394734,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"lobby-open","detail":"space=aasd-1782498385865 [+0ms]","src":"client"}
{"t":1782498394774,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"preload-start","detail":" [+23ms]","src":"client"}
{"t":1782498394781,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"manifest-done","detail":" [+24ms]","src":"client"}
{"t":1782498394794,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"colors-resolved","detail":" [+24ms]","src":"client"}
{"t":1782498394798,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"mychar-tinted","detail":"roomJoinReady=false [+24ms]","src":"client"}
{"t":1782498394807,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"preload-occupants-done","detail":" [+25ms]","src":"client"}
{"t":1782498394810,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"preload-ready(occupants)","detail":" [+25ms]","src":"client"}
{"t":1782498394888,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"socket-connect","detail":" [+154ms]","src":"client"}
{"t":1782498394918,"cat":"LobbyA","room":"aasd","who":"MONE","ev":"join","detail":"สี#5 · คน 2 + บอท 4","src":"server"}
{"t":1782498395617,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"join-ok","detail":"peers=2 host=other map=mlsbbxfe bots=4 [+870ms]","src":"client"}
{"t":1782498395621,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+870ms]","src":"client"}
{"t":1782498403982,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"preload-occupants-done","detail":" [+15000ms]","src":"client"}
{"t":1782498403984,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+15000ms]","src":"client"}
{"t":1782498403985,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"preload-ready(occupants)","detail":" [+15000ms]","src":"client"}
{"t":1782498427244,"cat":"LobbyA","room":"aasd-1782498385865","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+38242ms]","src":"client"}
{"t":1782498427308,"cat":"LobbyA","room":"aasd-1782498385865","who":"MONE","ev":"loading-hide","detail":"เริ่มเล่นได้ [+32499ms]","src":"client"}
{"t":1782498432003,"cat":"LobbyB","room":"aasd-1782498385865","who":"Q","ev":"loading-hide","detail":"เริ่มเล่นได้ [+43019ms]","src":"client"}
{"t":1782498434508,"cat":"MG1","room":"aasd","who":"","ev":"game-start","detail":"เริ่มมินิเกม: Minigame-1 จริงหรือไม่ (การ์ด 1)","src":"server"}
{"t":1782498434627,"cat":"MG1","room":"aasd","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782498434627,"cat":"MG1","room":"aasd","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782498434844,"cat":"MG1","room":"aasd","who":"MONE","ev":"join","detail":"สี#5 · คน 1 + บอท 4","src":"server"}
{"t":1782498434936,"cat":"MG1","room":"aasd","who":"Q","ev":"join","detail":"สี#7 · คน 2 + บอท 4","src":"server"}
{"t":1782498573171,"cat":"MG1","room":"aasd","who":"Q","ev":"host-change","detail":"host ใหม่ → MONE","src":"server"}
{"t":1782498573171,"cat":"MG1","room":"aasd","who":"Q","ev":"leave","detail":"ออกจากห้อง · เหลือคน 1","src":"server"}
{"t":1782498583172,"cat":"MG1","room":"aasd","who":"Q","ev":"bot-takeover","detail":"หลุดเกิน 10วิ → บอทแทน (สีตามคนออก)","src":"server"}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,722 @@
[
{
"n": 1,
"name": "แต่งตัวไม่ได้",
"detail": "แต่งตัวยังไม่ได้ มีพี่คิวทำได้คนเดียว",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "LobbyA"
},
{
"n": 2,
"name": "ตัวละครไม่แสดง",
"detail": "หน้าเลือกเกม Quiz battle ภาพตัวละครไม่แสดง",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "Minigame 1"
},
{
"n": 3,
"name": "ระบบ join เกมมีปัญหา",
"detail": "เมื่อเข้ามินิเกม : บางคนเล่นเกมกะบอท บางคนเล่นกะเพื่อน แต่ละคนเข้ามินิเกมแล้วเจอกันบ้าง ไม่เจอกันบ้าง",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 4,
"name": "ระบบ Host มีปัญหา - 1",
"detail": "เป็น host ในเกม ตอนที่เลือกผู้ต้องสงสัย รอบที่ 2 ระบบบอกว่าให้รอ host ไม่สามารถเลือกการ์ดและกดเริ่มสืบสวนได้",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "LobbyB"
},
{
"n": 5,
"name": "ระบบ Host มีปัญหา - 2",
"detail": "เมื่อกดออกจากเกม Host เปลี่ยนจากพี่ต้อมเป็นพี่คิวอัติโนมัติ",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 6,
"name": "ระบบ Host มีปัญหา - 3",
"detail": "เมื่อเข้ามินิเกม ทุกคนเห็นตัวเองเป็น host หมดเลย แต่กดเริ่มเกมไม่ได้",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 7,
"name": "ระบบสีตัวละคร ยังใช้ไม่ได้",
"detail": "สีตัวละครเปลี่ยนไปเรื่อย ไม่รุ้ว่าเราสีอะไรแน่ งงไปหมด",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 8,
"name": "หน้าเข้าร่วมเกมส์",
"detail": "ห้องไหนที่เริ่มเกมส์ไปแล้ว เมื่อกดเข้าร่วมแสดง popup alert error ปรับดีไซต์ให้สวยงามกว่านี้",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 9,
"name": "เกมวิ่งขึ้นบันได ผิด flow",
"detail": "ปรับ flow ให้ถูกต้อง คือ ใครตกจอตาย แต่ถ้าขึ้นไปอยู่บนสุดแล้วจะกระโดดไม่ไปต่อเฉยๆ แต่ไม่ตาย",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "Minigame 5"
},
{
"n": 10,
"name": "เกมวิ่งขึ้นบันได",
"detail": "เวลาหมดแล้ว ให้เล่นรอบ 2 auto \/ รอบ 3 มี popup ให้กดเล่นต่อ",
"prio": "",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "Minigame 2"
},
{
"n": 11,
"name": "เกมยิงลูกโป่ง",
"detail": "ฉากเกมยิงลูกโป่ง (MG7 Mega Virus) เล็กไป — ต้องการให้ภาพพื้นหลัง (BG) เต็มจอ แต่การเดิน (movement) และพื้นที่เล่น (area) ต่างๆ คงเดิม",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "แก้แล้ว (deploy prod play.js?v=0.006250401): BG ของ MG7 เป็นภาพ 16:9 (1920x1080) แต่โค้ดเดิม map ภาพเข้า world rect 4:3 (640x480) ทำให้ภาพถูกบีบ + เหลือขอบดำซ้าย-ขวา = ฉากดูเล็ก. เปลี่ยนการวาด BG ของ balloon_boss เป็นแบบ cover เต็มจอ (รักษาสัดส่วน 16:9, crop ส่วนเกิน, จัดกึ่งกลาง) วาดแยกจาก world layer → กล้อง\/movement\/area ของเกมคงเดิมทุกอย่าง เปลี่ยนเฉพาะพื้นหลังให้เต็มจอ. ไฟล์: Game\/public\/js\/play.js (draw loop, สาขา isBalloonBoss cover-fill).",
"cat": "Minigame 7"
},
{
"n": 13,
"name": "เข้าร่วมห้องไม่ได้",
"detail": "สร้างห้องส่วนตัวเเล้ว เเต่เพื่อนจอยเข้าไปไม่ได้ ทั้งที่กรอกข้อมูลครบ",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "LobbyA"
},
{
"n": 14,
"name": "Room ID",
"detail": "เวลาจอยห้องให้กรอกเเค่ ID กับรหัสที่สร้าง",
"prio": "ต่ำ",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 15,
"name": "จอยห้องคนอื่น",
"detail": "ในกรณีที่จอยห้องคนอื่น ไปหน้าเข้าร่วม เเละกดปุ่มเข้าร่วมไปเเล้ว จากนั้นกดปุ่ม exit จะพาไปหน้าสร้างห้อง สิ่งที่ถูกต้อง มันควรมาหน้า ห้องเข้าร่วมเกม",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "LobbyA"
},
{
"n": 16,
"name": "grid กับ ฉาก ไม่ตรงกัน",
"detail": "เกม Quiz battle เกมที่ 1 ฉากกับกริดไม่ตรงกัน ทำให้เดินทะลุ หรือเดินติดในจุดที่ไม่ควรติด",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "Minigame 1"
},
{
"n": 17,
"name": "ตัวละครวิ่งเร็วเกินไป",
"detail": "เกม Quiz battle เกมที่ 1 ตัวละครผู้เล่นเร็วเกินไป",
"prio": "กลาง",
"status": "เปิด",
"updated": "2026-06-25",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 18,
"name": "Oauth Social log-in error",
"detail": "ไม่สามารถ log-inด้วย facebook \/ Google ได้ path: \/oauth-public.php",
"prio": "ต่ำ",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 19,
"name": "หน้า login",
"detail": "นโยบายความเป็นส่วนตัวกดไม่ได้",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 20,
"name": "แสดงเลข version ตรงมุมจอ",
"detail": "แสดงเลข version ตรงมุมจอขวาบนหรือขวาล่างก็ได้",
"prio": "ต่ำ",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — badge มุมขวาล่าง อ่าน ?v= อัตโนมัติ",
"cat": "อื่นๆ"
},
{
"n": 21,
"name": "ลดขนาดตัวละคร",
"detail": "ลดขนาดตัวละครในห้อง lobby ลงอีก 2เท่า",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 22,
"name": "เปลี่ยน ui popup ตอนพูดบนหัว",
"detail": "แก้ png seq บนหัวใหม่ เป็นแบบอื่น",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 23,
"name": "ชื่่อตัวละครทับลำโพง\/ทับ bubble",
"detail": "ใน lobby ขยับชื่อลงมาอย่าให้ทับ",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 24,
"name": "UI แต่งตัว : การแจ้งเตือนสีตัวละครถูกใช้แล้ว",
"detail": "ตอนเลือกสีให้มีคำแจ้งเตือน used",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "LobbyA"
},
{
"n": 25,
"name": "เพิ่ม ข้อความแจ้งเตือนอัพเดทกลางจอ",
"detail": "ถ้ามีการอัพเดทซีน อัพเดทสีตัวละครให้มีป็อปอัพเด้งมากลางหน้าจอ ว่ามีการอัพเดทและให้รอโหลด",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 26,
"name": "เอาเงาตัวละครออก 1 อัน",
"detail": "ตอนนี้ตัวละครมีเงา 2 ชั้น เอาออกไป 1 ชั้น",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — ปิด default-shadow overlay เหลือเงาในสไปรต์",
"cat": "อื่นๆ"
},
{
"n": 27,
"name": "optimize ตัวละครให้เล็กลงอีก มันโหลดช้า",
"detail": "",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 28,
"name": "ปุ่ม start ใน lobby",
"detail": "ทำให้ดูโต้ตอบหน่อย เช่นพอเดินเข้าไปใกล้ให้มัน glow ขึ้นมา",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 31,
"name": "เอา mock การ์ดผู้ต้องหาเก่าออกไป",
"detail": "มันแว่บๆมา",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.006242530 (รอเทส) — ซ่อนรูปจนรูปคดีจริงโหลด + spinner",
"cat": "LobbyB"
},
{
"n": 32,
"name": "เอา popup ขออนุญาตใช้ไมค์ออกไปเลย น่ารำคาญ",
"detail": "",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 33,
"name": "หน้า howto เปลี่ยนสีปุ่ม ready ด้วยตอน กดready แล้ว",
"detail": "เปลี่ยนเป้นสีเขียวพร้อมเครื่องหมายถูกตามดีไซน์",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "LobbyA"
},
{
"n": 34,
"name": "เกม ใช่ หรือไม่ : ตอนจบบั๊ค",
"detail": "ตอนสรุปคะแนน ยังนับเวลาอยุ่ และขึ้น gameover ทับหน้าสรุปคะแนน",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG1 ใช่\/ไม่: capture mg1AnyScore ก่อนล้าง (gameover) + guard quiz-phase หลังจบ (timer)",
"cat": "Minigame 1"
},
{
"n": 35,
"name": "เกมวิ่ง : กดปุ่มไม่กระโดด",
"detail": "ปุ่ม jump กดแล้วไม่กระโดด",
"prio": "วิกฤต",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "Minigame 5"
},
{
"n": 36,
"name": "เกมวิ่ง : ตอนจบบั๊ค วิ่งเลยฉาก",
"detail": "ตอนจบบั๊ค วิ่งเลยฉาก (ในบางรอบ)",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG2 วิ่งเลยฉาก: walk-to-finish ค่อยๆเดินเข้าเส้น + clamp ไม่เลยเส้น",
"cat": "Minigame 2"
},
{
"n": 37,
"name": "popup รับหลักฐาน ทับไมค์",
"detail": "กดไมค์ไม่ได้ ตอนรับหลักฐาน ไปดูเรื่องเลเยอร์อีกที",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "LobbyB"
},
{
"n": 38,
"name": "หน้าส่งหลักฐาน ปุ่มส่งหลักฐานหลุดจอ (เครื่องของเนส)",
"detail": "เป้นเครื่องเนสคนเดียว",
"prio": "วิกฤต",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "ระบบ disconnect"
},
{
"n": 39,
"name": "ห้องส่งหลักฐาน : เมื่อมีคนหลุด 1 คน จะไปต่อไม่ได้เลย",
"detail": "",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — testimony: disconnect ลบ submit\/ready + client ใช้ totalPlayers authoritative",
"cat": "ระบบ disconnect"
},
{
"n": 40,
"name": "จำนวนคน ให้เล่นได้ตั้งแต่ 4-6 คน",
"detail": "กรณีเลือกผู้เล่นตั้งแต่ 4 คนขึ้นไปไม่ต้องมี bot",
"prio": "วิกฤต",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 41,
"name": "เกม หยิบแผ่นป้าย",
"detail": "ต้องเล่นให้ครบ 10 ข้อก่อน ค่อยจบเกม (ตอนนี้เล่นถูก 1 ข้อ จบเกมเลย)",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG4 หยิบป้าย: ใช้ map จริง (currentPlayMapId) เปิด mission flow + default 10 ข้อ",
"cat": "Minigame 4"
},
{
"n": 42,
"name": "เกม กระโดด",
"detail": "ท่ากระโดดแปลก ยืนซอยเท้าทำไม",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "anim ไม่ sync: ยืนบนแท่นที่เลื่อนลง world Y เปลี่ยนทุกเฟรม → ปลายทางเดา isWalking จาก delta = เห็น ซอยเท้า ตลอด. แก้: ส่ง isWalking จริงใน move (jsWalking) + ปลายทางใช้ค่านั้น (play.js ~19162\/20501\/24930). v0.006260100",
"cat": "Minigame 5"
},
{
"n": 43,
"name": "เกม กระโดด",
"detail": "ขั้นบันไดมันถี่ไป บางทีกระโดดแล้วเบิ้ลขั้นเลย ปรับให้ระยะห่างแต่ละขั้นมันเท่ากัน",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "ขั้นถี่\/ไม่เท่า → เบิ้ลขั้น+ติดรอแท่ง. แก้ layout mnptfts2: ระยะเท่ากันทุกขั้น (gap 3 แถว, rows 2\/5\/8\/11\/14\/17, zigzag กว้าง6) ในโซนปลอดภัย (เลี่ยง hazard แถว 0\/18\/19). reach apex 4.5 > 3 = ถึงทุกขั้น (ไม่ติดรอ #43b) + ขั้นถัดไป-อีกขั้น 6 แถว > reach = กระโดดข้ามไม่ได้ (ไม่เบิ้ล). seam รอยต่อ wrap ห่าง 5 แถว 1 จุด\/รอบ (h=20 หาร 3 ไม่ลง). restart service หลังแก้แมป | รอบ2: (ก) แก้ลายแท่นบิด — เดิม width เท่ากัน(6)ทำให้ภาพถูกบีบ → ตั้ง width = ขนาดจริงของรูป (เล็ก=var3 7ช่อง\/212px, กลาง=var2 13ช่อง\/389px) วาดได้สัดส่วนจริงไม่บิด. (ข) ติดบนสุด = seam รอยต่อ wrap 5แถว >ระยะกระโดด(apex4.5) → bump jumpSurviveJumpHeightMult 1.5→1.7 (apex 5.1) ให้ข้าม seam ได้ แต่ข้าม2ขั้น(6แถว)ยังไม่ได้. var1(ใหญ่ 46ช่อง)ใหญ่เกินแมป35 ใช้ไม่ได้ไม่บิด → ใช้ เล็ก\/กลาง",
"cat": "Minigame 5"
},
{
"n": 44,
"name": "เกมกระโดด",
"detail": "อีเวนท์พิเศษ (ทนาย\/เทพความรู้) หายไป",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG5 อีเวนต์พิเศษ: เพิ่ม branch jump_survive วาง icon บน platform",
"cat": "Minigame 5"
},
{
"n": 45,
"name": "เกมไม่รองรับ 4K",
"detail": "หน้ารับหลักฐาน (หลังจากเล่นเกมจบ)",
"prio": "วิกฤต",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "LobbyB"
},
{
"n": 46,
"name": "เกมยิิงอุกาบาด",
"detail": "สีตัวละครยังไม่ตรงกับที่เลือกมา",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG6 สี: ยาน Rocket-1..8 ตาม lobby theme ของผู้เล่น",
"cat": "Minigame 6"
},
{
"n": 47,
"name": "เกมยิิงอุกาบาด",
"detail": "อุกาบาดให้พุ่งเร็วกว่านี้ และลูกเล็กกว่านี้เกมง่ายไป",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG6: อุกาบาตเร็วขึ้น (+~50%) + เล็กลง (48->34\/11->8)",
"cat": "Minigame 6"
},
{
"n": 48,
"name": "เพิ่ม popup เมื่อเกมค้าง เล่นต้่อไม่ได้ ให้มีปุ่มกดออกไปหน้าแรกสุด",
"detail": "สาเหตุเกิดจากมีคนหลุดระหว่างรอ host กด",
"prio": "วิกฤต",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "ระบบ disconnect"
},
{
"n": 49,
"name": "กรณีผู้เล่นหลุดออกจากเกม",
"detail": "ถ้ามีคนหลุด ให้กลายเป้นบอทแทน",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "แก้แล้ว 2026-06-25: คนออกระหว่าง LobbyB\/เปลี่ยนหน้า กลายเป็นบอทสีตามคนออก (ดูบั๊ก #73)",
"cat": "ระบบ disconnect"
},
{
"n": 50,
"name": "ผู้เล่น 6 คน: บางเกมเล่นได้แค่ 5 (คนที่ 6 หายจากสรุป)",
"detail": "สรุปคะแนนฝั่ง client slice(0,5) ตัดคนที่ 6 — แก้เป็น slice(0,6) ทุกมินิเกม (MG1\/3\/4\/5\/6\/7)",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส)",
"cat": "Minigame 1"
},
{
"n": 51,
"name": "ผู้เล่น 6 คน: คะแนนตอนจบไม่ตรงกันแต่ละจอ",
"detail": "MG1 merge คะแนน server \/ MG6,7 merge คะแนน host -> ครบ 6 ตรงกัน (MG3 ยัง local)",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส)",
"cat": "Minigame 6"
},
{
"n": 52,
"name": "หน้าไต่สวน\/สรุปหลักฐาน: กรอบปลิ้นตอน 6 คน",
"detail": "member row grid repeat(5)->repeat(6) ใน testimony-overlay.css (คนที่6 ตกแถว2)",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.006242530 (รอเทส)",
"cat": "LobbyB"
},
{
"n": 53,
"name": "เพิ่มหน้าโหลด (loading) ตอนเข้าเกม",
"detail": "overlay spinner กันเห็นจอเปล่า\/asset แว่บ ซ่อนเมื่อ draw เฟรมแรก + safety 8s",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.006242530 (รอเทส)",
"cat": "อื่นๆ"
},
{
"n": 54,
"name": "host โหลดนานมากตอนเข้าเกม",
"detail": "optimize asset\/char (เกี่ยว row 28) — loading overlay ช่วยซ่อน แต่ยังโหลดช้าจริง",
"prio": "สูง",
"status": "เปิด",
"updated": "2026-06-25",
"note": "loading overlay บังอาการแล้ว · root = canvas tint ภาพตัวละครใหญ่ (source ไม่อยู่ใน repo) → ต้อง optimize ภาพแยก",
"cat": "อื่นๆ"
},
{
"n": 55,
"name": "หลังออกจาก LobbyA ไม่ให้ใครเข้า join",
"detail": "server มี joinLocked (set ตอน LobbyA->case ~8656, check ~7585 whitelist nickname) — ต้อง repro ว่าใครเข้าได้ยังไง (room list ยังโชว์? ชื่อซ้ำ whitelist?)",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 — กรองห้อง joinLocked ออกจาก \/api\/spaces list (ห้องเริ่มคดีแล้วหาย) + server reject อยู่แล้ว",
"cat": "LobbyB"
},
{
"n": 56,
"name": "ตอนกลับ LobbyB โชว์รูปแรกก่อนแล้วค่อยถูก",
"detail": "เหมือน #1 การ์ด — ต้องใส่ loading state ตอน return LobbyB ด้วย (มี room-loading-overlay อยู่แต่ซ่อนเร็วไป)",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.0308 — การ์ดมี spinner (#1) + room-loading overlay ใส่ % + รอ char preload เสร็จก่อนซ่อน + safety 12s",
"cat": "อื่นๆ"
},
{
"n": 57,
"name": "เล่นมินิเกมเกิน 3 ครั้งต่อผู้ต้องสงสัย (+การ์ดพิเศษโผล่รอบที่4)",
"detail": "server cap suspect-pick-start (max หลักฐาน>=3 reject) + award cap 3 + client canInvestigateSuspect<3 (เดิม stub return true). UI messaging มีอยู่แล้ว",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.0309\/server (รอเทส)",
"cat": "LobbyB"
},
{
"n": 58,
"name": "ปุ่ม \"เล่นเกมต่อ\" ไม่รู้ว่าค้างหรือรอคนอื่น",
"detail": "text \"รอผู้เล่นอื่น (X\/Y)\" ถูก set อยู่แล้วแต่ CSS font-size:0 ซ่อน → เพิ่ม .is-waiting CSS โชว์ข้อความ+spinner แทนรูปปุ่ม",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.0309\/server (รอเทส)",
"cat": "อื่นๆ"
},
{
"n": 59,
"name": "loading ไม่คลุม scene transition (เห็นฉากเก่าก่อนเปลี่ยน)",
"detail": "LobbyA->B (in-page swap) โชว์ room-loading ระหว่าง fetch+swap · LobbyB->เกม โชว์ overlay ก่อน location.href · play.html มี overlay รับช่วง",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.0309\/server (รอเทส)",
"cat": "LobbyA"
},
{
"n": 60,
"name": "ทำหน้า testcase บนเซิร์ฟเวอร์",
"detail": "srv1361159.hstgr.cloud\/testcase — bug list + filter\/search\/นับสถานะ generate จาก xlsx",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.0309\/server (รอเทส)",
"cat": "อื่นๆ"
},
{
"n": 62,
"name": "MG1\/MG4 user\/bot ติดกัน (เดินไม่ผ่าน)",
"detail": "เพิ่ม anti-stuck: ดันชนเพื่อน → เขย่า (shake) + ปลดล็อกเดินผ่านกันชั่วคราว คงกำแพง\/area\/quiz-lock; ทั้งผู้เล่นและบอท",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.006250100 (รอเทส)",
"cat": "Minigame 4"
},
{
"n": 63,
"name": "LobbyA มือถือ กดเดินไม่ได้",
"detail": "lobby canvas มีแค่ dblclick (ไม่มี touch) → มือถือแตะเดินไม่ได้. แก้: เพิ่ม tap-to-walk (เฉพาะ touch, PC ยัง dblclick) + DPI-safe coord + touch-action:none + zoom-out default บนจอ<600px (PC ย่อส่วน)",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 room-lobby.js?v=0.0310 (รอเทสมือถือ) · PC ไม่กระทบ",
"cat": "LobbyA"
},
{
"n": 64,
"name": "มือถือ: ปุ่มแชท AI ใหญ่ไป + ปุ่ม F (host) ไม่มี",
"detail": "AI chat collapsed btn 213x201px → ใหญ่บนมือถือ. + การกด F (interact: host เลือกระดับ\/คดี, ห้องแต่งตัว) ไม่มีบนมือถือ",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 (css 0.0176\/js 0.0311): media<600px ย่อปุ่ม AI (92px) + ปุ่มลอย \"โต้ตอบ(F)\" บน touch-primary device (dispatch synthetic KeyF). PC ไม่เห็น",
"cat": "LobbyB"
},
{
"n": 65,
"name": "อีเวนต์พิเศษ (ทนาย\/เทพ) = 1 ใน 3 (ตามดีไซน์)",
"detail": "ดีไซน์: 3 เกม\/LobbyB เล่นได้เกมละ 3 ครั้ง · อีเวนต์พิเศษ 1\/3 ต่อครั้ง (1 ใบ) · Test Mode บังคับ. revert การแก้ \">1 ต่อรอบ\" กลับเป็น 1 ใบ\/ครั้งที่ติด",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ revert 2026-06-25 — กลับเป็น 1\/3 (1 ใบ\/ครั้งที่ติด) ตามดีไซน์ · ยืนยันโครงสร้าง 3เกม×3ครั้ง + disruptor toggle (>4คน\/Test Mode) ถูกต้อง",
"cat": "อื่นๆ"
},
{
"n": 66,
"name": "host หลุด → ย้าย host ให้คนอยู่นานสุด",
"detail": "pickNextHostPeer เลือก spawnJoinOrder ต่ำสุด (เสถียรข้าม reconnect) แทน Map-first + host จริง reclaim ได้",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 (server) — Part 1 host migration",
"cat": "ระบบ disconnect"
},
{
"n": 67,
"name": "คนหลุดกลางเกม → 10 วิ reconnect + บอทเล่นแทน",
"detail": "peer-disconnect-grace แบนเนอร์นับ 10 วิ · กลับทัน=cancel เล่นต่อ · ครบเวลา=peer-bot-takeover host เติมบอท 1 ตัว (rebalance, cap≤6). บอทไม่สืบทอดตำแหน่ง\/คะแนน",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 (server+play.js v0.006250400) — Part 2 แบบ A · seamless(host คุม entity เดิม)=ค้าง(เสี่ยง)",
"cat": "ระบบ disconnect"
},
{
"n": 69,
"name": "UI ห้องเกม (LobbyA) มือถือแนวนอน — ย่อให้พอดี",
"detail": "room-lobby ไม่มี landscape media query → chat panel(576x525), ปุ่ม voice\/แว่น\/ถ้วย(80px), AI chat ล้น\/ใหญ่บนแนวนอน. เพิ่ม @media(landscape+max-height:540px) ย่อตามความสูงจอ (อิง Main-Lobby pattern)",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 room-lobby.css?v=0.0177 — chat\/BR buttons\/AI\/ready\/exit · overlay หลักฐาน-อันดับ (inline\/JS) ยังต้องทำแยก",
"cat": "LobbyB"
},
{
"n": 70,
"name": "การ์ดรางวัลหลักฐาน มือถือใหญ่เกิน กดปุ่มไม่ได้",
"detail": "หน้าโชว์การ์ดรางวัล \"คุณได้รับหลักฐาน!\" (หลังจบมินิเกมสืบสวน) บนมือถือการ์ดใหญ่มากจนเนื้อหา+ปุ่ม \"เก็บเข้าแฟ้ม\" หลุดล่างจอ กดปิดไม่ได้",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "แก้แล้ว (deploy prod play.js?v=0.006250402): ทำ overlay เป็น scroll container + inner margin:auto (กัน flexbox clip ด้านบนเวลาเนื้อหาสูงเกินจอ) + คุมขนาดการ์ด\/หัวข้อ\/ปุ่มด้วย clamp ตาม viewport (การ์ด max-width min(72vw,360px) + max-height 52vh, ปุ่ม font\/padding clamp). มือถือแนวตั้งเลื่อนถึงปุ่มได้เสมอ. ไฟล์: Game\/public\/js\/play.js (showInSceneEvidenceReveal).",
"cat": "ระบบ disconnect"
},
{
"n": 71,
"name": "หน้าผลชนะ (โพเดียม) ตัวละครลอย ไม่ยืนบนพื้น",
"detail": "หน้า \"ยินดีด้วย ทีมนักสืบ ชนะ!\" ตัวละครผู้ชนะลอยอยู่กลางอากาศ ไม่ยืนบนพื้นเวที",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "แก้แล้ว (deploy prod room-lobby.js?v=0.0312): พื้นหลัง win-bg เดิม center\/cover ทำให้พื้นเวทีถูก crop เลื่อน + podium ตั้ง bottom:9% ตัวละครเลยลอย. แก้เป็น (1) ปักพื้นหลังไว้ขอบล่าง background-position:center bottom -> พื้นเวทีติดขอบล่างจอเสมอทุกสัดส่วน (2) ลด podium bottom 9% -> 2% ให้ตัวละครยืนบนพื้น. ไฟล์: Game\/public\/js\/room-lobby.js (injectFinalResultStyle, #trial-final-podium).",
"cat": "อื่นๆ"
},
{
"n": 72,
"name": "ป๊อปอัปขอสิทธิ์ไมค์ เด้งทุกครั้งที่เข้า Lobby",
"detail": "หน้าขอสิทธิ์ไมโครโฟน (mic-permission-overlay) เด้งขึ้นทุกครั้งที่เข้า LobbyA\/LobbyB น่ารำคาญ ทั้งที่เบราว์เซอร์จำสิทธิ์ให้แล้ว",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "แก้แล้ว (deploy prod room-lobby.js?v=0.0313): เดิม overlay เป็น display:flex default จึงเด้งทุกครั้งที่โหลดหน้า. เพิ่มตรวจสิทธิ์ผ่าน navigator.permissions.query(microphone) + จำสถานะใน localStorage (justiceMicPromptHandled). แสดงเฉพาะครั้งแรกที่ยังไม่เคยตัดสินใจ (permission=prompt และยังไม่เคยกดอนุญาต\/ปิด); ถ้า granted แล้ว\/เคยจัดการแล้ว → ซ่อนทันที (มี inline script กันแฟลชก่อน paint). ปุ่ม 🎤 ขอสิทธิ์ไมค์ ในห้องยังใช้ขอใหม่ได้. ไฟล์: room-lobby.html (inline gate) + room-lobby.js (gateMicPermissionOverlay, hideMicPermissionOverlay).",
"cat": "LobbyA"
},
{
"n": 73,
"name": "คนออก LobbyB \/ ช่วงเปลี่ยนหน้า → ไม่เติมบอท + ค้างรอผู้เล่น เริ่มเกมต่อไม่ได้",
"detail": "คนหลุดระหว่างนั่งอยู่ LobbyB หรือช่วงเปลี่ยนหน้า minigame→LobbyB เดิมไม่ถูกเติมบอทแทน + ยังถูกนับใน roster คดี → host กดเริ่มสืบสวนรอบต่อไปไม่ได้ ค้าง รอผู้เล่น (x\/y) ตลอดไป",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "ขยาย grace+bot-takeover gate ให้ครอบ LobbyB\/คดีล็อก ไม่ใช่แค่ minigame active (server.js ~8921: inCaseFlowForBot = detectiveMinigameActive || serverMapIsPostCaseLobbyB || (joinLocked && caseParticipantNicknames.size>0)). คนออก→หลัง grace 10วิ ลบจาก roster + เติมบอทสีตามคนออก + presence ใหม่ → allHere=true เล่นต่อได้. + ส่ง botSlotCount ใน lobby-tint-sync (server.js ~121) + client อัปเดต lobbyBotSlotCount ก่อน render (room-lobby.js ~768) ให้บอทโผล่ทันทีไม่ต้อง re-join. v0.0323",
"cat": "ระบบ disconnect"
},
{
"n": 74,
"name": "แถวหน้าตัวละคร (ready ใต้ปุ่ม HOW TO) ค้างบนจอระหว่างเล่นเกม",
"detail": "หลังกด HOW TO\/Ready แล้วเริ่มเกม กล่องแถว avatar คนที่กด ready (ใต้ปุ่ม) ไม่ถูกซ่อน ค้างอยู่กลางจอล่างทับฉากเกม (เห็นชัดใน MG3 stack) — กระทบ MG1\/3\/5\/6",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "กล่องลอย #gch-ready-avatars-float ถูกซ่อนเฉพาะ MG2 (dismissGauntletCrownHowtoOverlayPlay) + MG4 (quiz_carry) เท่านั้น. begin*CountdownThenRun ของ MG1\/3\/5\/6 (stack\/jump\/space\/quiz) ตั้ง gauntletCrownHowtoVisible=false แต่ไม่เรียก hideReadyAvatarsFloat() → กล่องค้าง display:flex ทั้งเกม (ไม่มี driver เรียกใหม่ตอน live). แก้: เพิ่ม hideReadyAvatarsFloat() ในทั้ง 4 ฟังก์ชันเริ่มเกม (play.js). v0.006260101",
"cat": "อื่นๆ"
},
{
"name": "block สีไม่ตรงในฝั่ง client",
"detail": "",
"prio": "กลาง",
"status": "เปิด",
"note": "",
"cat": "Minigame 3",
"updated": "2026-06-26",
"n": 75
},
{
"name": "บางที client บางคนเล่นไม่ได้",
"detail": "",
"prio": "กลาง",
"status": "เปิด",
"note": "",
"cat": "Minigame 3",
"updated": "2026-06-26",
"n": 76
},
{
"name": "เปลี่ยนปุมลำโพง",
"detail": "",
"prio": "กลาง",
"status": "เปิด",
"note": "",
"cat": "LobbyA",
"updated": "2026-06-26",
"n": 77
}
]
@@ -0,0 +1,832 @@
[
{
"n": 1,
"name": "แต่งตัวไม่ได้",
"detail": "แต่งตัวยังไม่ได้ มีพี่คิวทำได้คนเดียว",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "LobbyA"
},
{
"n": 2,
"name": "ตัวละครไม่แสดง",
"detail": "หน้าเลือกเกม Quiz battle ภาพตัวละครไม่แสดง",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "Minigame 1"
},
{
"n": 3,
"name": "ระบบ join เกมมีปัญหา",
"detail": "เมื่อเข้ามินิเกม : บางคนเล่นเกมกะบอท บางคนเล่นกะเพื่อน แต่ละคนเข้ามินิเกมแล้วเจอกันบ้าง ไม่เจอกันบ้าง",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 4,
"name": "ระบบ Host มีปัญหา - 1",
"detail": "เป็น host ในเกม ตอนที่เลือกผู้ต้องสงสัย รอบที่ 2 ระบบบอกว่าให้รอ host ไม่สามารถเลือกการ์ดและกดเริ่มสืบสวนได้",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "LobbyB"
},
{
"n": 5,
"name": "ระบบ Host มีปัญหา - 2",
"detail": "เมื่อกดออกจากเกม Host เปลี่ยนจากพี่ต้อมเป็นพี่คิวอัติโนมัติ",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 6,
"name": "ระบบ Host มีปัญหา - 3",
"detail": "เมื่อเข้ามินิเกม ทุกคนเห็นตัวเองเป็น host หมดเลย แต่กดเริ่มเกมไม่ได้",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 7,
"name": "ระบบสีตัวละคร ยังใช้ไม่ได้",
"detail": "สีตัวละครเปลี่ยนไปเรื่อย ไม่รุ้ว่าเราสีอะไรแน่ งงไปหมด",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 8,
"name": "หน้าเข้าร่วมเกมส์",
"detail": "ห้องไหนที่เริ่มเกมส์ไปแล้ว เมื่อกดเข้าร่วมแสดง popup alert error ปรับดีไซต์ให้สวยงามกว่านี้",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 9,
"name": "เกมวิ่งขึ้นบันได ผิด flow",
"detail": "ปรับ flow ให้ถูกต้อง คือ ใครตกจอตาย แต่ถ้าขึ้นไปอยู่บนสุดแล้วจะกระโดดไม่ไปต่อเฉยๆ แต่ไม่ตาย",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "Minigame 5"
},
{
"n": 10,
"name": "เกมวิ่งขึ้นบันได",
"detail": "เวลาหมดแล้ว ให้เล่นรอบ 2 auto / รอบ 3 มี popup ให้กดเล่นต่อ",
"prio": "",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "Minigame 2"
},
{
"n": 11,
"name": "เกมยิงลูกโป่ง",
"detail": "ฉากเกมยิงลูกโป่ง (MG7 Mega Virus) เล็กไป — ต้องการให้ภาพพื้นหลัง (BG) เต็มจอ แต่การเดิน (movement) และพื้นที่เล่น (area) ต่างๆ คงเดิม",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "แก้แล้ว (deploy prod play.js?v=0.006250401): BG ของ MG7 เป็นภาพ 16:9 (1920x1080) แต่โค้ดเดิม map ภาพเข้า world rect 4:3 (640x480) ทำให้ภาพถูกบีบ + เหลือขอบดำซ้าย-ขวา = ฉากดูเล็ก. เปลี่ยนการวาด BG ของ balloon_boss เป็นแบบ cover เต็มจอ (รักษาสัดส่วน 16:9, crop ส่วนเกิน, จัดกึ่งกลาง) วาดแยกจาก world layer → กล้อง/movement/area ของเกมคงเดิมทุกอย่าง เปลี่ยนเฉพาะพื้นหลังให้เต็มจอ. ไฟล์: Game/public/js/play.js (draw loop, สาขา isBalloonBoss cover-fill).",
"cat": "Minigame 7"
},
{
"n": 13,
"name": "เข้าร่วมห้องไม่ได้",
"detail": "สร้างห้องส่วนตัวเเล้ว เเต่เพื่อนจอยเข้าไปไม่ได้ ทั้งที่กรอกข้อมูลครบ",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "LobbyA"
},
{
"n": 14,
"name": "Room ID",
"detail": "เวลาจอยห้องให้กรอกเเค่ ID กับรหัสที่สร้าง",
"prio": "ต่ำ",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 15,
"name": "จอยห้องคนอื่น",
"detail": "ในกรณีที่จอยห้องคนอื่น ไปหน้าเข้าร่วม เเละกดปุ่มเข้าร่วมไปเเล้ว จากนั้นกดปุ่ม exit จะพาไปหน้าสร้างห้อง สิ่งที่ถูกต้อง มันควรมาหน้า ห้องเข้าร่วมเกม",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "",
"note": "",
"cat": "LobbyA"
},
{
"n": 16,
"name": "grid กับ ฉาก ไม่ตรงกัน",
"detail": "เกม Quiz battle เกมที่ 1 ฉากกับกริดไม่ตรงกัน ทำให้เดินทะลุ หรือเดินติดในจุดที่ไม่ควรติด",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "Minigame 1"
},
{
"n": 17,
"name": "ตัวละครวิ่งเร็วเกินไป",
"detail": "เกม Quiz battle เกมที่ 1 ตัวละครผู้เล่นเร็วเกินไป",
"prio": "กลาง",
"status": "เปิด",
"updated": "2026-06-25",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 18,
"name": "Oauth Social log-in error",
"detail": "ไม่สามารถ log-inด้วย facebook / Google ได้ path: /oauth-public.php",
"prio": "ต่ำ",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 19,
"name": "หน้า login",
"detail": "นโยบายความเป็นส่วนตัวกดไม่ได้",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 20,
"name": "แสดงเลข version ตรงมุมจอ",
"detail": "แสดงเลข version ตรงมุมจอขวาบนหรือขวาล่างก็ได้",
"prio": "ต่ำ",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — badge มุมขวาล่าง อ่าน ?v= อัตโนมัติ",
"cat": "อื่นๆ"
},
{
"n": 21,
"name": "ลดขนาดตัวละคร",
"detail": "ลดขนาดตัวละครในห้อง lobby ลงอีก 2เท่า",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 22,
"name": "เปลี่ยน ui popup ตอนพูดบนหัว",
"detail": "แก้ png seq บนหัวใหม่ เป็นแบบอื่น",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 23,
"name": "ชื่่อตัวละครทับลำโพง/ทับ bubble",
"detail": "ใน lobby ขยับชื่อลงมาอย่าให้ทับ",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 24,
"name": "UI แต่งตัว : การแจ้งเตือนสีตัวละครถูกใช้แล้ว",
"detail": "ตอนเลือกสีให้มีคำแจ้งเตือน used",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "LobbyA"
},
{
"n": 25,
"name": "เพิ่ม ข้อความแจ้งเตือนอัพเดทกลางจอ",
"detail": "ถ้ามีการอัพเดทซีน อัพเดทสีตัวละครให้มีป็อปอัพเด้งมากลางหน้าจอ ว่ามีการอัพเดทและให้รอโหลด",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 26,
"name": "เอาเงาตัวละครออก 1 อัน",
"detail": "ตอนนี้ตัวละครมีเงา 2 ชั้น เอาออกไป 1 ชั้น",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — ปิด default-shadow overlay เหลือเงาในสไปรต์",
"cat": "อื่นๆ"
},
{
"n": 27,
"name": "optimize ตัวละครให้เล็กลงอีก มันโหลดช้า",
"detail": "",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 28,
"name": "ปุ่ม start ใน lobby",
"detail": "ทำให้ดูโต้ตอบหน่อย เช่นพอเดินเข้าไปใกล้ให้มัน glow ขึ้นมา",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 31,
"name": "เอา mock การ์ดผู้ต้องหาเก่าออกไป",
"detail": "มันแว่บๆมา",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.006242530 (รอเทส) — ซ่อนรูปจนรูปคดีจริงโหลด + spinner",
"cat": "LobbyB"
},
{
"n": 32,
"name": "เอา popup ขออนุญาตใช้ไมค์ออกไปเลย น่ารำคาญ",
"detail": "",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 33,
"name": "หน้า howto เปลี่ยนสีปุ่ม ready ด้วยตอน กดready แล้ว",
"detail": "เปลี่ยนเป้นสีเขียวพร้อมเครื่องหมายถูกตามดีไซน์",
"prio": "สูง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "LobbyA"
},
{
"n": 34,
"name": "เกม ใช่ หรือไม่ : ตอนจบบั๊ค",
"detail": "ตอนสรุปคะแนน ยังนับเวลาอยุ่ และขึ้น gameover ทับหน้าสรุปคะแนน",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG1 ใช่/ไม่: capture mg1AnyScore ก่อนล้าง (gameover) + guard quiz-phase หลังจบ (timer)",
"cat": "Minigame 1"
},
{
"n": 35,
"name": "เกมวิ่ง : กดปุ่มไม่กระโดด",
"detail": "ปุ่ม jump กดแล้วไม่กระโดด",
"prio": "วิกฤต",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "Minigame 5"
},
{
"n": 36,
"name": "เกมวิ่ง : ตอนจบบั๊ค วิ่งเลยฉาก",
"detail": "ตอนจบบั๊ค วิ่งเลยฉาก (ในบางรอบ)",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG2 วิ่งเลยฉาก: walk-to-finish ค่อยๆเดินเข้าเส้น + clamp ไม่เลยเส้น",
"cat": "Minigame 2"
},
{
"n": 37,
"name": "popup รับหลักฐาน ทับไมค์",
"detail": "กดไมค์ไม่ได้ ตอนรับหลักฐาน ไปดูเรื่องเลเยอร์อีกที",
"prio": "กลาง",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "LobbyB"
},
{
"n": 38,
"name": "หน้าส่งหลักฐาน ปุ่มส่งหลักฐานหลุดจอ (เครื่องของเนส)",
"detail": "เป้นเครื่องเนสคนเดียว",
"prio": "วิกฤต",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "ระบบ disconnect"
},
{
"n": 39,
"name": "ห้องส่งหลักฐาน : เมื่อมีคนหลุด 1 คน จะไปต่อไม่ได้เลย",
"detail": "",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — testimony: disconnect ลบ submit/ready + client ใช้ totalPlayers authoritative",
"cat": "ระบบ disconnect"
},
{
"n": 40,
"name": "จำนวนคน ให้เล่นได้ตั้งแต่ 4-6 คน",
"detail": "กรณีเลือกผู้เล่นตั้งแต่ 4 คนขึ้นไปไม่ต้องมี bot",
"prio": "วิกฤต",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "อื่นๆ"
},
{
"n": 41,
"name": "เกม หยิบแผ่นป้าย",
"detail": "ต้องเล่นให้ครบ 10 ข้อก่อน ค่อยจบเกม (ตอนนี้เล่นถูก 1 ข้อ จบเกมเลย)",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG4 หยิบป้าย: ใช้ map จริง (currentPlayMapId) เปิด mission flow + default 10 ข้อ",
"cat": "Minigame 4"
},
{
"n": 42,
"name": "เกม กระโดด",
"detail": "ท่ากระโดดแปลก ยืนซอยเท้าทำไม",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "anim ไม่ sync: ยืนบนแท่นที่เลื่อนลง world Y เปลี่ยนทุกเฟรม → ปลายทางเดา isWalking จาก delta = เห็น ซอยเท้า ตลอด. แก้: ส่ง isWalking จริงใน move (jsWalking) + ปลายทางใช้ค่านั้น (play.js ~19162/20501/24930). v0.006260100",
"cat": "Minigame 5"
},
{
"n": 43,
"name": "เกม กระโดด",
"detail": "ขั้นบันไดมันถี่ไป บางทีกระโดดแล้วเบิ้ลขั้นเลย ปรับให้ระยะห่างแต่ละขั้นมันเท่ากัน",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "ขั้นถี่/ไม่เท่า → เบิ้ลขั้น+ติดรอแท่ง. แก้ layout mnptfts2: ระยะเท่ากันทุกขั้น (gap 3 แถว, rows 2/5/8/11/14/17, zigzag กว้าง6) ในโซนปลอดภัย (เลี่ยง hazard แถว 0/18/19). reach apex 4.5 > 3 = ถึงทุกขั้น (ไม่ติดรอ #43b) + ขั้นถัดไป-อีกขั้น 6 แถว > reach = กระโดดข้ามไม่ได้ (ไม่เบิ้ล). seam รอยต่อ wrap ห่าง 5 แถว 1 จุด/รอบ (h=20 หาร 3 ไม่ลง). restart service หลังแก้แมป | รอบ2: (ก) แก้ลายแท่นบิด — เดิม width เท่ากัน(6)ทำให้ภาพถูกบีบ → ตั้ง width = ขนาดจริงของรูป (เล็ก=var3 7ช่อง/212px, กลาง=var2 13ช่อง/389px) วาดได้สัดส่วนจริงไม่บิด. (ข) ติดบนสุด = seam รอยต่อ wrap 5แถว >ระยะกระโดด(apex4.5) → bump jumpSurviveJumpHeightMult 1.5→1.7 (apex 5.1) ให้ข้าม seam ได้ แต่ข้าม2ขั้น(6แถว)ยังไม่ได้. var1(ใหญ่ 46ช่อง)ใหญ่เกินแมป35 ใช้ไม่ได้ไม่บิด → ใช้ เล็ก/กลาง",
"cat": "Minigame 5"
},
{
"n": 44,
"name": "เกมกระโดด",
"detail": "อีเวนท์พิเศษ (ทนาย/เทพความรู้) หายไป",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG5 อีเวนต์พิเศษ: เพิ่ม branch jump_survive วาง icon บน platform",
"cat": "Minigame 5"
},
{
"n": 45,
"name": "เกมไม่รองรับ 4K",
"detail": "หน้ารับหลักฐาน (หลังจากเล่นเกมจบ)",
"prio": "วิกฤต",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "LobbyB"
},
{
"n": 46,
"name": "เกมยิิงอุกาบาด",
"detail": "สีตัวละครยังไม่ตรงกับที่เลือกมา",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG6 สี: ยาน Rocket-1..8 ตาม lobby theme ของผู้เล่น",
"cat": "Minigame 6"
},
{
"n": 47,
"name": "เกมยิิงอุกาบาด",
"detail": "อุกาบาดให้พุ่งเร็วกว่านี้ และลูกเล็กกว่านี้เกมง่ายไป",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส) — MG6: อุกาบาตเร็วขึ้น (+~50%) + เล็กลง (48->34/11->8)",
"cat": "Minigame 6"
},
{
"n": 48,
"name": "เพิ่ม popup เมื่อเกมค้าง เล่นต้่อไม่ได้ ให้มีปุ่มกดออกไปหน้าแรกสุด",
"detail": "สาเหตุเกิดจากมีคนหลุดระหว่างรอ host กด",
"prio": "วิกฤต",
"status": "เปิด",
"updated": "",
"note": "",
"cat": "ระบบ disconnect"
},
{
"n": 49,
"name": "กรณีผู้เล่นหลุดออกจากเกม",
"detail": "ถ้ามีคนหลุด ให้กลายเป้นบอทแทน",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "แก้แล้ว 2026-06-25: คนออกระหว่าง LobbyB/เปลี่ยนหน้า กลายเป็นบอทสีตามคนออก (ดูบั๊ก #73)",
"cat": "ระบบ disconnect"
},
{
"n": 50,
"name": "ผู้เล่น 6 คน: บางเกมเล่นได้แค่ 5 (คนที่ 6 หายจากสรุป)",
"detail": "สรุปคะแนนฝั่ง client slice(0,5) ตัดคนที่ 6 — แก้เป็น slice(0,6) ทุกมินิเกม (MG1/3/4/5/6/7)",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส)",
"cat": "Minigame 1"
},
{
"n": 51,
"name": "ผู้เล่น 6 คน: คะแนนตอนจบไม่ตรงกันแต่ละจอ",
"detail": "MG1 merge คะแนน server / MG6,7 merge คะแนน host -> ครบ 6 ตรงกัน (MG3 ยัง local)",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-24",
"note": "✅ แก้แล้ว 2026-06-24 v0.006242500 (รอเทส)",
"cat": "Minigame 6"
},
{
"n": 52,
"name": "หน้าไต่สวน/สรุปหลักฐาน: กรอบปลิ้นตอน 6 คน",
"detail": "member row grid repeat(5)->repeat(6) ใน testimony-overlay.css (คนที่6 ตกแถว2)",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.006242530 (รอเทส)",
"cat": "LobbyB"
},
{
"n": 53,
"name": "เพิ่มหน้าโหลด (loading) ตอนเข้าเกม",
"detail": "overlay spinner กันเห็นจอเปล่า/asset แว่บ ซ่อนเมื่อ draw เฟรมแรก + safety 8s",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.006242530 (รอเทส)",
"cat": "อื่นๆ"
},
{
"n": 54,
"name": "host โหลดนานมากตอนเข้าเกม",
"detail": "optimize asset/char (เกี่ยว row 28) — loading overlay ช่วยซ่อน แต่ยังโหลดช้าจริง",
"prio": "สูง",
"status": "เปิด",
"updated": "2026-06-25",
"note": "loading overlay บังอาการแล้ว · root = canvas tint ภาพตัวละครใหญ่ (source ไม่อยู่ใน repo) → ต้อง optimize ภาพแยก",
"cat": "อื่นๆ"
},
{
"n": 55,
"name": "หลังออกจาก LobbyA ไม่ให้ใครเข้า join",
"detail": "server มี joinLocked (set ตอน LobbyA->case ~8656, check ~7585 whitelist nickname) — ต้อง repro ว่าใครเข้าได้ยังไง (room list ยังโชว์? ชื่อซ้ำ whitelist?)",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 — กรองห้อง joinLocked ออกจาก /api/spaces list (ห้องเริ่มคดีแล้วหาย) + server reject อยู่แล้ว",
"cat": "LobbyB"
},
{
"n": 56,
"name": "ตอนกลับ LobbyB โชว์รูปแรกก่อนแล้วค่อยถูก",
"detail": "เหมือน #1 การ์ด — ต้องใส่ loading state ตอน return LobbyB ด้วย (มี room-loading-overlay อยู่แต่ซ่อนเร็วไป)",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.0308 — การ์ดมี spinner (#1) + room-loading overlay ใส่ % + รอ char preload เสร็จก่อนซ่อน + safety 12s",
"cat": "อื่นๆ"
},
{
"n": 57,
"name": "เล่นมินิเกมเกิน 3 ครั้งต่อผู้ต้องสงสัย (+การ์ดพิเศษโผล่รอบที่4)",
"detail": "server cap suspect-pick-start (max หลักฐาน>=3 reject) + award cap 3 + client canInvestigateSuspect<3 (เดิม stub return true). UI messaging มีอยู่แล้ว",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.0309/server (รอเทส)",
"cat": "LobbyB"
},
{
"n": 58,
"name": "ปุ่ม \"เล่นเกมต่อ\" ไม่รู้ว่าค้างหรือรอคนอื่น",
"detail": "text \"รอผู้เล่นอื่น (X/Y)\" ถูก set อยู่แล้วแต่ CSS font-size:0 ซ่อน → เพิ่ม .is-waiting CSS โชว์ข้อความ+spinner แทนรูปปุ่ม",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.0309/server (รอเทส)",
"cat": "อื่นๆ"
},
{
"n": 59,
"name": "loading ไม่คลุม scene transition (เห็นฉากเก่าก่อนเปลี่ยน)",
"detail": "LobbyA->B (in-page swap) โชว์ room-loading ระหว่าง fetch+swap · LobbyB->เกม โชว์ overlay ก่อน location.href · play.html มี overlay รับช่วง",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.0309/server (รอเทส)",
"cat": "LobbyA"
},
{
"n": 60,
"name": "ทำหน้า testcase บนเซิร์ฟเวอร์",
"detail": "srv1361159.hstgr.cloud/testcase — bug list + filter/search/นับสถานะ generate จาก xlsx",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.0309/server (รอเทส)",
"cat": "อื่นๆ"
},
{
"n": 62,
"name": "MG1/MG4 user/bot ติดกัน (เดินไม่ผ่าน)",
"detail": "เพิ่ม anti-stuck: ดันชนเพื่อน → เขย่า (shake) + ปลดล็อกเดินผ่านกันชั่วคราว คงกำแพง/area/quiz-lock; ทั้งผู้เล่นและบอท",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 v0.006250100 (รอเทส)",
"cat": "Minigame 4"
},
{
"n": 63,
"name": "LobbyA มือถือ กดเดินไม่ได้",
"detail": "lobby canvas มีแค่ dblclick (ไม่มี touch) → มือถือแตะเดินไม่ได้. แก้: เพิ่ม tap-to-walk (เฉพาะ touch, PC ยัง dblclick) + DPI-safe coord + touch-action:none + zoom-out default บนจอ<600px (PC ย่อส่วน)",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 room-lobby.js?v=0.0310 (รอเทสมือถือ) · PC ไม่กระทบ",
"cat": "LobbyA"
},
{
"n": 64,
"name": "มือถือ: ปุ่มแชท AI ใหญ่ไป + ปุ่ม F (host) ไม่มี",
"detail": "AI chat collapsed btn 213x201px → ใหญ่บนมือถือ. + การกด F (interact: host เลือกระดับ/คดี, ห้องแต่งตัว) ไม่มีบนมือถือ",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 (css 0.0176/js 0.0311): media<600px ย่อปุ่ม AI (92px) + ปุ่มลอย \"โต้ตอบ(F)\" บน touch-primary device (dispatch synthetic KeyF). PC ไม่เห็น",
"cat": "LobbyB"
},
{
"n": 65,
"name": "อีเวนต์พิเศษ (ทนาย/เทพ) = 1 ใน 3 (ตามดีไซน์)",
"detail": "ดีไซน์: 3 เกม/LobbyB เล่นได้เกมละ 3 ครั้ง · อีเวนต์พิเศษ 1/3 ต่อครั้ง (1 ใบ) · Test Mode บังคับ. revert การแก้ \">1 ต่อรอบ\" กลับเป็น 1 ใบ/ครั้งที่ติด",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ revert 2026-06-25 — กลับเป็น 1/3 (1 ใบ/ครั้งที่ติด) ตามดีไซน์ · ยืนยันโครงสร้าง 3เกม×3ครั้ง + disruptor toggle (>4คน/Test Mode) ถูกต้อง",
"cat": "อื่นๆ"
},
{
"n": 66,
"name": "host หลุด → ย้าย host ให้คนอยู่นานสุด",
"detail": "pickNextHostPeer เลือก spawnJoinOrder ต่ำสุด (เสถียรข้าม reconnect) แทน Map-first + host จริง reclaim ได้",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 (server) — Part 1 host migration",
"cat": "ระบบ disconnect"
},
{
"n": 67,
"name": "คนหลุดกลางเกม → 10 วิ reconnect + บอทเล่นแทน",
"detail": "peer-disconnect-grace แบนเนอร์นับ 10 วิ · กลับทัน=cancel เล่นต่อ · ครบเวลา=peer-bot-takeover host เติมบอท 1 ตัว (rebalance, cap≤6). บอทไม่สืบทอดตำแหน่ง/คะแนน",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 (server+play.js v0.006250400) — Part 2 แบบ A · seamless(host คุม entity เดิม)=ค้าง(เสี่ยง)",
"cat": "ระบบ disconnect"
},
{
"n": 69,
"name": "UI ห้องเกม (LobbyA) มือถือแนวนอน — ย่อให้พอดี",
"detail": "room-lobby ไม่มี landscape media query → chat panel(576x525), ปุ่ม voice/แว่น/ถ้วย(80px), AI chat ล้น/ใหญ่บนแนวนอน. เพิ่ม @media(landscape+max-height:540px) ย่อตามความสูงจอ (อิง Main-Lobby pattern)",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "✅ แก้แล้ว 2026-06-25 room-lobby.css?v=0.0177 — chat/BR buttons/AI/ready/exit · overlay หลักฐาน-อันดับ (inline/JS) ยังต้องทำแยก",
"cat": "LobbyB"
},
{
"n": 70,
"name": "การ์ดรางวัลหลักฐาน มือถือใหญ่เกิน กดปุ่มไม่ได้",
"detail": "หน้าโชว์การ์ดรางวัล \"คุณได้รับหลักฐาน!\" (หลังจบมินิเกมสืบสวน) บนมือถือการ์ดใหญ่มากจนเนื้อหา+ปุ่ม \"เก็บเข้าแฟ้ม\" หลุดล่างจอ กดปิดไม่ได้",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "แก้แล้ว (deploy prod play.js?v=0.006250402): ทำ overlay เป็น scroll container + inner margin:auto (กัน flexbox clip ด้านบนเวลาเนื้อหาสูงเกินจอ) + คุมขนาดการ์ด/หัวข้อ/ปุ่มด้วย clamp ตาม viewport (การ์ด max-width min(72vw,360px) + max-height 52vh, ปุ่ม font/padding clamp). มือถือแนวตั้งเลื่อนถึงปุ่มได้เสมอ. ไฟล์: Game/public/js/play.js (showInSceneEvidenceReveal).",
"cat": "ระบบ disconnect"
},
{
"n": 71,
"name": "หน้าผลชนะ (โพเดียม) ตัวละครลอย ไม่ยืนบนพื้น",
"detail": "หน้า \"ยินดีด้วย ทีมนักสืบ ชนะ!\" ตัวละครผู้ชนะลอยอยู่กลางอากาศ ไม่ยืนบนพื้นเวที",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "แก้แล้ว (deploy prod room-lobby.js?v=0.0312): พื้นหลัง win-bg เดิม center/cover ทำให้พื้นเวทีถูก crop เลื่อน + podium ตั้ง bottom:9% ตัวละครเลยลอย. แก้เป็น (1) ปักพื้นหลังไว้ขอบล่าง background-position:center bottom -> พื้นเวทีติดขอบล่างจอเสมอทุกสัดส่วน (2) ลด podium bottom 9% -> 2% ให้ตัวละครยืนบนพื้น. ไฟล์: Game/public/js/room-lobby.js (injectFinalResultStyle, #trial-final-podium).",
"cat": "อื่นๆ"
},
{
"n": 72,
"name": "ป๊อปอัปขอสิทธิ์ไมค์ เด้งทุกครั้งที่เข้า Lobby",
"detail": "หน้าขอสิทธิ์ไมโครโฟน (mic-permission-overlay) เด้งขึ้นทุกครั้งที่เข้า LobbyA/LobbyB น่ารำคาญ ทั้งที่เบราว์เซอร์จำสิทธิ์ให้แล้ว",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "แก้แล้ว (deploy prod room-lobby.js?v=0.0313): เดิม overlay เป็น display:flex default จึงเด้งทุกครั้งที่โหลดหน้า. เพิ่มตรวจสิทธิ์ผ่าน navigator.permissions.query(microphone) + จำสถานะใน localStorage (justiceMicPromptHandled). แสดงเฉพาะครั้งแรกที่ยังไม่เคยตัดสินใจ (permission=prompt และยังไม่เคยกดอนุญาต/ปิด); ถ้า granted แล้ว/เคยจัดการแล้ว → ซ่อนทันที (มี inline script กันแฟลชก่อน paint). ปุ่ม 🎤 ขอสิทธิ์ไมค์ ในห้องยังใช้ขอใหม่ได้. ไฟล์: room-lobby.html (inline gate) + room-lobby.js (gateMicPermissionOverlay, hideMicPermissionOverlay).",
"cat": "LobbyA"
},
{
"n": 73,
"name": "คนออก LobbyB / ช่วงเปลี่ยนหน้า → ไม่เติมบอท + ค้างรอผู้เล่น เริ่มเกมต่อไม่ได้",
"detail": "คนหลุดระหว่างนั่งอยู่ LobbyB หรือช่วงเปลี่ยนหน้า minigame→LobbyB เดิมไม่ถูกเติมบอทแทน + ยังถูกนับใน roster คดี → host กดเริ่มสืบสวนรอบต่อไปไม่ได้ ค้าง รอผู้เล่น (x/y) ตลอดไป",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-25",
"note": "ขยาย grace+bot-takeover gate ให้ครอบ LobbyB/คดีล็อก ไม่ใช่แค่ minigame active (server.js ~8921: inCaseFlowForBot = detectiveMinigameActive || serverMapIsPostCaseLobbyB || (joinLocked && caseParticipantNicknames.size>0)). คนออก→หลัง grace 10วิ ลบจาก roster + เติมบอทสีตามคนออก + presence ใหม่ → allHere=true เล่นต่อได้. + ส่ง botSlotCount ใน lobby-tint-sync (server.js ~121) + client อัปเดต lobbyBotSlotCount ก่อน render (room-lobby.js ~768) ให้บอทโผล่ทันทีไม่ต้อง re-join. v0.0323",
"cat": "ระบบ disconnect"
},
{
"n": 74,
"name": "แถวหน้าตัวละคร (ready ใต้ปุ่ม HOW TO) ค้างบนจอระหว่างเล่นเกม",
"detail": "หลังกด HOW TO/Ready แล้วเริ่มเกม กล่องแถว avatar คนที่กด ready (ใต้ปุ่ม) ไม่ถูกซ่อน ค้างอยู่กลางจอล่างทับฉากเกม (เห็นชัดใน MG3 stack) — กระทบ MG1/3/5/6",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "กล่องลอย #gch-ready-avatars-float ถูกซ่อนเฉพาะ MG2 (dismissGauntletCrownHowtoOverlayPlay) + MG4 (quiz_carry) เท่านั้น. begin*CountdownThenRun ของ MG1/3/5/6 (stack/jump/space/quiz) ตั้ง gauntletCrownHowtoVisible=false แต่ไม่เรียก hideReadyAvatarsFloat() → กล่องค้าง display:flex ทั้งเกม (ไม่มี driver เรียกใหม่ตอน live). แก้: เพิ่ม hideReadyAvatarsFloat() ในทั้ง 4 ฟังก์ชันเริ่มเกม (play.js). v0.006260101",
"cat": "อื่นๆ"
},
{
"name": "block สีไม่ตรงในฝั่ง client",
"detail": "",
"prio": "กลาง",
"status": "เปิด",
"note": "",
"cat": "Minigame 3",
"updated": "2026-06-26",
"n": 75
},
{
"name": "บางที client บางคนเล่นไม่ได้",
"detail": "",
"prio": "กลาง",
"status": "เปิด",
"note": "",
"cat": "Minigame 3",
"updated": "2026-06-26",
"n": 76
},
{
"name": "เปลี่ยนปุมลำโพง",
"detail": "",
"prio": "กลาง",
"status": "เปิด",
"note": "",
"cat": "LobbyA",
"updated": "2026-06-26",
"n": 77
},
{
"n": 78,
"name": "Lobby: คน/บอท วิ่งเร็วเท่ากันทุกเครื่อง",
"detail": "เดิมจอ FPS สูงเดินเร็วกว่า — แก้เป็น time-based ความเร็วเท่ากันทุกเครื่อง",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: เปิด 2 เครื่อง/2 แท็บ เข้า LobbyA ห้องเดียวกัน เดินพร้อมกัน → ความเร็วต้องเท่ากัน และดูบอทเดินสม่ำเสมอ",
"cat": "LobbyA"
},
{
"n": 79,
"name": "Lobby: บอทเดินเองโดย server (host หลุดไม่หยุด)",
"detail": "ย้ายการเดินบอท lobby จาก host → server",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: LobbyA มีบอท → ให้ host (คนสร้างห้อง) รีเฟรช/ออก → บอทต้องเดินต่อ ไม่หยุดนิ่ง",
"cat": "LobbyA"
},
{
"n": 80,
"name": "Lobby: ผีหาย (avatar ไม่ซ้ำ)",
"detail": "server ส่ง roster ทุก 1.5s → client ตัดตัวซ้ำ",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: เข้า LobbyA/B แล้วรีเฟรช/เข้า-ออกซ้ำ 2-3 รอบ → ต้องไม่มีตัวละครซ้ำค้าง (รอ ~2วิ ผีหายเอง)",
"cat": "LobbyA"
},
{
"n": 81,
"name": "Lobby: บอทเกิดในห้อง ตำแหน่งเดียวกับคน",
"detail": "เดิมบอทเกิดนอกพื้นที่/ซ้อนกัน — แก้ให้เกิดที่ช่อง spawn ผู้เล่น",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: เข้า LobbyA ที่มีบอท → บอทต้องเกิดในห้อง (ไม่หลุดออกนอก area) แต่ละตัวคนละช่อง",
"cat": "LobbyA"
},
{
"n": 82,
"name": "MG1: หน้า How-to ใหม่ (SAFE/SCAM)",
"detail": "เปลี่ยน how-to เป็น \"วิเคราะห์ภัยร้าย\" (เดิมเป็นดีไซน์ MG4)",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: เข้า MG1 → หน้า HOW TO PLAY ต้องเป็น \"วิเคราะห์ภัยร้าย ปกป้องระบบให้ปลอดภัย\" มี SAFE/SCAM + การ์ด COMMON/RARE/LEGENDARY",
"cat": "Minigame 1"
},
{
"n": 83,
"name": "MG1: ปุ่ม READY 2 สถานะ",
"detail": "ยังไม่กด=ฟ้า / กดแล้ว=เขียว+เครื่องหมายถูก",
"prio": "ต่ำ",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: หน้า ready MG1 → ปุ่มฟ้า · กด → เขียวมี ✓ · กดอีกที → กลับฟ้า",
"cat": "Minigame 1"
},
{
"n": 84,
"name": "MG1: auto-start เมื่อทุกคน ready",
"detail": "ครบ ready → server เริ่มเอง ไม่ต้องรอ host กด START",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: ทุกคนกด READY ครบ → เกมเริ่มเอง (นับ 3-2-1) ไม่ต้องมีใครกด START · ลองให้ host ออกก่อนคนสุดท้าย ready → ยังเริ่มได้",
"cat": "Minigame 1"
},
{
"n": 85,
"name": "MG1: คน/บอท วิ่งเร็วเท่ากัน",
"detail": "movement time-based",
"prio": "กลาง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: 2 เครื่องเล่น MG1 พร้อมกัน → คนวิ่งเร็วเท่ากัน · บอทวิ่งเข้าโซน SAFE/SCAM สม่ำเสมอ",
"cat": "Minigame 1"
},
{
"n": 86,
"name": "MG1: ผีหาย (avatar ไม่ซ้ำ)",
"detail": "server ส่ง play-roster ทุก 1.5s ตัดตัวซ้ำระหว่างเล่น",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: เล่น MG1 แล้วมีคนหลุด/reconnect → ต้องไม่มีตัวซ้ำขยับไม่ได้ค้างในสนาม",
"cat": "Minigame 1"
},
{
"n": 87,
"name": "MG1: บอทเดินต่อแม้ host หลุด",
"detail": "server เป็นเจ้าของการเดินบอท quiz",
"prio": "วิกฤต",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: เล่น MG1 กับบอท · host รีเฟรช/ออกกลางเกม → บอทต้องเดิน+วิ่งเข้าโซนต่อ ไม่หยุดนิ่ง",
"cat": "Minigame 1"
},
{
"n": 88,
"name": "MG1: คะแนนบอทตรงกันทุกจอ",
"detail": "server คิดคะแนนบอท (เดิม host คิดเอง ไม่ sync)",
"prio": "สูง",
"status": "แก้ไขแล้ว",
"updated": "2026-06-26",
"note": "วิธีเทส: 2 เครื่องเล่น MG1 กับบอท → คะแนนบอทบนกระดานต้องตรงกันทั้ง 2 จอทุกข้อ",
"cat": "Minigame 1"
}
]