diff --git a/www/html/Create Room/create-room.js b/www/html/Create Room/create-room.js
index 30d7927..37d1e58 100644
--- a/www/html/Create Room/create-room.js
+++ b/www/html/Create Room/create-room.js
@@ -54,6 +54,7 @@
function botCountForSlot(n) {
var humans = Math.min(LOBBY_TOTAL_SLOTS, Math.max(1, parseInt(n, 10) || 1));
+ if (humans >= 4) return 0; /* เลือก ≥ 4 คน → ไม่มีบอท (รอคนจริง) — ต้องตรงกับ server effectiveBotSlotCount */
return Math.max(0, LOBBY_TOTAL_SLOTS - humans);
}
diff --git a/www/html/Create Room/create-room.js.bak-no4bot b/www/html/Create Room/create-room.js.bak-no4bot
new file mode 100644
index 0000000..30d7927
--- /dev/null
+++ b/www/html/Create Room/create-room.js.bak-no4bot
@@ -0,0 +1,255 @@
+(function () {
+ 'use strict';
+
+ if (typeof ensureLocalDevLogin === 'function') ensureLocalDevLogin();
+
+ function checkLoginStatus() {
+ var isLoggedIn = localStorage.getItem('isLoggedIn');
+ if (!isLoggedIn || isLoggedIn !== 'true') {
+ window.location.href = typeof appPath === 'function' ? appPath('/Login/') : '/Login/';
+ return false;
+ }
+ return true;
+ }
+
+ if (!checkLoginStatus()) return;
+
+ var BASE = typeof appPath === 'function' ? appPath('/Game') : '/Game';
+
+ var PROD_GAME_API = 'https://srv1361159.hstgr.cloud/Game';
+
+ function resolveCreateRoomApiBase() {
+ if (typeof resolveGameApiBase === 'function') {
+ return resolveGameApiBase().replace(/\/$/, '');
+ }
+ if (typeof window.__JD_GAME_API_BASE__ === 'string' && window.__JD_GAME_API_BASE__) {
+ return window.__JD_GAME_API_BASE__.replace(/\/$/, '');
+ }
+ var pageGame = BASE.replace(/\/$/, '');
+ try {
+ var h = (location.hostname || '').toLowerCase();
+ if (h === 'localhost' || h === '127.0.0.1') {
+ try {
+ if (localStorage.getItem('jdUseLocalGameApi') === '1') {
+ var port = localStorage.getItem('jdGameNodePort') || '13010';
+ return 'http://127.0.0.1:' + String(port).replace(/\D/g, '') + '/Game';
+ }
+ } catch (e) { /* ignore */ }
+ return PROD_GAME_API;
+ }
+ } catch (e2) { /* ignore */ }
+ return pageGame;
+ }
+
+ var SERVER = resolveCreateRoomApiBase();
+ var LOBBY_A_MAP_ID = 'mlsbbxfe';
+ var LOBBY_TOTAL_SLOTS = 6;
+
+ var selectedSlot = 3;
+ var isPrivate = false;
+
+ function getNick() {
+ return (localStorage.getItem('playerName') || '').trim() || 'ผู้เล่น';
+ }
+
+ function botCountForSlot(n) {
+ var humans = Math.min(LOBBY_TOTAL_SLOTS, Math.max(1, parseInt(n, 10) || 1));
+ return Math.max(0, LOBBY_TOTAL_SLOTS - humans);
+ }
+
+ function maxPlayersForSlot(n) {
+ var humans = Math.min(LOBBY_TOTAL_SLOTS, Math.max(1, parseInt(n, 10) || 3));
+ return Math.min(10, Math.max(1, humans));
+ }
+
+ var btnBack = document.getElementById('btn-back');
+ var tabPublic = document.getElementById('tab-public');
+ var tabPrivate = document.getElementById('tab-private');
+ var privateBlock = document.getElementById('create-private-block');
+ var inputRoomName = document.getElementById('create-room-name');
+ var inputPrivatePin = document.getElementById('create-private-pin');
+ var playerBtnsWrap = document.getElementById('create-player-btns');
+ var btnConfirm = document.getElementById('btn-confirm');
+ var statusEl = document.getElementById('create-status');
+ var summaryEl = document.getElementById('create-summary');
+
+ function updateSummary() {
+ if (!summaryEl) return;
+ var bots = botCountForSlot(selectedSlot);
+ summaryEl.textContent = 'สรุปจำนวน : ' + selectedSlot + ' ผู้เล่น + ' + bots + ' Bot';
+ }
+
+ btnBack?.addEventListener('click', function () {
+ window.location.href = typeof appPath === 'function' ? appPath('/Main-Menu/') : '/Main-Menu/';
+ });
+
+ inputPrivatePin?.addEventListener('input', function (e) {
+ e.target.value = e.target.value.replace(/[^0-9]/g, '').slice(0, 4);
+ updateConfirmButtonEnabled();
+ });
+
+ function updateModeImages() {
+ [tabPublic, tabPrivate].forEach(function (btn) {
+ if (!btn) return;
+ var img = btn.querySelector('.create-mode-btn-img');
+ if (!img) return;
+ var isActive = btn.classList.contains('create-mode-btn--active');
+ img.src = isActive ? btn.getAttribute('data-img-h') : btn.getAttribute('data-img');
+ });
+ }
+
+ function setTab(privateMode) {
+ isPrivate = privateMode;
+ tabPublic?.classList.toggle('create-mode-btn--active', !privateMode);
+ tabPrivate?.classList.toggle('create-mode-btn--active', privateMode);
+ tabPublic?.setAttribute('aria-selected', privateMode ? 'false' : 'true');
+ tabPrivate?.setAttribute('aria-selected', privateMode ? 'true' : 'false');
+ if (privateBlock) privateBlock.classList.toggle('create-view--hidden', !privateMode);
+ updateModeImages();
+ updateConfirmButtonEnabled();
+ }
+
+ tabPublic?.addEventListener('click', function () { setTab(false); });
+ tabPrivate?.addEventListener('click', function () { setTab(true); });
+
+ function updatePlayerImages() {
+ if (!playerBtnsWrap) return;
+ var buttons = playerBtnsWrap.querySelectorAll('.create-num-btn');
+ buttons.forEach(function (btn) {
+ var v = parseInt(btn.getAttribute('data-slot'), 10);
+ var on = v === selectedSlot;
+ var img = btn.querySelector('.create-num-btn-img');
+ if (img) {
+ img.src = on ? btn.getAttribute('data-img-h') : btn.getAttribute('data-img');
+ }
+ btn.setAttribute('aria-pressed', on ? 'true' : 'false');
+ });
+ }
+
+ function selectSlot(n) {
+ selectedSlot = Math.min(6, Math.max(1, parseInt(n, 10) || 3));
+ updatePlayerImages();
+ updateSummary();
+ }
+
+ function buildPlayerButtons() {
+ if (!playerBtnsWrap) return;
+ playerBtnsWrap.innerHTML = '';
+ for (var i = 1; i <= 6; i++) {
+ var b = document.createElement('button');
+ b.type = 'button';
+ b.className = 'create-num-btn';
+ b.setAttribute('data-slot', String(i));
+ b.setAttribute('data-img', 'IMAGE/player-' + i + '.png');
+ b.setAttribute('data-img-h', 'IMAGE/player-' + i + '-h.png');
+ b.setAttribute('aria-label', 'เลือก ' + i + ' ผู้เล่น รวม ' + LOBBY_TOTAL_SLOTS + ' ที่นั่ง (Bot ' + botCountForSlot(i) + ' ตัว)');
+ b.setAttribute('aria-pressed', i === selectedSlot ? 'true' : 'false');
+
+ var img = document.createElement('img');
+ img.className = 'create-num-btn-img';
+ img.alt = String(i);
+ img.decoding = 'async';
+ img.src = i === selectedSlot ? 'IMAGE/player-' + i + '-h.png' : 'IMAGE/player-' + i + '.png';
+ b.appendChild(img);
+
+ b.addEventListener('click', function () {
+ selectSlot(this.getAttribute('data-slot'));
+ });
+ playerBtnsWrap.appendChild(b);
+ }
+ updateSummary();
+ }
+
+ function getRoomName() {
+ return (inputRoomName && inputRoomName.value || '').trim();
+ }
+
+ function getPrivatePinDigits() {
+ if (!inputPrivatePin) return '';
+ return String(inputPrivatePin.value || '').replace(/\D/g, '').slice(0, 4);
+ }
+
+ function isPrivatePinComplete() {
+ return /^\d{4}$/.test(getPrivatePinDigits());
+ }
+
+ function updateConfirmButtonEnabled() {
+ if (!btnConfirm) return;
+ if (btnConfirm.getAttribute('data-create-loading') === '1') return;
+ btnConfirm.disabled = isPrivate && !isPrivatePinComplete();
+ }
+
+ btnConfirm?.addEventListener('click', function () {
+ if (statusEl) statusEl.textContent = '';
+ var mapId = LOBBY_A_MAP_ID;
+ var name = getRoomName();
+ if (!name) {
+ if (statusEl) statusEl.textContent = 'กรุณาใส่ชื่อห้อง';
+ return;
+ }
+ if (isPrivate && !isPrivatePinComplete()) {
+ if (statusEl) statusEl.textContent = 'กรุณาใส่รหัสผ่าน 4 หลัก (ตัวเลข) สำหรับห้องส่วนตัว';
+ inputPrivatePin?.focus();
+ return;
+ }
+ btnConfirm.setAttribute('data-create-loading', '1');
+ btnConfirm.disabled = true;
+ var body = {
+ mapId: mapId,
+ name: name,
+ isPrivate: isPrivate,
+ maxPlayers: maxPlayersForSlot(selectedSlot),
+ password: isPrivate ? getPrivatePinDigits() : '',
+ };
+ fetch(SERVER + '/api/spaces', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(body),
+ })
+ .then(function (r) { return r.json().then(function (j) { return { ok: r.ok, j: j }; }); })
+ .then(function (res) {
+ if (!res.j || !res.j.ok) {
+ if (statusEl) statusEl.textContent = (res.j && res.j.error) || 'สร้างห้องไม่สำเร็จ';
+ btnConfirm.removeAttribute('data-create-loading');
+ updateConfirmButtonEnabled();
+ return;
+ }
+ var sid = res.j.spaceId;
+ if (!sid) {
+ if (statusEl) statusEl.textContent = 'ไม่ได้รับรหัสห้อง';
+ btnConfirm.removeAttribute('data-create-loading');
+ updateConfirmButtonEnabled();
+ return;
+ }
+ if (isPrivate) {
+ try { localStorage.setItem('roomPinHint_' + sid, getPrivatePinDigits()); } catch (e) {}
+ }
+ try {
+ localStorage.setItem('lastCreatedSpaceId', sid);
+ localStorage.setItem('lastCreatedSpaceName', name);
+ } catch (e) {}
+ var lobbyUrl = BASE + '/room-lobby.html?space=' + encodeURIComponent(sid) + '&nick=' + encodeURIComponent(getNick());
+ lobbyUrl += '&displayRoom=' + encodeURIComponent(name);
+ if (isPrivate) lobbyUrl += '&pass=' + encodeURIComponent(getPrivatePinDigits()); /* host เข้าห้องตัวเองผ่านด่านรหัส */
+ try {
+ var caseId = localStorage.getItem('caseId');
+ var prevSpaceName = localStorage.getItem('prevSpaceName');
+ if (caseId) lobbyUrl += '&caseId=' + encodeURIComponent(caseId);
+ if (prevSpaceName) lobbyUrl += '&prevSpaceName=' + encodeURIComponent(prevSpaceName);
+ } catch (e) {}
+ window.location.replace((typeof appPath === 'function' ? appPath('/Loading/') : '/Loading/') + '?redirect=' + encodeURIComponent(lobbyUrl));
+ })
+ .catch(function () {
+ if (statusEl) statusEl.textContent = 'เชื่อมต่อเซิร์ฟเวอร์ไม่ได้';
+ btnConfirm.removeAttribute('data-create-loading');
+ updateConfirmButtonEnabled();
+ });
+ });
+
+ inputRoomName?.addEventListener('input', function () {
+ updateConfirmButtonEnabled();
+ });
+
+ buildPlayerButtons();
+ setTab(false);
+})();
diff --git a/www/html/Create Room/index.html b/www/html/Create Room/index.html
index 4b929fe..2d09baa 100644
--- a/www/html/Create Room/index.html
+++ b/www/html/Create Room/index.html
@@ -87,7 +87,7 @@
-
+
+
+
+