"use strict"; var CloudSDK; (function (CloudSDK) { // Local backend endpoints const API_PREFIX = ""; // Relative to current origin async function resolveToken(token) { if (token && token.length === 5) { try { const response = await fetch(API_PREFIX + "/token/get?id=" + token); const data = await response.json(); if (data.token === token) { return data; } } catch (e) { console.error("Token check failed", e); } } return null; } CloudSDK.resolveToken = resolveToken; async function pushToStorage(token, fileName, payload) { const profile = await resolveToken(token); if (!profile || !profile.premium) { return false; } // Compression logic from original SDK const boundSize = compressBound(payload.length); const compressed = new Uint8Array(boundSize + 4); writeUint32(compressed, payload.length, 0); const compressedSize = compress(payload, compressed, 4, compressed.length); const upload = compressed.slice(0, compressedSize); const formData = new FormData(); formData.append("token", token); formData.append("fileName", fileName); formData.append("file", new Blob([upload])); try { const response = await fetch(API_PREFIX + "/saves/upload", { method: "POST", body: formData }); if (response.ok) { return true; } } catch (e) { console.error("Upload failed", e); } return false; } CloudSDK.pushToStorage = pushToStorage; async function pullFromStorage(token, fileName) { const profile = await resolveToken(token); if (profile) { try { const response = await fetch(API_PREFIX + "/saves/download/" + token + "/" + encodeURIComponent(fileName), { cache: "no-cache" }); if (response.ok) { const compressed = new Uint8Array(await response.arrayBuffer()); if (compressed.length < 4) return null; const uncompressedSize = readUint32(compressed, 0); const uncompressed = new Uint8Array(uncompressedSize); if (uncompress(compressed, uncompressed, 4) === uncompressedSize) { return uncompressed; } } } catch (e) { console.error("Download failed", e); } } return null; } CloudSDK.pullFromStorage = pullFromStorage; // LZ4 Implementation const lz4 = {}; lz4.uncompress = function (input, output, sIdx, eIdx) { sIdx = sIdx || 0; eIdx = eIdx || (input.length - sIdx); for (var i = sIdx, n = eIdx, j = 0; i < n;) { var token = input[i++]; var literals_length = (token >> 4); if (literals_length > 0) { var l = literals_length + 240; while (l === 255) { l = input[i++]; literals_length += l; } var end = i + literals_length; while (i < end) output[j++] = input[i++]; if (i === n) return j; } var offset = input[i++] | (input[i++] << 8); if (offset === 0) return j; if (offset > j) return -(i - 2); var match_length = (token & 0xf); var l = match_length + 240; while (l === 255) { l = input[i++]; match_length += l; } var pos = j - offset; var end = j + match_length + 4; while (j < end) output[j++] = output[pos++]; } return j; }; var maxInputSize = 0x7E000000, minMatch = 4, hashLog = 16, hashShift = (minMatch * 8) - hashLog, hashSize = 1 << hashLog, copyLength = 8, lastLiterals = 5, mfLimit = copyLength + minMatch, skipStrength = 6, mlBits = 4, mlMask = (1 << mlBits) - 1, runBits = 8 - mlBits, runMask = (1 << runBits) - 1, hasher = 2654435761; // assert(hashShift === 16); var hashTable = new Int16Array(1 << 16); var empty = new Int16Array(hashTable.length); lz4.compressBound = function (isize) { return isize > maxInputSize ? 0 : (isize + (isize / 255) + 16) | 0; }; lz4.compress = function (src, dst, sIdx, eIdx) { hashTable.set(empty); return compressBlock(src, dst, 0, sIdx || 0, eIdx || dst.length); }; function compressBlock(src, dst, pos, sIdx, eIdx) { var dpos = sIdx; var dlen = eIdx - sIdx; var anchor = 0; if (src.length >= maxInputSize) throw new Error("input too large"); if (src.length > mfLimit) { var n = lz4.compressBound(src.length); if (dlen < n) throw Error("output too small: " + dlen + " < " + n); var step = 1, findMatchAttempts = (1 << skipStrength) + 3, srcLength = src.length - mfLimit; while (pos + minMatch < srcLength) { var sequenceLowBits = src[pos + 1] << 8 | src[pos]; var sequenceHighBits = src[pos + 3] << 8 | src[pos + 2]; var hash = Math.imul(sequenceLowBits | (sequenceHighBits << 16), hasher) >>> hashShift; var ref = hashTable[hash] - 1; hashTable[hash] = pos + 1; if (ref < 0 || ((pos - ref) >>> 16) > 0 || (((src[ref + 3] << 8 | src[ref + 2]) != sequenceHighBits) || ((src[ref + 1] << 8 | src[ref]) != sequenceLowBits))) { step = findMatchAttempts++ >> skipStrength; pos += step; continue; } findMatchAttempts = (1 << skipStrength) + 3; var literals_length = pos - anchor; var offset = pos - ref; pos += minMatch; ref += minMatch; var match_length = pos; while (pos < srcLength && src[pos] == src[ref]) { pos++; ref++; } match_length = pos - match_length; var token = match_length < mlMask ? match_length : mlMask; if (literals_length >= runMask) { dst[dpos++] = (runMask << mlBits) + token; for (var len = literals_length - runMask; len > 254; len -= 255) { dst[dpos++] = 255; } dst[dpos++] = len; } else { dst[dpos++] = (literals_length << mlBits) + token; } for (var i = 0; i < literals_length; i++) { dst[dpos++] = src[anchor + i]; } dst[dpos++] = offset; dst[dpos++] = (offset >> 8); if (match_length >= mlMask) { match_length -= mlMask; while (match_length >= 255) { match_length -= 255; dst[dpos++] = 255; } dst[dpos++] = match_length; } anchor = pos; } } if (anchor == 0) return 0; literals_length = src.length - anchor; if (literals_length >= runMask) { dst[dpos++] = (runMask << mlBits); for (var ln = literals_length - runMask; ln > 254; ln -= 255) { dst[dpos++] = 255; } dst[dpos++] = ln; } else { dst[dpos++] = (literals_length << mlBits); } pos = anchor; while (pos < src.length) { dst[dpos++] = src[pos++]; } return dpos; } lz4.CHUNK_SIZE = 2048; const compressBound = lz4.compressBound; const compress = lz4.compress; const uncompress = lz4.uncompress; function writeUint32(container, value, offset) { container[offset] = value & 0xFF; container[offset + 1] = (value & 0x0000FF00) >> 8; container[offset + 2] = (value & 0x00FF0000) >> 16; container[offset + 3] = (value & 0xFF000000) >> 24; return offset + 4; } function readUint32(container, offset) { return (container[offset] & 0x000000FF) | ((container[offset + 1] << 8) & 0x0000FF00) | ((container[offset + 2] << 16) & 0x00FF0000) | ((container[offset + 3] << 24) & 0xFF000000); } })(CloudSDK || (CloudSDK = {})); var CloudSDKUI; (function (CloudSDKUI) { let v8Key = localStorage.getItem("js.cloud.sdk.v8.key"); let premium = false; let renderedState = null; let state = "init"; const lang = navigator.language.substring(0, 2); const t = { en: { enter: "Enter", key: "key", toenable: "to enable cloud saves", cloudsaves: "Cloud saves", enabled: "enabled", disabled: "disabled, no", subscription: "subscription", savedincloud: "Saved in cloud", savedlocally: "Saved locally", saveerror: "Save error", }, ru: { enter: "Введите", key: "ключ", toenable: "чтобы включить облачные сохранения", cloudsaves: "Облачные сохранения", enabled: "включены", disabled: "выключены, отсутствует", subscription: "подписка", savedincloud: "Сохранено в облаке", savedlocally: "Сохранено локально", saveerror: "Ошибка сохранения", }, }[lang === "ru" ? "ru" : "en"]; function Loading() { return { html: `