mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-12-13 18:21:51 +00:00
Merge pull request #40 from tobspr-games/dengr1065/even-more-cleanups
Even more cleanups
This commit is contained in:
commit
cbd3f20f20
@ -28,7 +28,6 @@
|
|||||||
"debounce-promise": "^3.1.2",
|
"debounce-promise": "^3.1.2",
|
||||||
"howler": "^2.1.2",
|
"howler": "^2.1.2",
|
||||||
"lz-string": "^1.4.4",
|
"lz-string": "^1.4.4",
|
||||||
"rusha": "^0.8.13",
|
|
||||||
"semver": "^7.3.5"
|
"semver": "^7.3.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -36,22 +36,6 @@ import { SettingsState } from "./states/settings";
|
|||||||
|
|
||||||
const logger = createLogger("application");
|
const logger = createLogger("application");
|
||||||
|
|
||||||
// Set the name of the hidden property and the change event for visibility
|
|
||||||
let pageHiddenPropName, pageVisibilityEventName;
|
|
||||||
if (typeof document.hidden !== "undefined") {
|
|
||||||
// Opera 12.10 and Firefox 18 and later support
|
|
||||||
pageHiddenPropName = "hidden";
|
|
||||||
pageVisibilityEventName = "visibilitychange";
|
|
||||||
// @ts-ignore
|
|
||||||
} else if (typeof document.msHidden !== "undefined") {
|
|
||||||
pageHiddenPropName = "msHidden";
|
|
||||||
pageVisibilityEventName = "msvisibilitychange";
|
|
||||||
// @ts-ignore
|
|
||||||
} else if (typeof document.webkitHidden !== "undefined") {
|
|
||||||
pageHiddenPropName = "webkitHidden";
|
|
||||||
pageVisibilityEventName = "webkitvisibilitychange";
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Application {
|
export class Application {
|
||||||
/**
|
/**
|
||||||
* Boots the application
|
* Boots the application
|
||||||
@ -176,7 +160,7 @@ export class Application {
|
|||||||
// Unload events
|
// Unload events
|
||||||
window.addEventListener("beforeunload", this.onBeforeUnload.bind(this), true);
|
window.addEventListener("beforeunload", this.onBeforeUnload.bind(this), true);
|
||||||
|
|
||||||
document.addEventListener(pageVisibilityEventName, this.handleVisibilityChange.bind(this), false);
|
document.addEventListener("visibilitychange", this.handleVisibilityChange.bind(this), false);
|
||||||
|
|
||||||
// Track touches so we can update the focus appropriately
|
// Track touches so we can update the focus appropriately
|
||||||
document.addEventListener("touchstart", this.updateFocusAfterUserInteraction.bind(this), true);
|
document.addEventListener("touchstart", this.updateFocusAfterUserInteraction.bind(this), true);
|
||||||
@ -217,7 +201,7 @@ export class Application {
|
|||||||
*/
|
*/
|
||||||
handleVisibilityChange(event) {
|
handleVisibilityChange(event) {
|
||||||
window.focus();
|
window.focus();
|
||||||
const pageVisible = !document[pageHiddenPropName];
|
const pageVisible = !document.hidden;
|
||||||
if (pageVisible !== this.pageVisible) {
|
if (pageVisible !== this.pageVisible) {
|
||||||
this.pageVisible = pageVisible;
|
this.pageVisible = pageVisible;
|
||||||
logger.log("Visibility changed:", this.pageVisible);
|
logger.log("Visibility changed:", this.pageVisible);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// @ts-ignore
|
// @ts-expect-error FIXME: missing typings
|
||||||
import CompressionWorker from "../webworkers/compression.worker";
|
import CompressionWorker from "../webworkers/compression.worker";
|
||||||
|
|
||||||
import { createLogger } from "./logging";
|
import { createLogger } from "./logging";
|
||||||
@ -6,26 +6,7 @@ import { round2Digits } from "./utils";
|
|||||||
|
|
||||||
const logger = createLogger("async_compression");
|
const logger = createLogger("async_compression");
|
||||||
|
|
||||||
export let compressionPrefix = String.fromCodePoint(1);
|
export const compressionPrefix = String.fromCodePoint(1);
|
||||||
|
|
||||||
function checkCryptPrefix(prefix) {
|
|
||||||
try {
|
|
||||||
window.localStorage.setItem("prefix_test", prefix);
|
|
||||||
window.localStorage.removeItem("prefix_test");
|
|
||||||
return true;
|
|
||||||
} catch (ex) {
|
|
||||||
logger.warn("Prefix '" + prefix + "' not available");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!checkCryptPrefix(compressionPrefix)) {
|
|
||||||
logger.warn("Switching to basic prefix");
|
|
||||||
compressionPrefix = " ";
|
|
||||||
if (!checkCryptPrefix(compressionPrefix)) {
|
|
||||||
logger.warn("Prefix not available, ls seems to be unavailable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { globalConfig } from "./config";
|
import { globalConfig } from "./config";
|
||||||
import { fastArrayDelete } from "./utils";
|
|
||||||
import { createLogger } from "./logging";
|
import { createLogger } from "./logging";
|
||||||
|
import { fastArrayDelete } from "./utils";
|
||||||
|
|
||||||
const logger = createLogger("buffer_utils");
|
const logger = createLogger("buffer_utils");
|
||||||
|
|
||||||
@ -10,9 +10,6 @@ const logger = createLogger("buffer_utils");
|
|||||||
*/
|
*/
|
||||||
export function enableImageSmoothing(context) {
|
export function enableImageSmoothing(context) {
|
||||||
context.imageSmoothingEnabled = true;
|
context.imageSmoothingEnabled = true;
|
||||||
context.webkitImageSmoothingEnabled = true;
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
context.imageSmoothingQuality = globalConfig.smoothing.quality;
|
context.imageSmoothingQuality = globalConfig.smoothing.quality;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,7 +19,6 @@ export function enableImageSmoothing(context) {
|
|||||||
*/
|
*/
|
||||||
export function disableImageSmoothing(context) {
|
export function disableImageSmoothing(context) {
|
||||||
context.imageSmoothingEnabled = false;
|
context.imageSmoothingEnabled = false;
|
||||||
context.webkitImageSmoothingEnabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -108,24 +108,16 @@ export const globalConfig = {
|
|||||||
|
|
||||||
smoothing: {
|
smoothing: {
|
||||||
smoothMainCanvas: smoothCanvas && true,
|
smoothMainCanvas: smoothCanvas && true,
|
||||||
quality: "low", // Low is CRUCIAL for mobile performance!
|
quality: "low" as ImageSmoothingQuality, // Low is CRUCIAL for mobile performance!
|
||||||
},
|
},
|
||||||
|
|
||||||
rendering: {},
|
rendering: {},
|
||||||
debug,
|
debug,
|
||||||
|
|
||||||
currentDiscount: 0,
|
|
||||||
|
|
||||||
// Secret vars
|
// Secret vars
|
||||||
info: {
|
info: {
|
||||||
// Binary file salt
|
// Binary file salt
|
||||||
file: "Ec'])@^+*9zMevK3uMV4432x9%iK'=",
|
file: "Ec'])@^+*9zMevK3uMV4432x9%iK'=",
|
||||||
|
|
||||||
// Savegame salt
|
|
||||||
sgSalt: "}95Q3%8/.837Lqym_BJx%q7)pAHJbF",
|
|
||||||
|
|
||||||
// Analytics key
|
|
||||||
analyticsApiKey: "baf6a50f0cc7dfdec5a0e21c88a1c69a4b34bc4a",
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -41,13 +41,9 @@ export function prepareHighDPIContext(context, smooth = true) {
|
|||||||
|
|
||||||
if (smooth) {
|
if (smooth) {
|
||||||
context.imageSmoothingEnabled = true;
|
context.imageSmoothingEnabled = true;
|
||||||
context.webkitImageSmoothingEnabled = true;
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
context.imageSmoothingQuality = globalConfig.smoothing.quality;
|
context.imageSmoothingQuality = globalConfig.smoothing.quality;
|
||||||
} else {
|
} else {
|
||||||
context.imageSmoothingEnabled = false;
|
context.imageSmoothingEnabled = false;
|
||||||
context.webkitImageSmoothingEnabled = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,79 +10,6 @@ function mathPolyfills() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringPolyfills() {
|
|
||||||
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
|
|
||||||
if (!String.prototype.padStart) {
|
|
||||||
String.prototype.padStart = function padStart(targetLength, padString) {
|
|
||||||
targetLength = targetLength >> 0; //truncate if number, or convert non-number to 0;
|
|
||||||
padString = String(typeof padString !== "undefined" ? padString : " ");
|
|
||||||
if (this.length >= targetLength) {
|
|
||||||
return String(this);
|
|
||||||
} else {
|
|
||||||
targetLength = targetLength - this.length;
|
|
||||||
if (targetLength > padString.length) {
|
|
||||||
padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
|
|
||||||
}
|
|
||||||
return padString.slice(0, targetLength) + String(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
|
|
||||||
if (!String.prototype.padEnd) {
|
|
||||||
String.prototype.padEnd = function padEnd(targetLength, padString) {
|
|
||||||
targetLength = targetLength >> 0; //floor if number or convert non-number to 0;
|
|
||||||
padString = String(typeof padString !== "undefined" ? padString : " ");
|
|
||||||
if (this.length > targetLength) {
|
|
||||||
return String(this);
|
|
||||||
} else {
|
|
||||||
targetLength = targetLength - this.length;
|
|
||||||
if (targetLength > padString.length) {
|
|
||||||
padString += padString.repeat(targetLength / padString.length); //append to original to ensure we are longer than needed
|
|
||||||
}
|
|
||||||
return String(this) + padString.slice(0, targetLength);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function objectPolyfills() {
|
|
||||||
// https://github.com/tc39/proposal-object-values-entries/blob/master/polyfill.js
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
const reduce = Function.bind.call(Function.call, Array.prototype.reduce);
|
|
||||||
// @ts-ignore
|
|
||||||
const isEnumerable = Function.bind.call(Function.call, Object.prototype.propertyIsEnumerable);
|
|
||||||
// @ts-ignore
|
|
||||||
const concat = Function.bind.call(Function.call, Array.prototype.concat);
|
|
||||||
const keys = Reflect.ownKeys;
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
if (!Object.values) {
|
|
||||||
// @ts-ignore
|
|
||||||
Object.values = function values(O) {
|
|
||||||
return reduce(
|
|
||||||
keys(O),
|
|
||||||
(v, k) => concat(v, typeof k === "string" && isEnumerable(O, k) ? [O[k]] : []),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Object.entries) {
|
|
||||||
// @ts-ignore
|
|
||||||
Object.entries = function entries(O) {
|
|
||||||
return reduce(
|
|
||||||
keys(O),
|
|
||||||
(e, k) => concat(e, typeof k === "string" && isEnumerable(O, k) ? [[k, O[k]]] : []),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function domPolyfills() {
|
function domPolyfills() {
|
||||||
// from:https://github.com/jserz/js_piece/blob/master/DOM/ChildNode/remove()/remove().md
|
// from:https://github.com/jserz/js_piece/blob/master/DOM/ChildNode/remove()/remove().md
|
||||||
(function (arr) {
|
(function (arr) {
|
||||||
@ -104,18 +31,8 @@ function domPolyfills() {
|
|||||||
|
|
||||||
function initPolyfills() {
|
function initPolyfills() {
|
||||||
mathPolyfills();
|
mathPolyfills();
|
||||||
stringPolyfills();
|
|
||||||
objectPolyfills();
|
|
||||||
domPolyfills();
|
domPolyfills();
|
||||||
}
|
}
|
||||||
|
|
||||||
function initExtensions() {
|
|
||||||
String.prototype.replaceAll = function (search, replacement) {
|
|
||||||
var target = this;
|
|
||||||
return target.split(search).join(replacement);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other polyfills
|
// Other polyfills
|
||||||
initPolyfills();
|
initPolyfills();
|
||||||
initExtensions();
|
|
||||||
|
|||||||
@ -2,21 +2,20 @@
|
|||||||
import { Application } from "../application";
|
import { Application } from "../application";
|
||||||
/* typehints:end */
|
/* typehints:end */
|
||||||
|
|
||||||
import { sha1, CRC_PREFIX, computeCrc } from "./sensitive_utils.encrypt";
|
|
||||||
import { createLogger } from "./logging";
|
|
||||||
import { FILE_NOT_FOUND } from "../platform/storage";
|
import { FILE_NOT_FOUND } from "../platform/storage";
|
||||||
import { accessNestedPropertyReverse } from "./utils";
|
import { compressObject, decompressObject } from "../savegame/savegame_compressor";
|
||||||
|
import { asyncCompressor, compressionPrefix } from "./async_compression";
|
||||||
import { IS_DEBUG, globalConfig } from "./config";
|
import { IS_DEBUG, globalConfig } from "./config";
|
||||||
import { ExplainedResult } from "./explained_result";
|
import { ExplainedResult } from "./explained_result";
|
||||||
import { decompressX64, compressX64 } from "./lzstring";
|
import { createLogger } from "./logging";
|
||||||
import { asyncCompressor, compressionPrefix } from "./async_compression";
|
import { compressX64, decompressX64 } from "./lzstring";
|
||||||
import { compressObject, decompressObject } from "../savegame/savegame_compressor";
|
import { computeCrc } from "./sensitive_utils.encrypt";
|
||||||
|
|
||||||
import debounce from "debounce-promise";
|
import debounce from "debounce-promise";
|
||||||
|
|
||||||
const logger = createLogger("read_write_proxy");
|
const logger = createLogger("read_write_proxy");
|
||||||
|
|
||||||
const salt = accessNestedPropertyReverse(globalConfig, ["file", "info"]);
|
const salt = globalConfig.info.file;
|
||||||
|
|
||||||
// Helper which only writes / reads if verify() works. Also performs migration
|
// Helper which only writes / reads if verify() works. Also performs migration
|
||||||
export class ReadWriteProxy {
|
export class ReadWriteProxy {
|
||||||
@ -110,9 +109,7 @@ export class ReadWriteProxy {
|
|||||||
const checksum = decompressed.substring(0, 40);
|
const checksum = decompressed.substring(0, 40);
|
||||||
const jsonString = decompressed.substr(40);
|
const jsonString = decompressed.substr(40);
|
||||||
|
|
||||||
const desiredChecksum = checksum.startsWith(CRC_PREFIX)
|
const desiredChecksum = computeCrc(jsonString + salt);
|
||||||
? computeCrc(jsonString + salt)
|
|
||||||
: sha1(jsonString + salt);
|
|
||||||
|
|
||||||
if (desiredChecksum !== checksum) {
|
if (desiredChecksum !== checksum) {
|
||||||
// Checksum mismatch
|
// Checksum mismatch
|
||||||
@ -199,11 +196,9 @@ export class ReadWriteProxy {
|
|||||||
|
|
||||||
// Compare stored checksum with actual checksum
|
// Compare stored checksum with actual checksum
|
||||||
const checksum = decompressed.substring(0, 40);
|
const checksum = decompressed.substring(0, 40);
|
||||||
const jsonString = decompressed.substr(40);
|
const jsonString = decompressed.slice(40);
|
||||||
|
|
||||||
const desiredChecksum = checksum.startsWith(CRC_PREFIX)
|
const desiredChecksum = computeCrc(jsonString + salt);
|
||||||
? computeCrc(jsonString + salt)
|
|
||||||
: sha1(jsonString + salt);
|
|
||||||
|
|
||||||
if (desiredChecksum !== checksum) {
|
if (desiredChecksum !== checksum) {
|
||||||
// Checksum mismatch
|
// Checksum mismatch
|
||||||
|
|||||||
@ -1,15 +1,4 @@
|
|||||||
import { createHash } from "rusha";
|
|
||||||
import crc32 from "crc/crc32";
|
import crc32 from "crc/crc32";
|
||||||
import { decompressX64 } from "./lzstring";
|
|
||||||
|
|
||||||
export function sha1(str) {
|
|
||||||
return createHash().update(str).digest("hex");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Window.location.host
|
|
||||||
export function getNameOfProvider() {
|
|
||||||
return window[decompressX64("DYewxghgLgliB2Q")][decompressX64("BYewzgLgdghgtgUyA")];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Distinguish legacy crc prefixes
|
// Distinguish legacy crc prefixes
|
||||||
export const CRC_PREFIX = "crc32".padEnd(32, "-");
|
export const CRC_PREFIX = "crc32".padEnd(32, "-");
|
||||||
|
|||||||
@ -40,19 +40,6 @@ export function randomInt(start, end) {
|
|||||||
return Math.floor(Math.random() * (end - start + 1) + start);
|
return Math.floor(Math.random() * (end - start + 1) + start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Access an object in a very annoying way, used for obsfuscation.
|
|
||||||
* @param {any} obj
|
|
||||||
* @param {Array<string>} keys
|
|
||||||
*/
|
|
||||||
export function accessNestedPropertyReverse(obj, keys) {
|
|
||||||
let result = obj;
|
|
||||||
for (let i = keys.length - 1; i >= 0; --i) {
|
|
||||||
result = result[keys[i]];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chooses a random entry of an array
|
* Chooses a random entry of an array
|
||||||
* @template T
|
* @template T
|
||||||
@ -406,7 +393,7 @@ export function makeButton(parent, classes = [], innerHTML = "") {
|
|||||||
*/
|
*/
|
||||||
export function removeAllChildren(elem) {
|
export function removeAllChildren(elem) {
|
||||||
if (elem) {
|
if (elem) {
|
||||||
var range = document.createRange();
|
const range = document.createRange();
|
||||||
range.selectNodeContents(elem);
|
range.selectNodeContents(elem);
|
||||||
range.deleteContents();
|
range.deleteContents();
|
||||||
}
|
}
|
||||||
@ -618,7 +605,7 @@ export function fillInLinkIntoTranslation(translation, link) {
|
|||||||
* @param {string} text
|
* @param {string} text
|
||||||
*/
|
*/
|
||||||
export function generateFileDownload(filename, text) {
|
export function generateFileDownload(filename, text) {
|
||||||
var element = document.createElement("a");
|
const element = document.createElement("a");
|
||||||
element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text));
|
element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text));
|
||||||
element.setAttribute("download", filename);
|
element.setAttribute("download", filename);
|
||||||
|
|
||||||
@ -634,7 +621,7 @@ export function generateFileDownload(filename, text) {
|
|||||||
* @param {string} acceptedType
|
* @param {string} acceptedType
|
||||||
*/
|
*/
|
||||||
export function startFileChoose(acceptedType = ".bin") {
|
export function startFileChoose(acceptedType = ".bin") {
|
||||||
var input = document.createElement("input");
|
const input = document.createElement("input");
|
||||||
input.type = "file";
|
input.type = "file";
|
||||||
input.accept = acceptedType;
|
input.accept = acceptedType;
|
||||||
|
|
||||||
|
|||||||
@ -489,7 +489,6 @@ export class Vector {
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
assertAlways(false, "Invalid fast inplace rotation: " + angle);
|
assertAlways(false, "Invalid fast inplace rotation: " + angle);
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// return new Vector(this.x * cos - this.y * sin, this.x * sin + this.y * cos);
|
// return new Vector(this.x * cos - this.y * sin, this.x * sin + this.y * cos);
|
||||||
@ -519,7 +518,6 @@ export class Vector {
|
|||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
assertAlways(false, "Invalid fast inplace rotation: " + angle);
|
assertAlways(false, "Invalid fast inplace rotation: " + angle);
|
||||||
return new Vector();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -593,7 +591,6 @@ export class Vector {
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
assertAlways(false, "Invalid angle: " + angle);
|
assertAlways(false, "Invalid angle: " + angle);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,7 +600,7 @@ export class Vector {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
equalsEpsilon(v, epsilon = 1e-5) {
|
equalsEpsilon(v, epsilon = 1e-5) {
|
||||||
return Math.abs(this.x - v.x) < 1e-5 && Math.abs(this.y - v.y) < epsilon;
|
return Math.abs(this.x - v.x) < epsilon && Math.abs(this.y - v.y) < epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
9
src/js/globals.d.ts
vendored
9
src/js/globals.d.ts
vendored
@ -22,11 +22,6 @@ declare const shapez: any;
|
|||||||
|
|
||||||
declare const ipcRenderer: any;
|
declare const ipcRenderer: any;
|
||||||
|
|
||||||
// Polyfills
|
|
||||||
declare interface String {
|
|
||||||
replaceAll(search: string, replacement: string): string;
|
|
||||||
}
|
|
||||||
|
|
||||||
declare interface ImportMeta {
|
declare interface ImportMeta {
|
||||||
webpackContext(
|
webpackContext(
|
||||||
request: string,
|
request: string,
|
||||||
@ -47,10 +42,6 @@ declare interface ImportMeta {
|
|||||||
declare interface CanvasRenderingContext2D {
|
declare interface CanvasRenderingContext2D {
|
||||||
beginRoundedRect(x: number, y: number, w: number, h: number, r: number): void;
|
beginRoundedRect(x: number, y: number, w: number, h: number, r: number): void;
|
||||||
beginCircle(x: number, y: number, r: number): void;
|
beginCircle(x: number, y: number, r: number): void;
|
||||||
|
|
||||||
msImageSmoothingEnabled: boolean;
|
|
||||||
mozImageSmoothingEnabled: boolean;
|
|
||||||
webkitImageSmoothingEnabled: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just for compatibility with the shared code
|
// Just for compatibility with the shared code
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
|
import { globalConfig } from "../core/config";
|
||||||
import { ExplainedResult } from "../core/explained_result";
|
import { ExplainedResult } from "../core/explained_result";
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { ReadWriteProxy } from "../core/read_write_proxy";
|
import { ReadWriteProxy } from "../core/read_write_proxy";
|
||||||
import { globalConfig } from "../core/config";
|
|
||||||
import { Savegame } from "./savegame";
|
import { Savegame } from "./savegame";
|
||||||
const logger = createLogger("savegame_manager");
|
const logger = createLogger("savegame_manager");
|
||||||
|
|
||||||
import Rusha from "rusha";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import("./savegame_typedefs").SavegamesData} SavegamesData
|
* @typedef {import("./savegame_typedefs").SavegamesData} SavegamesData
|
||||||
* @typedef {import("./savegame_typedefs").SavegameMetadata} SavegameMetadata
|
* @typedef {import("./savegame_typedefs").SavegameMetadata} SavegameMetadata
|
||||||
@ -217,9 +215,7 @@ export class SavegameManager extends ReadWriteProxy {
|
|||||||
* Helper method to generate a new internal savegame id
|
* Helper method to generate a new internal savegame id
|
||||||
*/
|
*/
|
||||||
generateInternalId() {
|
generateInternalId() {
|
||||||
return Rusha.createHash()
|
return self.crypto.randomUUID();
|
||||||
.update(Date.now() + "/" + Math.random())
|
|
||||||
.digest("hex");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// End
|
// End
|
||||||
|
|||||||
@ -2,10 +2,10 @@ import { CHANGELOG } from "../changelog";
|
|||||||
import { globalConfig } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { GameState } from "../core/game_state";
|
import { GameState } from "../core/game_state";
|
||||||
import { createLogger } from "../core/logging";
|
import { createLogger } from "../core/logging";
|
||||||
import { getLogoSprite, timeoutPromise } from "../core/utils";
|
import { getLogoSprite } from "../core/utils";
|
||||||
import { getRandomHint } from "../game/hints";
|
import { getRandomHint } from "../game/hints";
|
||||||
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
||||||
import { autoDetectLanguageId, T, updateApplicationLanguage } from "../translations";
|
import { T, autoDetectLanguageId, updateApplicationLanguage } from "../translations";
|
||||||
|
|
||||||
const logger = createLogger("state/preload");
|
const logger = createLogger("state/preload");
|
||||||
|
|
||||||
@ -44,22 +44,6 @@ export class PreloadState extends GameState {
|
|||||||
this.startLoading();
|
this.startLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchDiscounts() {
|
|
||||||
await timeoutPromise(
|
|
||||||
fetch("https://analytics.shapez.io/v1/discounts")
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(data => {
|
|
||||||
globalConfig.currentDiscount = Number(
|
|
||||||
data["1318690"].data.price_overview.discount_percent
|
|
||||||
);
|
|
||||||
logger.log("Fetched current discount:", globalConfig.currentDiscount);
|
|
||||||
}),
|
|
||||||
2000
|
|
||||||
).catch(err => {
|
|
||||||
logger.warn("Failed to fetch current discount:", err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async sendBeacon() {
|
async sendBeacon() {
|
||||||
// TODO: Get rid of this analytics stuff
|
// TODO: Get rid of this analytics stuff
|
||||||
}
|
}
|
||||||
@ -78,9 +62,6 @@ export class PreloadState extends GameState {
|
|||||||
return this.app.storage.initialize();
|
return this.app.storage.initialize();
|
||||||
})
|
})
|
||||||
|
|
||||||
.then(() => this.setStatus("Connecting to api", 15))
|
|
||||||
.then(() => this.fetchDiscounts())
|
|
||||||
|
|
||||||
.then(() => this.setStatus("Initializing settings", 20))
|
.then(() => this.setStatus("Initializing settings", 20))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return this.app.settings.initialize();
|
return this.app.settings.initialize();
|
||||||
@ -256,7 +237,7 @@ export class PreloadState extends GameState {
|
|||||||
|
|
||||||
subElement.innerHTML = `
|
subElement.innerHTML = `
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<img src="res/getLogoSprite()" alt="Shapez.io Logo">
|
<img src="res/${getLogoSprite()}" alt="Shapez.io Logo">
|
||||||
</div>
|
</div>
|
||||||
<div class="failureInner">
|
<div class="failureInner">
|
||||||
<div class="errorHeader">
|
<div class="errorHeader">
|
||||||
|
|||||||
@ -7,7 +7,7 @@ const logger = createLogger("translations");
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import baseTranslations from "./built-temp/base-en.json";
|
import baseTranslations from "./built-temp/base-en.json";
|
||||||
|
|
||||||
export let T = baseTranslations;
|
export const T = baseTranslations;
|
||||||
|
|
||||||
if (G_IS_DEV && globalConfig.debug.testTranslations) {
|
if (G_IS_DEV && globalConfig.debug.testTranslations) {
|
||||||
// Replaces all translations by fake translations to see whats translated and what not
|
// Replaces all translations by fake translations to see whats translated and what not
|
||||||
@ -67,18 +67,11 @@ function mapLanguageCodeToId(languageKey) {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function autoDetectLanguageId() {
|
export function autoDetectLanguageId() {
|
||||||
let languages = [];
|
const languages = navigator.languages;
|
||||||
if (navigator.languages) {
|
|
||||||
languages = navigator.languages.slice();
|
|
||||||
} else if (navigator.language) {
|
|
||||||
languages = [navigator.language];
|
|
||||||
} else {
|
|
||||||
logger.warn("Navigator has no languages prop");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < languages.length; ++i) {
|
for (const language of languages) {
|
||||||
logger.log("Trying to find language target for", languages[i]);
|
logger.log("Trying to find language target for", language);
|
||||||
const trans = mapLanguageCodeToId(languages[i]);
|
const trans = mapLanguageCodeToId(language);
|
||||||
if (trans) {
|
if (trans) {
|
||||||
return trans;
|
return trans;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,16 +3,6 @@ import { compressX64 } from "../core/lzstring";
|
|||||||
import { computeCrc } from "../core/sensitive_utils.encrypt";
|
import { computeCrc } from "../core/sensitive_utils.encrypt";
|
||||||
import { compressObject } from "../savegame/savegame_compressor";
|
import { compressObject } from "../savegame/savegame_compressor";
|
||||||
|
|
||||||
function accessNestedPropertyReverse(obj, keys) {
|
|
||||||
let result = obj;
|
|
||||||
for (let i = keys.length - 1; i >= 0; --i) {
|
|
||||||
result = result[keys[i]];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const salt = accessNestedPropertyReverse(globalConfig, ["file", "info"]);
|
|
||||||
|
|
||||||
self.addEventListener("message", event => {
|
self.addEventListener("message", event => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const { jobId, job, data } = event.data;
|
const { jobId, job, data } = event.data;
|
||||||
@ -32,7 +22,7 @@ function performJob(job, data) {
|
|||||||
const optimized = compressObject(data.obj);
|
const optimized = compressObject(data.obj);
|
||||||
const stringified = JSON.stringify(optimized);
|
const stringified = JSON.stringify(optimized);
|
||||||
|
|
||||||
const checksum = computeCrc(stringified + salt);
|
const checksum = computeCrc(stringified + globalConfig.info.file);
|
||||||
return data.compressionPrefix + compressX64(checksum + stringified);
|
return data.compressionPrefix + compressX64(checksum + stringified);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -8580,11 +8580,6 @@ run-parallel@^1.1.9:
|
|||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask "^1.2.2"
|
queue-microtask "^1.2.2"
|
||||||
|
|
||||||
rusha@^0.8.13:
|
|
||||||
version "0.8.14"
|
|
||||||
resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.14.tgz#a977d0de9428406138b7bb90d3de5dcd024e2f68"
|
|
||||||
integrity sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==
|
|
||||||
|
|
||||||
rx-lite@^3.1.2:
|
rx-lite@^3.1.2:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
|
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user