diff --git a/www/html/Game/public/editor.html b/www/html/Game/public/editor.html
index 7f34f82..7020074 100644
--- a/www/html/Game/public/editor.html
+++ b/www/html/Game/public/editor.html
@@ -146,7 +146,7 @@
-
+
diff --git a/www/html/Game/public/js/play.js b/www/html/Game/public/js/play.js
index bee2acb..712d953 100644
--- a/www/html/Game/public/js/play.js
+++ b/www/html/Game/public/js/play.js
@@ -6,6 +6,21 @@
const previewMode = params.get('preview') === '1';
const forceDefaultCharacter = params.get('defaultChar') === '1';
const editorEmbedReturn = params.get('editorEmbed') === '1';
+ /** จนกว่าโหลด /api/characters — placeholder ชั่วคราวก่อน join */
+ const LEGACY_PLACEHOLDER_CHARACTER_ID = 'Chatest';
+ let firstCharacterDefaultResolved = null;
+ const firstCharacterDefaultPromise = fetch(BASE + '/api/characters')
+ .then((r) => r.json())
+ .then((list) => {
+ if (Array.isArray(list) && list.length > 0 && list[0] && list[0].id) {
+ firstCharacterDefaultResolved = String(list[0].id);
+ } else {
+ firstCharacterDefaultResolved = '';
+ }
+ })
+ .catch(() => {
+ firstCharacterDefaultResolved = '';
+ });
const lobbyLevelParam = params.get('lobbyLevel');
const lobbyCaseParam = params.get('case');
if (lobbyLevelParam || lobbyCaseParam) {
@@ -443,12 +458,19 @@
if (img) return img;
return defaultAvatarImg;
}
- const DEFAULT_CHARACTER_ID = 'Chatest';
function getStoredCharacterId() {
- try { return localStorage.getItem('gameCharacterId') || DEFAULT_CHARACTER_ID; } catch (e) { return DEFAULT_CHARACTER_ID; }
+ try {
+ const v = localStorage.getItem('gameCharacterId');
+ if (v) return v;
+ } catch (e) { /* ignore */ }
+ if (firstCharacterDefaultResolved === null) return LEGACY_PLACEHOLDER_CHARACTER_ID;
+ return firstCharacterDefaultResolved || '';
}
function getPlayCharacterId() {
- if (forceDefaultCharacter) return DEFAULT_CHARACTER_ID;
+ if (forceDefaultCharacter) {
+ if (firstCharacterDefaultResolved === null) return LEGACY_PLACEHOLDER_CHARACTER_ID;
+ return firstCharacterDefaultResolved || '';
+ }
return getStoredCharacterId();
}
const MOVE_SPEED = 0.15;
@@ -4973,43 +4995,45 @@
}
socket.on('connect', () => {
- socket.emit('join-space', { spaceId, nickname: nick, characterId: getPlayCharacterId() }, (res) => {
- if (!res || !res.ok) {
- const errMsg = (res && res.error) || 'เข้าร่วมไม่ได้';
- alert(errMsg);
- const caseLocked = /เริ่มคดี|ไม่รับผู้เล่น/.test(errMsg);
- if (caseLocked) {
- window.location.replace('room-lobby.html?space=' + encodeURIComponent(spaceId) + '&nick=' + encodeURIComponent(nick));
- } else {
- window.location.replace(BASE + '/lobby.html');
+ firstCharacterDefaultPromise.then(() => {
+ socket.emit('join-space', { spaceId, nickname: nick, characterId: getPlayCharacterId() }, (res) => {
+ if (!res || !res.ok) {
+ const errMsg = (res && res.error) || 'เข้าร่วมไม่ได้';
+ alert(errMsg);
+ const caseLocked = /เริ่มคดี|ไม่รับผู้เล่น/.test(errMsg);
+ if (caseLocked) {
+ window.location.replace('room-lobby.html?space=' + encodeURIComponent(spaceId) + '&nick=' + encodeURIComponent(nick));
+ } else {
+ window.location.replace(BASE + '/lobby.html');
+ }
+ return;
}
- return;
- }
- myId = socket.id;
- if (previewMode && editorEmbedReturn && res.mapData && res.mapData.gameType === 'lobby') {
- const q = [];
- q.push('space=' + encodeURIComponent(spaceId));
- q.push('nick=' + encodeURIComponent(nick));
- const mid = params.get('map');
- if (mid) q.push('map=' + encodeURIComponent(mid));
- q.push('preview=1');
- q.push('editorEmbed=1');
- if (params.get('defaultChar') != null) q.push('defaultChar=' + encodeURIComponent(params.get('defaultChar')));
- window.location.replace(BASE + '/room-lobby.html?' + q.join('&'));
- return;
- }
- const playMapId = params.get('map');
- if (playMapId) {
- fetch(BASE + '/api/maps/' + encodeURIComponent(playMapId))
- .then(r => r.ok ? r.json() : null)
- .then(data => {
- if (data) applyMapAndStart(data, res);
- else applyMapAndStart(res.mapData, res);
- })
- .catch(() => applyMapAndStart(res.mapData, res));
- } else {
- applyMapAndStart(res.mapData, res);
- }
+ myId = socket.id;
+ if (previewMode && editorEmbedReturn && res.mapData && res.mapData.gameType === 'lobby') {
+ const q = [];
+ q.push('space=' + encodeURIComponent(spaceId));
+ q.push('nick=' + encodeURIComponent(nick));
+ const mid = params.get('map');
+ if (mid) q.push('map=' + encodeURIComponent(mid));
+ q.push('preview=1');
+ q.push('editorEmbed=1');
+ if (params.get('defaultChar') != null) q.push('defaultChar=' + encodeURIComponent(params.get('defaultChar')));
+ window.location.replace(BASE + '/room-lobby.html?' + q.join('&'));
+ return;
+ }
+ const playMapId = params.get('map');
+ if (playMapId) {
+ fetch(BASE + '/api/maps/' + encodeURIComponent(playMapId))
+ .then(r => r.ok ? r.json() : null)
+ .then(data => {
+ if (data) applyMapAndStart(data, res);
+ else applyMapAndStart(res.mapData, res);
+ })
+ .catch(() => applyMapAndStart(res.mapData, res));
+ } else {
+ applyMapAndStart(res.mapData, res);
+ }
+ });
});
});
@@ -6418,9 +6442,13 @@
const av = document.createElement('img');
av.className = 'play-cyber-score-av';
av.alt = '';
- const cid = row.characterId || DEFAULT_CHARACTER_ID;
- const im = getCharacterImg(cid, 'down');
- if (im && im.src) av.src = im.src;
+ const cid = row.characterId ? String(row.characterId) : '';
+ if (!cid) {
+ av.src = defaultAvatarImg.src;
+ } else {
+ const im = getCharacterImg(cid, 'down');
+ if (im && im.src) av.src = im.src;
+ }
const mid = document.createElement('div');
mid.className = 'play-cyber-score-mid';
const name = document.createElement('span');
diff --git a/www/html/Game/public/js/room-lobby.js b/www/html/Game/public/js/room-lobby.js
index 1f8cf40..b1d3146 100644
--- a/www/html/Game/public/js/room-lobby.js
+++ b/www/html/Game/public/js/room-lobby.js
@@ -7,6 +7,21 @@
const previewMode = params.get('preview') === '1';
const editorEmbedReturn = params.get('editorEmbed') === '1';
const forceDefaultCharacter = params.get('defaultChar') === '1';
+ /** จนกว่าโหลด /api/characters — ใช้ชั่วคราวก่อน join (หลังโหลดใช้ตัวแรกตามเวลาไฟล์บนเซิร์ฟเวอร์) */
+ const LEGACY_PLACEHOLDER_CHARACTER_ID = 'Chatest';
+ let firstCharacterDefaultResolved = null;
+ const firstCharacterDefaultPromise = fetch(BASE + '/api/characters')
+ .then((r) => r.json())
+ .then((list) => {
+ if (Array.isArray(list) && list.length > 0 && list[0] && list[0].id) {
+ firstCharacterDefaultResolved = String(list[0].id);
+ } else {
+ firstCharacterDefaultResolved = '';
+ }
+ })
+ .catch(() => {
+ firstCharacterDefaultResolved = '';
+ });
if (!spaceId) { location.href = BASE + '/lobby.html'; return; }
const CREATE_ROOM_URL = '/Create%20Room/';
@@ -1147,10 +1162,17 @@
if (quizModeActive) renderQuizScoreboard(lastQuizScores);
}
- const DEFAULT_CHARACTER_ID = 'Chatest';
function getStoredCharacterId() {
- if (forceDefaultCharacter) return DEFAULT_CHARACTER_ID;
- try { return localStorage.getItem('gameCharacterId') || DEFAULT_CHARACTER_ID; } catch (e) { return DEFAULT_CHARACTER_ID; }
+ if (forceDefaultCharacter) {
+ if (firstCharacterDefaultResolved === null) return LEGACY_PLACEHOLDER_CHARACTER_ID;
+ return firstCharacterDefaultResolved || '';
+ }
+ try {
+ const v = localStorage.getItem('gameCharacterId');
+ if (v) return v;
+ } catch (e) { /* ignore */ }
+ if (firstCharacterDefaultResolved === null) return LEGACY_PLACEHOLDER_CHARACTER_ID;
+ return firstCharacterDefaultResolved || '';
}
function updatePreviewClaimHostUi() {
@@ -1168,7 +1190,11 @@
const img = document.getElementById('room-lobby-profile-avatar');
if (!img) return;
const id = getStoredCharacterId();
- img.src = BASE + '/img/characters/' + encodeURIComponent(id) + '_down.png?ch=' + encodeURIComponent(id);
+ if (!id) {
+ img.src = defaultAvatarImg.src;
+ } else {
+ img.src = BASE + '/img/characters/' + encodeURIComponent(id) + '_down.png?ch=' + encodeURIComponent(id);
+ }
img.alt = (nick || 'ผู้เล่น') + ' — ตัวละคร';
}
@@ -1178,7 +1204,8 @@
}
socket.on('connect', () => {
- socket.emit('join-space', { spaceId, nickname: nick, characterId: getStoredCharacterId() }, (res) => {
+ firstCharacterDefaultPromise.then(() => {
+ socket.emit('join-space', { spaceId, nickname: nick, characterId: getStoredCharacterId() }, (res) => {
if (!res || !res.ok) {
var joinErr = (res && res.error) || 'เข้าไม่ได้';
if (/เริ่มคดี|ไม่รับผู้เล่น/.test(joinErr)) {
@@ -1269,6 +1296,7 @@
}).catch(() => {});
}, 600);
});
+ });
});
const LERP = 0.2;
diff --git a/www/html/Game/public/play.html b/www/html/Game/public/play.html
index 20a8314..483ae63 100644
--- a/www/html/Game/public/play.html
+++ b/www/html/Game/public/play.html
@@ -669,7 +669,7 @@
-
+
v —