' +
+ '
' +
+ '
ซิงก์โปรไฟล์ข้ามเครื่อง
' +
+ '
ใช้รหัสนี้เพื่อดึงสี / COINS / ชื่อ ไปยังเครื่องหรือ browser อื่น
' +
+ '
รหัสผู้เล่นของฉัน
' +
+ '
····-····
' +
+ '
รหัสจะหมดอายุถ้าไม่ได้ใช้เกิน 30 วัน
' +
+ '
' +
+ '
มีรหัสจากเครื่องอื่น? กรอกที่นี่
' +
+ '
' +
+ '
การดึงข้อมูลจะแทนที่โปรไฟล์ในเครื่องนี้ (สี/COINS/ชื่อ)
' +
+ '
' +
+ '
';
+ document.body.appendChild(ov);
+
+ linkRefs.overlay = ov;
+ linkRefs.codeEl = document.getElementById('jd-link-code');
+ linkRefs.input = document.getElementById('jd-link-input');
+ linkRefs.msgEl = document.getElementById('jd-link-msg');
+
+ document.getElementById('jd-link-backdrop').addEventListener('click', closeLinkModal);
+ document.getElementById('jd-link-close').addEventListener('click', closeLinkModal);
+ document.getElementById('jd-link-copy').addEventListener('click', copyMyCode);
+ document.getElementById('jd-link-go').addEventListener('click', redeemEnteredCode);
+ linkRefs.input.addEventListener('keydown', function (e) { if (e.key === 'Enter') { e.preventDefault(); redeemEnteredCode(); } });
+
+ // ปุ่มเปิด — ฝังในกล่องโปรไฟล์ (absolute, ไม่กระทบ layout เดิม)
+ if (refs.dialog && !document.getElementById('jd-link-trigger')) {
+ var btn = document.createElement('button');
+ btn.type = 'button';
+ btn.id = 'jd-link-trigger';
+ btn.className = 'jd-link-trigger';
+ btn.textContent = '🔗 ซิงก์เครื่อง';
+ btn.addEventListener('click', openLinkModal);
+ refs.dialog.appendChild(btn);
+ }
+ }
+
+ function setLinkMsg(text, kind) {
+ if (!linkRefs.msgEl) return;
+ linkRefs.msgEl.textContent = text || '';
+ linkRefs.msgEl.className = 'jd-link-msg' + (kind ? ' is-' + kind : '');
+ }
+
+ function openLinkModal() {
+ if (!linkRefs.overlay) return;
+ setLinkMsg('', '');
+ if (linkRefs.input) linkRefs.input.value = '';
+ if (linkRefs.codeEl) linkRefs.codeEl.textContent = '····-····';
+ linkRefs.overlay.classList.remove('is-hidden');
+ linkRefs.overlay.setAttribute('aria-hidden', 'false');
+ fetchMyCode();
+ }
+
+ function closeLinkModal() {
+ if (!linkRefs.overlay) return;
+ linkRefs.overlay.classList.add('is-hidden');
+ linkRefs.overlay.setAttribute('aria-hidden', 'true');
+ }
+
+ function fetchMyCode() {
+ var key = ensurePlayerKey();
+ var url = linkApiUrl() + '?action=code&playerKey=' + encodeURIComponent(key) +
+ '&displayName=' + encodeURIComponent(readName()) +
+ '&agentId=' + encodeURIComponent(readAgentIdRaw());
+ fetch(url, { credentials: 'omit', cache: 'no-store' })
+ .then(function (r) { return r.json(); })
+ .then(function (d) {
+ if (d && d.ok && d.codeDisplay && linkRefs.codeEl) linkRefs.codeEl.textContent = d.codeDisplay;
+ else setLinkMsg('โหลดรหัสไม่สำเร็จ ลองใหม่อีกครั้ง', 'err');
+ })
+ .catch(function () { setLinkMsg('ออฟไลน์ — โหลดรหัสไม่ได้', 'err'); });
+ }
+
+ function copyMyCode() {
+ var txt = linkRefs.codeEl ? linkRefs.codeEl.textContent : '';
+ if (!txt || txt.indexOf('·') >= 0) return;
+ function done() { setLinkMsg('คัดลอกรหัสแล้ว', 'ok'); }
+ try {
+ if (navigator.clipboard && navigator.clipboard.writeText) {
+ navigator.clipboard.writeText(txt).then(done, function () { done(); });
+ return;
+ }
+ } catch (e) { /* ignore */ }
+ done();
+ }
+
+ function redeemEnteredCode() {
+ var raw = (linkRefs.input && linkRefs.input.value || '').toUpperCase().replace(/[^A-Z0-9]/g, '');
+ if (raw.length !== 8) { setLinkMsg('กรุณากรอกรหัส 8 ตัว', 'err'); return; }
+ setLinkMsg('กำลังดึงข้อมูล…', '');
+ fetch(linkApiUrl(), {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ credentials: 'omit',
+ body: JSON.stringify({ action: 'redeem', code: raw })
+ })
+ .then(function (r) { return r.json().then(function (j) { return { status: r.status, j: j }; }); })
+ .then(function (res) {
+ var d = res.j || {};
+ if (!d.ok || !d.playerKey) {
+ setLinkMsg(d.error || 'ไม่พบรหัสนี้', 'err');
+ return;
+ }
+ applyRedeemedProfile(d);
+ })
+ .catch(function () { setLinkMsg('ออฟไลน์ — ดึงข้อมูลไม่ได้', 'err'); });
+ }
+
+ function applyRedeemedProfile(p) {
+ try {
+ localStorage.setItem('jdPlayerKey', String(p.playerKey));
+ if (p.displayName) { localStorage.setItem(DISPLAY_NAME_KEY, p.displayName); localStorage.setItem('playerName', p.displayName); }
+ if (p.agentId) localStorage.setItem('agentDisplayId', String(p.agentId));
+ if (p.colorThemeIndex) localStorage.setItem('lobbyThemeColor', String(p.colorThemeIndex));
+ if (p.skinToneIndex) localStorage.setItem('lobbySkinTone', String(p.skinToneIndex));
+ if (p.coins != null) localStorage.setItem('jdCoins', String(p.coins));
+ // ลบ avatar ที่ bake สีไว้ของเครื่องนี้ — บังคับ recompute จากสีที่ดึงมา
+ Object.keys(localStorage).forEach(function (k) {
+ if (k.indexOf('jdCharLobbyIdleDown:') === 0) localStorage.removeItem(k);
+ });
+ } catch (e) { /* ignore */ }
+ setLinkMsg('สำเร็จ! กำลังโหลดโปรไฟล์ใหม่…', 'ok');
+ setTimeout(function () { window.location.reload(); }, 500);
+ }
+
function isRoomLobbyPage() {
return /room-lobby\.html$/i.test(String(window.location.pathname || ''));
}
@@ -297,6 +478,7 @@
createMarkupIfNeeded();
bindRefs();
bindEvents();
+ buildLinkUi();
syncProfileScale();
setGroup(1);
if (window.jdAchievements) window.jdAchievements.load();
diff --git a/www/html/Game/public/js/room-lobby.js b/www/html/Game/public/js/room-lobby.js
index 9d57d7b..55f2cf3 100644
--- a/www/html/Game/public/js/room-lobby.js
+++ b/www/html/Game/public/js/room-lobby.js
@@ -362,18 +362,9 @@
var fromHex = rlHexToRgbCss(hexArr[hi]);
if (fromHex) { rlSwatchCache[key] = fromHex; cb(fromHex); return; }
}
- rlLoadImg(RL_CUSTOMIZE_ASSET + (group === 'color' ? 'color-' : 'skin-tone-') + idx + '.png', function (img) {
- if (!img || !img.naturalWidth) { cb(null); return; }
- try {
- var c = document.createElement('canvas'); c.width = 1; c.height = 1;
- var x = c.getContext('2d');
- x.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, 1, 1);
- var d = x.getImageData(0, 0, 1, 1).data;
- var rgb = 'rgb(' + d[0] + ',' + d[1] + ',' + d[2] + ')';
- rlSwatchCache[key] = rgb;
- cb(rgb);
- } catch (e) { cb(null); }
- });
+ // ไม่ sample สีจากรูปด้วย getImageData อีกต่อไป — การย่อรูป/decode ต่าง browser
+ // ทำให้ค่าสีเพี้ยนไม่ตรงกัน ใช้ palette hex (ด้านบน) เป็นแหล่งความจริงเดียว
+ cb(null);
}
var LOBBY_PLAYER_TINT_KEY = 'justiceLobbyPlayerTint';
diff --git a/www/html/Game/public/room-lobby.html b/www/html/Game/public/room-lobby.html
index e5442fa..0ade52d 100644
--- a/www/html/Game/public/room-lobby.html
+++ b/www/html/Game/public/room-lobby.html
@@ -1615,9 +1615,9 @@
-
+
-
+