From e7235f1488dbd500c1d99cfd1d08f7f0ecfc7e96 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 May 2026 00:13:00 +0200 Subject: [PATCH 1/8] cleaner online level searcher + maybe fixed loading bug --- assets/scripts/core/game-scene.js | 124 +++++++++++++++++++++--------- 1 file changed, 86 insertions(+), 38 deletions(-) diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index 6eb2b66..1c0747f 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -1154,46 +1154,82 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" const levelIdParsed = gdMap["1"] || levelId; const songIdRaw = (gdMap["35"] || "").trim(); const isCustomSong = !!songIdRaw && songIdRaw !== "0"; + console.log(songIdRaw); const officialSongId = gdMap["12"] || "0"; - const songKey = isCustomSong ? `ng_song_${songIdRaw}` : window.allLevels[officialSongId][0]; + const isLibrarySong = isCustomSong && parseInt(songIdRaw) >= 1000000; + const songKey = isCustomSong + ? (isLibrarySong ? `lib_song_${songIdRaw}` : `ng_song_${songIdRaw}`) + : window.allLevels[officialSongId][0]; window.currentlevel[0] = songKey; window._onlineSongOffset = parseFloat(gdMap["45"] || "0") || 0; - _showStatus(`found "${levelName}"${isCustomSong ? ` — loading song #${songIdRaw}...` : ""}`, "#00ff00"); + const sourceName = isLibrarySong ? "NCS Library" : "Newgrounds"; + _showStatus(`found "${levelName}"${isCustomSong ? ` — loading ${sourceName} #${songIdRaw}...` : ""}`, "#00ff00"); if (isCustomSong) { window._onlineSongBuffer = null; window._onlineSongKey = null; - try { const ngRes = await fetch(`${PROXY_BASE}/getGJSongInfo.php`, { - method: "POST", - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body: `songID=${songIdRaw}&secret=Wmfd2893gb7` + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: `songID=${songIdRaw}&secret=Wmfd2893gb7` }); const ngText = ngRes.ok ? await ngRes.text() : "-1"; - if (ngText && ngText !== "-1") { - const ngParts = ngText.split("~|~"); - const ngMap = {}; - for (let i = 0; i + 1 < ngParts.length; i += 2) ngMap[ngParts[i]] = ngParts[i + 1]; - const rawUrl = (ngMap["10"] || "").trim(); - const songUrl = decodeURIComponent(rawUrl); - const songArtist = (ngMap["4"] || "Unknown").replace(/:$/, "").trim(); - const songTitle = (ngMap["2"] || `Song #${songIdRaw}`).replace(/:$/, "").trim(); - if (songUrl) { - _showStatus(`loading "${songTitle}" by ${songArtist}...`, "#00ff00"); - const audioCtx = this.game.sound.context; - if (audioCtx.state === "suspended") await audioCtx.resume(); - const proxiedUrl = `${PROXY_BASE}/audio-proxy?url=${encodeURIComponent(songUrl)}`; - const audioRes = await fetch(proxiedUrl); - if (!audioRes.ok) throw new Error(`audio proxy returned ${audioRes.status}`); - const arrayBuf = await audioRes.arrayBuffer(); - const decoded = await audioCtx.decodeAudioData(arrayBuf); - window._onlineSongBuffer = decoded; - window._onlineSongKey = songKey; - window._onlineSongTitle = songTitle; - window._onlineSongArtist = songArtist; - } + + if (ngText && ngText !== "-1") { + const ngParts = ngText.split("~|~"); + const ngMap = {}; + for (let i = 0; i + 1 < ngParts.length; i += 2) ngMap[ngParts[i]] = ngParts[i + 1]; + + const songData = { + id: ngMap["1"] || songIdRaw, + title: (ngMap["2"] || "Unknown").trim(), + artistID: ngMap["3"] || "0", + artistName: (ngMap["4"] || "Unknown").trim(), + sizeMB: ngMap["5"] || "0", + videoID: ngMap["6"] || null, + youtubeURL: ngMap["7"] ? decodeURIComponent(ngMap["7"]) : null, + isScouted: ngMap["8"] === "1", + priority: ngMap["9"] || "0", + rawUrl: (ngMap["10"] || "").trim(), + nongType: parseInt(ngMap["11"] || "0"), + //extraIDs: (ngMap["12"] || "").split("."), //array + isNew: ngMap["13"] === "1", + newIconType: ngMap["14"] || "0", + extraArtists: ngMap["15"] || "" + }; + + const isNCS = isLibrarySong || songData.nongType === 1; + + let songUrl = songData.rawUrl ? decodeURIComponent(songData.rawUrl) : null; + + if (!songUrl && isNCS) { + songUrl = `https://geometrydashfiles.b-cdn.net/music/${songIdRaw}.mp3`; + } + + console.table({ ...songData, finalUrl: songUrl, isNCS }); + + if (songUrl) { + _showStatus(`loading "${songData.title}" by ${songData.artistName}...`, "#00ff00"); + + const audioCtx = this.game.sound.context; + if (audioCtx.state === "suspended") await audioCtx.resume(); + + const proxiedUrl = `${PROXY_BASE}/audio-proxy?url=${encodeURIComponent(songUrl)}`; + const audioRes = await fetch(proxiedUrl); + if (!audioRes.ok) throw new Error(`audio proxy returned ${audioRes.status}`); + + const arrayBuf = await audioRes.arrayBuffer(); + const decoded = await audioCtx.decodeAudioData(arrayBuf); + + window._onlineSongBuffer = decoded; + window._onlineSongKey = songKey; + window._onlineSongTitle = songData.title; + window._onlineSongArtist = songData.artistName; + } else { + _showStatus("failed to resolve song URL", "#ff0000"); + } + } else { + _showStatus("Song info failed to load", "#ff0000"); } - } catch (songErr) { - } } else { window._onlineSongBuffer = null; window._onlineSongKey = null; @@ -2246,14 +2282,25 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" this._openSearchMenu(); } if (this.game.registry.get("autoStartGame")) { - this.game.registry.remove("autoStartGame"); - this._levelLabel.setVisible(false); - this._leftBtn.setVisible(false); - this._rightBtn.setVisible(false); - if (this._practiceModeBarContainer) { - this._practiceModeBarContainer.setVisible(this._practicedMode && this._practicedMode.practiceMode); + if (!window.settingsMap) { + const cachedLevelText = this.cache.text.get(window.currentlevel[2]) || + ((window._onlineLevelString && window.currentlevel[2] === window._onlineLevelId) ? window._onlineLevelString : null); + if (cachedLevelText) { + this._level.loadLevel(cachedLevelText); + } + } + if (window.settingsMap) { + this.game.registry.remove("autoStartGame"); + this._levelLabel.setVisible(false); + this._leftBtn.setVisible(false); + this._rightBtn.setVisible(false); + if (this._practiceModeBarContainer) { + this._practiceModeBarContainer.setVisible(this._practicedMode && this._practicedMode.practiceMode); + } + this._startGame(); + } else { + console.warn("autoStartGame: missing settingsMap for", window.currentlevel && window.currentlevel[2]); } - this._startGame(); } } _parseLevelColors(levelId) { @@ -2499,6 +2546,7 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" this._closeLevelSelect(true); this._audio.stopMusic(); this.input.enabled = true; + this.game.registry.set("autoStartGame", true); this.scene.restart(); }); @@ -6577,7 +6625,7 @@ _applyMirrorEffect() { url: "https://discord.gg/TfEzAVWPSJ" }, { key: "downloadSteam_001", - url: "https://store.steampowered.com/app/322170/Geometry_Dash" + url: "https://github.com/web-dashers/web-dashers.github.io" }]; for (let _0x10f8cc = 0; _0x10f8cc < _0x34b1bd.length; _0x10f8cc++) { const _0xd7310b = _0x34b1bd[_0x10f8cc]; From da6252e40cb5035c93cab11166576eb009c5819f Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 May 2026 04:58:47 +0200 Subject: [PATCH 2/8] ts ncs songs --- assets/scripts/core/game-scene.js | 96 ++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index 1c0747f..62885e6 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -1123,7 +1123,7 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" } }; const _doSearchInner = async (levelId) => { - _showStatus("fetching level", "#ffb700"); + _showStatus("fetching level", "#ffb700"); const PROXY_BASE = (window._gdProxyUrl || "").replace(/\/$/, ""); if (!PROXY_BASE) { @@ -1202,8 +1202,98 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" let songUrl = songData.rawUrl ? decodeURIComponent(songData.rawUrl) : null; if (!songUrl && isNCS) { - songUrl = `https://geometrydashfiles.b-cdn.net/music/${songIdRaw}.mp3`; - } + const songId = songIdRaw; + const path = `/music/${songId}.mp3`; + + function generateCdnAuth(path) { + const SALT = "8501f9c2-75ba-4230-8188-51037c4da102"; + const expires = Math.floor(Date.now() / 1000) + 3600; + const inputString = `${SALT}${path}${expires}`; + + const md5Cycle = (x, k) => { + let a = x[0], b = x[1], c = x[2], d = x[3]; + const f = (p, q, r, s, x, sft, t) => { + let val = p + (q & r | ~q & s) + x + t; + return ((val << sft) | (val >>> (32 - sft))) + q; + }; + const g = (p, q, r, s, x, sft, t) => { + let val = p + (q & s | r & ~s) + x + t; + return ((val << sft) | (val >>> (32 - sft))) + q; + }; + const h = (p, q, r, s, x, sft, t) => { + let val = p + (q ^ r ^ s) + x + t; + return ((val << sft) | (val >>> (32 - sft))) + q; + }; + const i = (p, q, r, s, x, sft, t) => { + let val = p + (r ^ (q | ~s)) + x + t; + return ((val << sft) | (val >>> (32 - sft))) + q; + }; + + a = f(a, b, c, d, k[0], 7, -680876936); d = f(d, a, b, c, k[1], 12, -389564586); + c = f(c, d, a, b, k[2], 17, 606105819); b = f(b, c, d, a, k[3], 22, -1044525330); + a = f(a, b, c, d, k[4], 7, -176418897); d = f(d, a, b, c, k[5], 12, 1200080426); + c = f(c, d, a, b, k[6], 17, -1473231341); b = f(b, c, d, a, k[7], 22, -45705983); + a = f(a, b, c, d, k[8], 7, 1770035416); d = f(d, a, b, c, k[9], 12, -1958414417); + c = f(c, d, a, b, k[10], 17, -42063); b = f(b, c, d, a, k[11], 22, -1990404162); + a = f(a, b, c, d, k[12], 7, 1804603682); d = f(d, a, b, c, k[13], 12, -40341101); + c = f(c, d, a, b, k[14], 17, -1502002290); b = f(b, c, d, a, k[15], 22, 1236535329); + + a = g(a, b, c, d, k[1], 5, -165796510); d = g(d, a, b, c, k[6], 9, -1069501632); + c = g(c, d, a, b, k[11], 14, 643717713); b = g(b, c, d, a, k[0], 20, -373897302); + a = g(a, b, c, d, k[5], 5, -701558691); d = g(d, a, b, c, k[10], 9, 38016083); + c = g(c, d, a, b, k[15], 14, -660478335); b = g(b, c, d, a, k[4], 20, -405537848); + a = g(a, b, c, d, k[9], 5, 568446438); d = g(d, a, b, c, k[14], 9, -1019803690); + c = g(c, d, a, b, k[3], 14, -187363961); b = g(b, c, d, a, k[8], 20, 1163531501); + a = g(a, b, c, d, k[13], 5, -1444681467); d = g(d, a, b, c, k[2], 9, -51403784); + c = g(c, d, a, b, k[7], 14, 1735328473); b = g(b, c, d, a, k[12], 20, -1926607734); + + a = h(a, b, c, d, k[5], 4, -378558); d = h(d, a, b, c, k[8], 11, -2022574463); + c = h(c, d, a, b, k[11], 16, 1839030562); b = h(b, c, d, a, k[14], 23, -35309556); + a = h(a, b, c, d, k[1], 4, -1530992060); d = h(d, a, b, c, k[4], 11, 1272893353); + c = h(c, d, a, b, k[7], 16, -155497632); b = h(b, c, d, a, k[10], 23, -1094730640); + a = h(a, b, c, d, k[13], 4, 681279174); d = h(d, a, b, c, k[0], 11, -358537222); + c = h(c, d, a, b, k[3], 16, -722521979); b = h(b, c, d, a, k[6], 23, 76029189); + a = h(a, b, c, d, k[9], 4, -640364487); d = h(d, a, b, c, k[12], 11, -421815835); + c = h(c, d, a, b, k[15], 16, 530742520); b = h(b, c, d, a, k[2], 23, -995338651); + + a = i(a, b, c, d, k[0], 6, -198630844); d = i(d, a, b, c, k[7], 10, 1126891415); + c = i(c, d, a, b, k[14], 15, -1416354905); b = i(b, c, d, a, k[5], 21, -57434055); + a = i(a, b, c, d, k[12], 6, 1700485571); d = i(d, a, b, c, k[3], 10, -1894986606); + c = i(c, d, a, b, k[10], 15, -1051523); b = i(b, c, d, a, k[1], 21, -2054922799); + a = i(a, b, c, d, k[8], 6, 1873313359); d = i(d, a, b, c, k[15], 10, -30611744); + c = i(c, d, a, b, k[6], 15, -1560198380); b = i(b, c, d, a, k[13], 21, 1309151649); + a = i(a, b, c, d, k[4], 6, -145523070); d = i(d, a, b, c, k[11], 10, -1120210379); + c = i(c, d, a, b, k[2], 15, 718787259); b = i(b, c, d, a, k[9], 21, -343485551); + + x[0] = (x[0] + a) | 0; x[1] = (x[1] + b) | 0; + x[2] = (x[2] + c) | 0; x[3] = (x[3] + d) | 0; + }; + + const md5Raw = (str) => { + let n = str.length, state = [1732584193, -271733879, -1732584194, 271733878], i; + let words = []; + for (i = 0; i <= n; i++) words[i >> 2] |= (str.charCodeAt(i) || 128) << ((i % 4) << 3); + words[(((n + 8) >> 6) << 4) + 14] = n * 8; + for (i = 0; i < words.length; i += 16) md5Cycle(state, words.slice(i, i + 16)); + return state.map(val => [val & 0xFF, (val >> 8) & 0xFF, (val >> 16) & 0xFF, (val >> 24) & 0xFF]).flat(); + }; + + const hashBytes = md5Raw(inputString); + const binaryStr = String.fromCharCode(...hashBytes); + const token = btoa(binaryStr) + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/, ''); + + return { token, expires }; + } + + const auth = generateCdnAuth("/sfx/sfxlibrary_version.txt"); + console.log(auth.token, auth.expires); + + songUrl = `https://geometrydashfiles.b-cdn.net${path}?token=${auth.token}&expires=${auth.expires}`; + + console.log("Generated NCS URL:", songUrl); } console.table({ ...songData, finalUrl: songUrl, isNCS }); From b230ec763938cb63d259df510c1de77a7260f537 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 May 2026 18:47:34 +0200 Subject: [PATCH 3/8] better levelData --- assets/scripts/core/game-scene.js | 267 +++++++++++++++++------------- 1 file changed, 151 insertions(+), 116 deletions(-) diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index 62885e6..2f9b319 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -1142,35 +1142,72 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" _showStatus("level not found from servers. check the id and try again.", "#ff0000"); return; } - const gdMap = {}; - const _gdMatches = [...rawResponse.matchAll(/(?:^|:)(\d+):/g)]; - for (let i = 0; i < _gdMatches.length; i++) { - const valueStart = _gdMatches[i].index + _gdMatches[i][0].length; - const valueEnd = i + 1 < _gdMatches.length ? _gdMatches[i + 1].index : rawResponse.length; - gdMap[_gdMatches[i][1]] = rawResponse.slice(valueStart, valueEnd); + + const responseSegments = rawResponse.split("#"); + const lvlParts = responseSegments[0].split(":"); + const lvlMap = {}; + for (let i = 0; i + 1 < lvlParts.length; i += 2) { + lvlMap[lvlParts[i]] = lvlParts[i + 1]; } - const levelString = gdMap["4"] || null; - const levelName = gdMap["2"] || "Online Level"; - const levelIdParsed = gdMap["1"] || levelId; - const songIdRaw = (gdMap["35"] || "").trim(); - const isCustomSong = !!songIdRaw && songIdRaw !== "0"; - console.log(songIdRaw); - const officialSongId = gdMap["12"] || "0"; - const isLibrarySong = isCustomSong && parseInt(songIdRaw) >= 1000000; - const songKey = isCustomSong - ? (isLibrarySong ? `lib_song_${songIdRaw}` : `ng_song_${songIdRaw}`) - : window.allLevels[officialSongId][0]; + + const levelData = { + // Core Level Info + id: lvlMap["1"] || levelId, + title: (lvlMap["2"] || "Online Level").trim(), + description: lvlMap["3"] ? atob(lvlMap["3"].replace(/-/g, '+').replace(/_/g, '/')) : "", // Base64 decoded + string: lvlMap["4"] || null, // The raw level data string + version: parseInt(lvlMap["5"]) || 1, + + // User / Author Info + playerID: lvlMap["6"] || null, + accountID: lvlMap["57"] || null, // The author's accountID returned by the server + + // Song Info + officialSong: lvlMap["12"] || "0", + customSongID: (lvlMap["35"] || "").trim(), + isCustomSong: !!(lvlMap["35"] || "").trim() && (lvlMap["35"] || "").trim() !== "0", + isLibrarySong: !!(lvlMap["35"] || "").trim() && (lvlMap["35"] || "").trim() !== "0" && parseInt((lvlMap["35"] || "").trim()) >= 1000000, + offset: parseFloat(lvlMap["45"] || "0") || 0, + + // Gameplay Details + difficulty: parseInt(lvlMap["9"]) || 0, // Auto, Easy, Normal, Hard, Harder, Insane + stars: parseInt(lvlMap["18"]) || 0, + diamonds: parseInt(lvlMap["46"]) || 0, + orbs: parseInt(lvlMap["48"]) || 0, + length: parseInt(lvlMap["15"]) || 0, // 0=Tiny, 1=Small, 2=Medium, 3=Long, 4=XL, 5=Platformer + gameVersion: parseInt(lvlMap["13"]) || 22, // The game version the level was created in (e.g. 22 = 2.2) + binaryVersion: parseInt(lvlMap["52"]) || 0, // The build version used to upload + + // Meta / Social Counters + downloads: parseInt(lvlMap["10"]) || 0, + likes: parseInt(lvlMap["14"]) || 0, + objects: parseInt(lvlMap["45"]) || 0, // Object count (Note: 45 can double as audio offset or object count depending on context) + ts: lvlMap["28"] || null, // Upload/Update timestamp hint + + // Technical / Security Verification keys sent back by server + chk: lvlMap["chk"] || null, + rs: lvlMap["rs"] || null + }; + + const { string, ...tableFriendlyData } = levelData; + console.table(tableFriendlyData); + + const songKey = levelData.isCustomSong + ? (levelData.isLibrarySong ? `lib_song_${levelData.customSongID}` : `ng_song_${levelData.customSongID}`) + : window.allLevels[levelData.officialSong][0]; + window.currentlevel[0] = songKey; - window._onlineSongOffset = parseFloat(gdMap["45"] || "0") || 0; - const sourceName = isLibrarySong ? "NCS Library" : "Newgrounds"; - _showStatus(`found "${levelName}"${isCustomSong ? ` — loading ${sourceName} #${songIdRaw}...` : ""}`, "#00ff00"); - if (isCustomSong) { + window._onlineSongOffset = levelData.offset; + + const sourceName = levelData.isLibrarySong ? "NCS Library" : "Newgrounds"; + _showStatus(`found "${levelData.title}"${levelData.isCustomSong ? ` — loading ${sourceName} #${levelData.customSongID}...` : ""}`, "#00ff00");; + if (levelData.isCustomSong) { window._onlineSongBuffer = null; window._onlineSongKey = null; const ngRes = await fetch(`${PROXY_BASE}/getGJSongInfo.php`, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body: `songID=${songIdRaw}&secret=Wmfd2893gb7` + body: `songID=${levelData.customSongID}&secret=Wmfd2893gb7` }); const ngText = ngRes.ok ? await ngRes.text() : "-1"; @@ -1180,7 +1217,7 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" for (let i = 0; i + 1 < ngParts.length; i += 2) ngMap[ngParts[i]] = ngParts[i + 1]; const songData = { - id: ngMap["1"] || songIdRaw, + id: ngMap["1"] || levelData.customSongID, title: (ngMap["2"] || "Unknown").trim(), artistID: ngMap["3"] || "0", artistName: (ngMap["4"] || "Unknown").trim(), @@ -1197,105 +1234,103 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" extraArtists: ngMap["15"] || "" }; - const isNCS = isLibrarySong || songData.nongType === 1; - + const isNCS = levelData.isLibrarySong || songData.nongType === 1; let songUrl = songData.rawUrl ? decodeURIComponent(songData.rawUrl) : null; if (!songUrl && isNCS) { - const songId = songIdRaw; - const path = `/music/${songId}.mp3`; - - function generateCdnAuth(path) { - const SALT = "8501f9c2-75ba-4230-8188-51037c4da102"; - const expires = Math.floor(Date.now() / 1000) + 3600; - const inputString = `${SALT}${path}${expires}`; - - const md5Cycle = (x, k) => { - let a = x[0], b = x[1], c = x[2], d = x[3]; - const f = (p, q, r, s, x, sft, t) => { - let val = p + (q & r | ~q & s) + x + t; - return ((val << sft) | (val >>> (32 - sft))) + q; - }; - const g = (p, q, r, s, x, sft, t) => { - let val = p + (q & s | r & ~s) + x + t; - return ((val << sft) | (val >>> (32 - sft))) + q; - }; - const h = (p, q, r, s, x, sft, t) => { - let val = p + (q ^ r ^ s) + x + t; - return ((val << sft) | (val >>> (32 - sft))) + q; - }; - const i = (p, q, r, s, x, sft, t) => { - let val = p + (r ^ (q | ~s)) + x + t; - return ((val << sft) | (val >>> (32 - sft))) + q; - }; - - a = f(a, b, c, d, k[0], 7, -680876936); d = f(d, a, b, c, k[1], 12, -389564586); - c = f(c, d, a, b, k[2], 17, 606105819); b = f(b, c, d, a, k[3], 22, -1044525330); - a = f(a, b, c, d, k[4], 7, -176418897); d = f(d, a, b, c, k[5], 12, 1200080426); - c = f(c, d, a, b, k[6], 17, -1473231341); b = f(b, c, d, a, k[7], 22, -45705983); - a = f(a, b, c, d, k[8], 7, 1770035416); d = f(d, a, b, c, k[9], 12, -1958414417); - c = f(c, d, a, b, k[10], 17, -42063); b = f(b, c, d, a, k[11], 22, -1990404162); - a = f(a, b, c, d, k[12], 7, 1804603682); d = f(d, a, b, c, k[13], 12, -40341101); - c = f(c, d, a, b, k[14], 17, -1502002290); b = f(b, c, d, a, k[15], 22, 1236535329); - - a = g(a, b, c, d, k[1], 5, -165796510); d = g(d, a, b, c, k[6], 9, -1069501632); - c = g(c, d, a, b, k[11], 14, 643717713); b = g(b, c, d, a, k[0], 20, -373897302); - a = g(a, b, c, d, k[5], 5, -701558691); d = g(d, a, b, c, k[10], 9, 38016083); - c = g(c, d, a, b, k[15], 14, -660478335); b = g(b, c, d, a, k[4], 20, -405537848); - a = g(a, b, c, d, k[9], 5, 568446438); d = g(d, a, b, c, k[14], 9, -1019803690); - c = g(c, d, a, b, k[3], 14, -187363961); b = g(b, c, d, a, k[8], 20, 1163531501); - a = g(a, b, c, d, k[13], 5, -1444681467); d = g(d, a, b, c, k[2], 9, -51403784); - c = g(c, d, a, b, k[7], 14, 1735328473); b = g(b, c, d, a, k[12], 20, -1926607734); - - a = h(a, b, c, d, k[5], 4, -378558); d = h(d, a, b, c, k[8], 11, -2022574463); - c = h(c, d, a, b, k[11], 16, 1839030562); b = h(b, c, d, a, k[14], 23, -35309556); - a = h(a, b, c, d, k[1], 4, -1530992060); d = h(d, a, b, c, k[4], 11, 1272893353); - c = h(c, d, a, b, k[7], 16, -155497632); b = h(b, c, d, a, k[10], 23, -1094730640); - a = h(a, b, c, d, k[13], 4, 681279174); d = h(d, a, b, c, k[0], 11, -358537222); - c = h(c, d, a, b, k[3], 16, -722521979); b = h(b, c, d, a, k[6], 23, 76029189); - a = h(a, b, c, d, k[9], 4, -640364487); d = h(d, a, b, c, k[12], 11, -421815835); - c = h(c, d, a, b, k[15], 16, 530742520); b = h(b, c, d, a, k[2], 23, -995338651); - - a = i(a, b, c, d, k[0], 6, -198630844); d = i(d, a, b, c, k[7], 10, 1126891415); - c = i(c, d, a, b, k[14], 15, -1416354905); b = i(b, c, d, a, k[5], 21, -57434055); - a = i(a, b, c, d, k[12], 6, 1700485571); d = i(d, a, b, c, k[3], 10, -1894986606); - c = i(c, d, a, b, k[10], 15, -1051523); b = i(b, c, d, a, k[1], 21, -2054922799); - a = i(a, b, c, d, k[8], 6, 1873313359); d = i(d, a, b, c, k[15], 10, -30611744); - c = i(c, d, a, b, k[6], 15, -1560198380); b = i(b, c, d, a, k[13], 21, 1309151649); - a = i(a, b, c, d, k[4], 6, -145523070); d = i(d, a, b, c, k[11], 10, -1120210379); - c = i(c, d, a, b, k[2], 15, 718787259); b = i(b, c, d, a, k[9], 21, -343485551); - - x[0] = (x[0] + a) | 0; x[1] = (x[1] + b) | 0; - x[2] = (x[2] + c) | 0; x[3] = (x[3] + d) | 0; - }; - - const md5Raw = (str) => { - let n = str.length, state = [1732584193, -271733879, -1732584194, 271733878], i; - let words = []; - for (i = 0; i <= n; i++) words[i >> 2] |= (str.charCodeAt(i) || 128) << ((i % 4) << 3); - words[(((n + 8) >> 6) << 4) + 14] = n * 8; - for (i = 0; i < words.length; i += 16) md5Cycle(state, words.slice(i, i + 16)); - return state.map(val => [val & 0xFF, (val >> 8) & 0xFF, (val >> 16) & 0xFF, (val >> 24) & 0xFF]).flat(); - }; - - const hashBytes = md5Raw(inputString); - const binaryStr = String.fromCharCode(...hashBytes); - const token = btoa(binaryStr) - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=+$/, ''); - - return { token, expires }; - } + const songId = levelData.customSongID; + const path = `/music/${songId}.mp3`; + + function generateCdnAuth(path) { + const SALT = "8501f9c2-75ba-4230-8188-51037c4da102"; + const expires = Math.floor(Date.now() / 1000) + 3600; + const inputString = `${SALT}${path}${expires}`; + + const md5Cycle = (x, k) => { + let a = x[0], b = x[1], c = x[2], d = x[3]; + const f = (p, q, r, s, x, sft, t) => { + let val = p + (q & r | ~q & s) + x + t; + return ((val << sft) | (val >>> (32 - sft))) + q; + }; + const g = (p, q, r, s, x, sft, t) => { + let val = p + (q & s | r & ~s) + x + t; + return ((val << sft) | (val >>> (32 - sft))) + q; + }; + const h = (p, q, r, s, x, sft, t) => { + let val = p + (q ^ r ^ s) + x + t; + return ((val << sft) | (val >>> (32 - sft))) + q; + }; + const i = (p, q, r, s, x, sft, t) => { + let val = p + (r ^ (q | ~s)) + x + t; + return ((val << sft) | (val >>> (32 - sft))) + q; + }; + + a = f(a, b, c, d, k[0], 7, -680876936); d = f(d, a, b, c, k[1], 12, -389564586); + c = f(c, d, a, b, k[2], 17, 606105819); b = f(b, c, d, a, k[3], 22, -1044525330); + a = f(a, b, c, d, k[4], 7, -176418897); d = f(d, a, b, c, k[5], 12, 1200080426); + c = f(c, d, a, b, k[6], 17, -1473231341); b = f(b, c, d, a, k[7], 22, -45705983); + a = f(a, b, c, d, k[8], 7, 1770035416); d = f(d, a, b, c, k[9], 12, -1958414417); + c = f(c, d, a, b, k[10], 17, -42063); b = f(b, c, d, a, k[11], 22, -1990404162); + a = f(a, b, c, d, k[12], 7, 1804603682); d = f(d, a, b, c, k[13], 12, -40341101); + c = f(c, d, a, b, k[14], 17, -1502002290); b = f(b, c, d, a, k[15], 22, 1236535329); + + a = g(a, b, c, d, k[1], 5, -165796510); d = g(d, a, b, c, k[6], 9, -1069501632); + c = g(c, d, a, b, k[11], 14, 643717713); b = g(b, c, d, a, k[0], 20, -373897302); + a = g(a, b, c, d, k[5], 5, -701558691); d = g(d, a, b, c, k[10], 9, 38016083); + c = g(c, d, a, b, k[15], 14, -660478335); b = g(b, c, d, a, k[4], 20, -405537848); + a = g(a, b, c, d, k[9], 5, 568446438); d = g(d, a, b, c, k[14], 9, -1019803690); + c = g(c, d, a, b, k[3], 14, -187363961); b = g(b, c, d, a, k[8], 20, 1163531501); + a = g(a, b, c, d, k[13], 5, -1444681467); d = g(d, a, b, c, k[2], 9, -51403784); + c = g(c, d, a, b, k[7], 14, 1735328473); b = g(b, c, d, a, k[12], 20, -1926607734); + + a = h(a, b, c, d, k[5], 4, -378558); d = h(d, a, b, c, k[8], 11, -2022574463); + c = h(c, d, a, b, k[11], 16, 1839030562); b = h(b, c, d, a, k[14], 23, -35309556); + a = h(a, b, c, d, k[1], 4, -1530992060); d = h(d, a, b, c, k[4], 11, 1272893353); + c = h(c, d, a, b, k[7], 16, -155497632); b = h(b, c, d, a, k[10], 23, -1094730640); + a = h(a, b, c, d, k[13], 4, 681279174); d = h(d, a, b, c, k[0], 11, -358537222); + c = h(c, d, a, b, k[3], 16, -722521979); b = h(b, c, d, a, k[6], 23, 76029189); + a = h(a, b, c, d, k[9], 4, -640364487); d = h(d, a, b, c, k[12], 11, -421815835); + c = h(c, d, a, b, k[15], 16, 530742520); b = h(b, c, d, a, k[2], 23, -995338651); + + a = i(a, b, c, d, k[0], 6, -198630844); d = i(d, a, b, c, k[7], 10, 1126891415); + c = i(c, d, a, b, k[14], 15, -1416354905); b = i(b, c, d, a, k[5], 21, -57434055); + a = i(a, b, c, d, k[12], 6, 1700485571); d = i(d, a, b, c, k[3], 10, -1894986606); + c = i(c, d, a, b, k[10], 15, -1051523); b = i(b, c, d, a, k[1], 21, -2054922799); + a = i(a, b, c, d, k[8], 6, 1873313359); d = i(d, a, b, c, k[15], 10, -30611744); + c = i(c, d, a, b, k[6], 15, -1560198380); b = i(b, c, d, a, k[13], 21, 1309151649); + a = i(a, b, c, d, k[4], 6, -145523070); d = i(d, a, b, c, k[11], 10, -1120210379); + c = i(c, d, a, b, k[2], 15, 718787259); b = i(b, c, d, a, k[9], 21, -343485551); + + x[0] = (x[0] + a) | 0; x[1] = (x[1] + b) | 0; + x[2] = (x[2] + c) | 0; x[3] = (x[3] + d) | 0; + }; + + const md5Raw = (str) => { + let n = str.length, state = [1732584193, -271733879, -1732584194, 271733878], i; + let words = []; + for (i = 0; i <= n; i++) words[i >> 2] |= (str.charCodeAt(i) || 128) << ((i % 4) << 3); + words[(((n + 8) >> 6) << 4) + 14] = n * 8; + for (i = 0; i < words.length; i += 16) md5Cycle(state, words.slice(i, i + 16)); + return state.map(val => [val & 0xFF, (val >> 8) & 0xFF, (val >> 16) & 0xFF, (val >> 24) & 0xFF]).flat(); + }; + + const hashBytes = md5Raw(inputString); + const binaryStr = String.fromCharCode(...hashBytes); + const token = btoa(binaryStr) + .replace(/\+/g, '-') + .replace(/\//g, '_') + .replace(/=+$/, ''); + + return { token, expires }; + } - const auth = generateCdnAuth("/sfx/sfxlibrary_version.txt"); - console.log(auth.token, auth.expires); + const auth = generateCdnAuth(path); - songUrl = `https://geometrydashfiles.b-cdn.net${path}?token=${auth.token}&expires=${auth.expires}`; - - console.log("Generated NCS URL:", songUrl); } + songUrl = `https://geometrydashfiles.b-cdn.net${path}?token=${auth.token}&expires=${auth.expires}`; + } - console.table({ ...songData, finalUrl: songUrl, isNCS }); + console.table({ ...songData}); + console.log(songUrl); if (songUrl) { _showStatus(`loading "${songData.title}" by ${songData.artistName}...`, "#00ff00"); From 89581780c1e64f66a83af5f70c56a06599063883 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 May 2026 19:01:24 +0200 Subject: [PATCH 4/8] correct variable name --- assets/scripts/core/game-scene.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index 2f9b319..a4b20ef 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -1360,17 +1360,17 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" window._onlineSongKey = null; window._onlineSongArtist = null; } - window._onlineLevelString = levelString; - window._onlineLevelName = levelName; - window._onlineLevelId = "online_" + levelIdParsed; + window._onlineLevelString = levelData.string; + window._onlineLevelName = levelData.title; + window._onlineLevelId = "online_" + levelData.id; this.game.registry.set("autoStartGame", true); window.currentlevel = [ songKey, - levelName, + window._onlineLevelName, window._onlineLevelId, [window._onlineSongArtist || "Unknown"] ]; - _showStatus(`loading string for "${levelName}"`, "#00ff00"); + _showStatus(`loading string for "${window._onlineLevelName}"`, "#00ff00"); this.time.delayedCall(600, () => { htmlInput.remove(); window.removeEventListener("resize", _repositionInput); From 89e259d5ae865593fd3d7d6b389830d3bd18c314 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 May 2026 19:09:41 +0200 Subject: [PATCH 5/8] minor fixes + prettier --- assets/scripts/core/game-scene.js | 43 +++++++++++++++++++------------ 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index a4b20ef..7bfbf63 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -1333,25 +1333,36 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" console.log(songUrl); if (songUrl) { - _showStatus(`loading "${songData.title}" by ${songData.artistName}...`, "#00ff00"); - - const audioCtx = this.game.sound.context; - if (audioCtx.state === "suspended") await audioCtx.resume(); + _showStatus(`loading "${songData.title}" by ${songData.artistName}...`, "#00ff00"); + + const audioCtx = this.game.sound.context; + if (audioCtx.state === "suspended") await audioCtx.resume(); - const proxiedUrl = `${PROXY_BASE}/audio-proxy?url=${encodeURIComponent(songUrl)}`; - const audioRes = await fetch(proxiedUrl); - if (!audioRes.ok) throw new Error(`audio proxy returned ${audioRes.status}`); + window._onlineSongKey = songKey; + window._onlineSongTitle = songData.title; + window._onlineSongArtist = songData.artistName; - const arrayBuf = await audioRes.arrayBuffer(); - const decoded = await audioCtx.decodeAudioData(arrayBuf); + try { + const proxiedUrl = `${PROXY_BASE}/audio-proxy?url=${encodeURIComponent(songUrl)}`; + const audioRes = await fetch(proxiedUrl); + + if (!audioRes.ok) throw new Error(`audio proxy returned ${audioRes.status}`); - window._onlineSongBuffer = decoded; - window._onlineSongKey = songKey; - window._onlineSongTitle = songData.title; - window._onlineSongArtist = songData.artistName; - } else { - _showStatus("failed to resolve song URL", "#ff0000"); - } + const arrayBuf = await audioRes.arrayBuffer(); + const decoded = await audioCtx.decodeAudioData(arrayBuf); + + window._onlineSongBuffer = decoded; + _showStatus(`loaded "${songData.title}" successfully!`, "#00ff00"); + + } catch (error) { + console.error("Failed to load audio via proxy:", error.message); + _showStatus(`failed to load audio: ${songData.title}`, "#ffaa00"); + + window._onlineSongBuffer = null; + } + } else { + _showStatus("failed to resolve song URL", "#ff0000"); + } } else { _showStatus("Song info failed to load", "#ff0000"); } From 9eb5b110b4e0a58c47854b6e480b54104410375c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 May 2026 19:19:51 +0200 Subject: [PATCH 6/8] collapsed tables --- assets/scripts/core/game-scene.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index 7bfbf63..15734ec 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -1188,10 +1188,11 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" chk: lvlMap["chk"] || null, rs: lvlMap["rs"] || null }; - + console.groupCollapsed("level data"); const { string, ...tableFriendlyData } = levelData; console.table(tableFriendlyData); - + console.groupEnd(); + const songKey = levelData.isCustomSong ? (levelData.isLibrarySong ? `lib_song_${levelData.customSongID}` : `ng_song_${levelData.customSongID}`) : window.allLevels[levelData.officialSong][0]; @@ -1328,9 +1329,11 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" songUrl = `https://geometrydashfiles.b-cdn.net${path}?token=${auth.token}&expires=${auth.expires}`; } - + + console.groupCollapsed("song data"); console.table({ ...songData}); console.log(songUrl); + console.groupEnd(); if (songUrl) { _showStatus(`loading "${songData.title}" by ${songData.artistName}...`, "#00ff00"); From f9355834ba69d29c75294ac0428351813958c722 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 16 May 2026 20:05:17 +0200 Subject: [PATCH 7/8] finally fixed lazyloading --- assets/scripts/core/game-scene.js | 51 +++++++++++++-------------- assets/scripts/core/loading-screen.js | 4 +-- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index 446eda0..711609d 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -2748,35 +2748,32 @@ this._menuUpdateLogBtn = this.add.image(screenWidth - 30 - 50, 33, "GJ_WebSheet" } else { if (ptr.x >= cardX - cardW/2 && ptr.x <= cardX + cardW/2 && ptr.y >= cardY - cardH/2 && ptr.y <= cardY + cardH/2) { - this.input.enabled = false; - const lvl = window.currentlevel; - const songID = lvl[0]; - const levelFileName = lvl[2]; - const songFileName = lvl[4] ? lvl[4] : lvl[1].replaceAll(" ", ""); - const loadingText = this.add.bitmapText(cx, cy, "goldFont", "Downloading Level Assets...", 20).setOrigin(0.5).setDepth(200); - - this.load.text(levelFileName, "assets/levels/" + levelFileName.split("_")[1] + ".txt"); - this.load.audio(songID, "assets/music/" + songFileName + ".mp3"); - - this.load.once("complete", () => { - loadingText.destroy(); - this._audio.playEffect("playSound_01", { volume: 1 }); - this._closeLevelSelect(true); - this._audio.stopMusic(); - this.input.enabled = true; - this.game.registry.set("autoStartGame", true); - this.scene.restart(); - }); - this.load.start(); + this.input.enabled = false; + this.tweens.killTweensOf(cardBounceContainer, "scale"); + cardBounceContainer.setScale(1); + + const lvl = window.currentlevel; + const songID = lvl[0]; + const levelFileName = lvl[2]; + const songFileName = lvl[4] ? lvl[4] : lvl[1].replaceAll(" ", ""); + + const loadingText = this.add.bitmapText(cx, cy, "goldFont", "Downloading Level Assets...", 20).setOrigin(0.5).setDepth(200); + + this.load.text(levelFileName, "assets/levels/" + levelFileName.split("_")[1] + ".txt"); + this.load.audio(songID, "assets/music/" + songFileName + ".mp3"); - this.tweens.killTweensOf(cardBounceContainer, "scale"); - cardBounceContainer.setScale(1); - this._audio.playEffect("playSound_01", { volume: 1 }); - this._closeLevelSelect(true); - this._audio.stopMusic(); - this.game.registry.set("autoStartGame", true); - this.scene.restart(); + this.load.once("complete", () => { + loadingText.destroy(); + this._audio.playEffect("playSound_01", { volume: 1 }); + this._closeLevelSelect(true); + this._audio.stopMusic(); + this.input.enabled = true; + this.game.registry.set("autoStartGame", true); + this.scene.restart(); + }); + + this.load.start(); } else { this.tweens.killTweensOf(cardBounceContainer, "scale"); this.tweens.add({ targets: cardBounceContainer, scale: 1, duration: 200, ease: "Quad.Out" }); diff --git a/assets/scripts/core/loading-screen.js b/assets/scripts/core/loading-screen.js index 68274a9..89888ac 100644 --- a/assets/scripts/core/loading-screen.js +++ b/assets/scripts/core/loading-screen.js @@ -289,10 +289,10 @@ class BootScene extends Phaser.Scene { this.load.audio("menu_music", "assets/music/menuLoop.mp3"); this.load.audio("StayInsideMe", "assets/music/StayInsideMe.mp3"); - for (const lvlarray of window.allLevels) { + /*for (const lvlarray of window.allLevels) { this.load.text(lvlarray[2], "assets/levels/" + lvlarray[2].split("_")[1] + ".txt"); this.load.audio(lvlarray[0], "assets/music/" + (lvlarray[4] ? lvlarray[4] : lvlarray[1].replaceAll(" ", "")) + ".mp3"); - } + }*/ this.load.audio("explode_11", "assets/sfx/explode_11.ogg"); this.load.audio("endStart_02", "assets/sfx/endStart_02.ogg"); From fa21779282e87e8f48c4caacf68ae21bc02e981f Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 17 May 2026 22:00:33 +0200 Subject: [PATCH 8/8] added object id visualisation --- assets/scripts/core/game-scene.js | 24 +++++++++++-- assets/scripts/core/level.js | 56 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/assets/scripts/core/game-scene.js b/assets/scripts/core/game-scene.js index 711609d..39850eb 100644 --- a/assets/scripts/core/game-scene.js +++ b/assets/scripts/core/game-scene.js @@ -3461,6 +3461,16 @@ _buildSettingsPopup() { () => window.solidWave, (v) => window.solidWave = v ); + + createToggle(container, column1X, startY + (spacingY * 5), "Create Object ID labels", + () => window.createObjectIds, + (v) => window.createObjectIds = v + ); + + createToggle(container, column1X, startY + (spacingY * 6), "Show Object ID labels", + () => window.showObjectIds, + (v) => window.showObjectIds = v + ); }; const buildPage = (idx) => { @@ -3493,7 +3503,9 @@ _buildSettingsPopup() { solidWaveTrail: window.solidWave, noclipAccuracy: window.noClipAccuracy, hitboxesOnDeath: window.hitboxesOnDeath, - showEditorGlow: window.showEditorGlow + showEditorGlow: window.showEditorGlow, + createObjectIds: window.createObjectIds, + showObjectIds: window.showObjectIds }; localStorage.setItem("gd_settings", JSON.stringify(settings)); } @@ -3510,7 +3522,9 @@ _buildSettingsPopup() { solidWaveTrail: false, noclipAccuracy: false, hitboxesOnDeath: false, - showEditorGlow: false + showEditorGlow: false, + createObjectIds: false, + showObjectIds: false }; const data = saved ? JSON.parse(saved) : defaults; @@ -3526,6 +3540,8 @@ _buildSettingsPopup() { window.noClipAccuracy = data.noclipAccuracy; window.hitboxesOnDeath = data.hitboxesOnDeath; window.showEditorGlow = data.showEditorGlow; + window.createObjectIds = data.createObjectIds; + window.showObjectIds = data.showObjectIds; } _buildInfoPopup() { @@ -4835,6 +4851,7 @@ _buildSettingsPopup() { this._level.topContainer.x = -this._cameraX; this._level.topContainer.y = this._cameraY; this._level.updateVisibility(this._cameraX); + this._level.updateObjectDebugIds(); this._updateBackground(); this._applyMirrorEffect(); if (!this._audio.musicPlaying) { @@ -4882,6 +4899,7 @@ _buildSettingsPopup() { this._level.shiftGroundTiles(this._cameraX - _0x56287b); this._level.updateGroundTiles(this._cameraY); this._level.updateVisibility(this._cameraX); + this._level.updateObjectDebugIds(); this._level.applyEnterEffects(this._cameraX); const _0xde8a1a = this._playerWorldX - this._cameraX; this._player.syncSprites(this._cameraX, this._cameraY, 0, this._getMirrorXOffset(_0xde8a1a)); @@ -5078,6 +5096,7 @@ _buildSettingsPopup() { this._level.topContainer.x = -this._cameraX; this._level.topContainer.y = this._cameraY; this._level.updateVisibility(this._cameraX); + this._level.updateObjectDebugIds(); this._updateBackground(); this._level.stepGroundAnimation(deltaTime / 1000); this._level.updateGroundTiles(this._cameraY); @@ -5381,6 +5400,7 @@ if (!this._state.isFlying && !this._state.isWave && !this._state.isUfo) { this._bg.setTint(this._colorManager.getHex(fs)); this._level.setGroundColor(this._colorManager.getHex(gs)); this._level.updateVisibility(this._cameraX); + this._level.updateObjectDebugIds(); this._level.checkEnterEffectTriggers(playerX); this._level.applyEnterEffects(this._cameraX); this._glitterCenterX = this._cameraX + screenWidth / 2; diff --git a/assets/scripts/core/level.js b/assets/scripts/core/level.js index 86f424f..19c3b39 100644 --- a/assets/scripts/core/level.js +++ b/assets/scripts/core/level.js @@ -329,6 +329,7 @@ window.LevelObject = class LevelObject { this._ceilingStartScreenY = 0; this._activeStartPosIndex = -1; this._startPositions = []; + this._debugIdTextsList = []; this._buildGround(); } getStartPositions() { @@ -1454,6 +1455,46 @@ window.LevelObject = class LevelObject { } this.endXPos = Math.max(screenWidth + 1200, this._lastObjectX + 680); + + if (window.createObjectIds) { + const scene = this._scene; + const worldContainer = this.container || this._container; + + if (worldContainer) { + this._debugIdTextsList = []; + + _0x35f1ae.forEach((levelObj, index) => { + if (!levelObj || levelObj.id === undefined) return; + + const worldX = levelObj.x * 2; + const textY = typeof b === 'function' ? b(levelObj.y * 2) : levelObj.y * 2; + + const idText = scene.add.text(worldX, textY, String(levelObj.id), { + fontFamily: 'monospace', + fontSize: '30px', + fill: '#00ff00', + stroke: '#000000', + strokeThickness: 3 + }); + idText.setOrigin(0.5); + idText.setDepth(999); + idText.setVisible(window.showObjectIds); + + worldContainer.add(idText); + + idText.preUpdate = () => { + idText.x = worldX; + idText.y = textY; + }; + + scene.sys.updateList.add(idText); + this._debugIdTextsList.push(idText); + + if (!this.objectSprites[index]) this.objectSprites[index] = []; + this.objectSprites[index].push(idText); + }); + } + } } createEndPortal(_0x41fbdb) { if (window.isEditor) return; // not dealing with ts rn @@ -1635,6 +1676,21 @@ window.LevelObject = class LevelObject { this._visMaxSec = sliderHeight; } } + updateObjectDebugIds() { + if (window.showObjectIds) { + if (this._debugIdTextsList && this._debugIdTextsList.length > 0) { + for (const idText of this._debugIdTextsList) { + if (idText) idText.setVisible(true); + } + } + } else { + if (this._debugIdTextsList && this._debugIdTextsList.length > 0 ) { + for (const idText of this._debugIdTextsList) { + if (idText) idText.setVisible(false); + } + } + } + } getNearbySectionObjects(_0x2e85c7) { const _0x55d1b7 = Math.max(0, Math.floor(_0x2e85c7 / 400)); const _0x31c345 = Math.max(0, _0x55d1b7 - 1);