1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-12-11 09:11:50 +00:00

Merge pull request #40 from tobspr-games/dengr1065/even-more-cleanups

Even more cleanups
This commit is contained in:
Даниїл Григор'єв 2024-07-27 21:59:26 +03:00 committed by GitHub
commit cbd3f20f20
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 30 additions and 251 deletions

View File

@ -28,7 +28,6 @@
"debounce-promise": "^3.1.2",
"howler": "^2.1.2",
"lz-string": "^1.4.4",
"rusha": "^0.8.13",
"semver": "^7.3.5"
},
"devDependencies": {

View File

@ -36,22 +36,6 @@ import { SettingsState } from "./states/settings";
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 {
/**
* Boots the application
@ -176,7 +160,7 @@ export class Application {
// Unload events
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
document.addEventListener("touchstart", this.updateFocusAfterUserInteraction.bind(this), true);
@ -217,7 +201,7 @@ export class Application {
*/
handleVisibilityChange(event) {
window.focus();
const pageVisible = !document[pageHiddenPropName];
const pageVisible = !document.hidden;
if (pageVisible !== this.pageVisible) {
this.pageVisible = pageVisible;
logger.log("Visibility changed:", this.pageVisible);

View File

@ -1,4 +1,4 @@
// @ts-ignore
// @ts-expect-error FIXME: missing typings
import CompressionWorker from "../webworkers/compression.worker";
import { createLogger } from "./logging";
@ -6,26 +6,7 @@ import { round2Digits } from "./utils";
const logger = createLogger("async_compression");
export let 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");
}
}
export const compressionPrefix = String.fromCodePoint(1);
/**
* @typedef {{

View File

@ -1,6 +1,6 @@
import { globalConfig } from "./config";
import { fastArrayDelete } from "./utils";
import { createLogger } from "./logging";
import { fastArrayDelete } from "./utils";
const logger = createLogger("buffer_utils");
@ -10,9 +10,6 @@ const logger = createLogger("buffer_utils");
*/
export function enableImageSmoothing(context) {
context.imageSmoothingEnabled = true;
context.webkitImageSmoothingEnabled = true;
// @ts-ignore
context.imageSmoothingQuality = globalConfig.smoothing.quality;
}
@ -22,7 +19,6 @@ export function enableImageSmoothing(context) {
*/
export function disableImageSmoothing(context) {
context.imageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
}
/**

View File

@ -108,24 +108,16 @@ export const globalConfig = {
smoothing: {
smoothMainCanvas: smoothCanvas && true,
quality: "low", // Low is CRUCIAL for mobile performance!
quality: "low" as ImageSmoothingQuality, // Low is CRUCIAL for mobile performance!
},
rendering: {},
debug,
currentDiscount: 0,
// Secret vars
info: {
// Binary file salt
file: "Ec'])@^+*9zMevK3uMV4432x9%iK'=",
// Savegame salt
sgSalt: "}95Q3%8/.837Lqym_BJx%q7)pAHJbF",
// Analytics key
analyticsApiKey: "baf6a50f0cc7dfdec5a0e21c88a1c69a4b34bc4a",
},
};

View File

@ -41,13 +41,9 @@ export function prepareHighDPIContext(context, smooth = true) {
if (smooth) {
context.imageSmoothingEnabled = true;
context.webkitImageSmoothingEnabled = true;
// @ts-ignore
context.imageSmoothingQuality = globalConfig.smoothing.quality;
} else {
context.imageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
}
}

View File

@ -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() {
// from:https://github.com/jserz/js_piece/blob/master/DOM/ChildNode/remove()/remove().md
(function (arr) {
@ -104,18 +31,8 @@ function domPolyfills() {
function initPolyfills() {
mathPolyfills();
stringPolyfills();
objectPolyfills();
domPolyfills();
}
function initExtensions() {
String.prototype.replaceAll = function (search, replacement) {
var target = this;
return target.split(search).join(replacement);
};
}
// Other polyfills
initPolyfills();
initExtensions();

View File

@ -2,21 +2,20 @@
import { Application } from "../application";
/* typehints:end */
import { sha1, CRC_PREFIX, computeCrc } from "./sensitive_utils.encrypt";
import { createLogger } from "./logging";
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 { ExplainedResult } from "./explained_result";
import { decompressX64, compressX64 } from "./lzstring";
import { asyncCompressor, compressionPrefix } from "./async_compression";
import { compressObject, decompressObject } from "../savegame/savegame_compressor";
import { createLogger } from "./logging";
import { compressX64, decompressX64 } from "./lzstring";
import { computeCrc } from "./sensitive_utils.encrypt";
import debounce from "debounce-promise";
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
export class ReadWriteProxy {
@ -110,9 +109,7 @@ export class ReadWriteProxy {
const checksum = decompressed.substring(0, 40);
const jsonString = decompressed.substr(40);
const desiredChecksum = checksum.startsWith(CRC_PREFIX)
? computeCrc(jsonString + salt)
: sha1(jsonString + salt);
const desiredChecksum = computeCrc(jsonString + salt);
if (desiredChecksum !== checksum) {
// Checksum mismatch
@ -199,11 +196,9 @@ export class ReadWriteProxy {
// Compare stored checksum with actual checksum
const checksum = decompressed.substring(0, 40);
const jsonString = decompressed.substr(40);
const jsonString = decompressed.slice(40);
const desiredChecksum = checksum.startsWith(CRC_PREFIX)
? computeCrc(jsonString + salt)
: sha1(jsonString + salt);
const desiredChecksum = computeCrc(jsonString + salt);
if (desiredChecksum !== checksum) {
// Checksum mismatch

View File

@ -1,15 +1,4 @@
import { createHash } from "rusha";
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
export const CRC_PREFIX = "crc32".padEnd(32, "-");

View File

@ -40,19 +40,6 @@ export function randomInt(start, end) {
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
* @template T
@ -406,7 +393,7 @@ export function makeButton(parent, classes = [], innerHTML = "") {
*/
export function removeAllChildren(elem) {
if (elem) {
var range = document.createRange();
const range = document.createRange();
range.selectNodeContents(elem);
range.deleteContents();
}
@ -618,7 +605,7 @@ export function fillInLinkIntoTranslation(translation, link) {
* @param {string} 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("download", filename);
@ -634,7 +621,7 @@ export function generateFileDownload(filename, text) {
* @param {string} acceptedType
*/
export function startFileChoose(acceptedType = ".bin") {
var input = document.createElement("input");
const input = document.createElement("input");
input.type = "file";
input.accept = acceptedType;

View File

@ -489,7 +489,6 @@ export class Vector {
}
default: {
assertAlways(false, "Invalid fast inplace rotation: " + angle);
return this;
}
}
// return new Vector(this.x * cos - this.y * sin, this.x * sin + this.y * cos);
@ -519,7 +518,6 @@ export class Vector {
}
default: {
assertAlways(false, "Invalid fast inplace rotation: " + angle);
return new Vector();
}
}
}
@ -593,7 +591,6 @@ export class Vector {
}
default:
assertAlways(false, "Invalid angle: " + angle);
return;
}
}
@ -603,7 +600,7 @@ export class Vector {
* @returns {Boolean}
*/
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
View File

@ -22,11 +22,6 @@ declare const shapez: any;
declare const ipcRenderer: any;
// Polyfills
declare interface String {
replaceAll(search: string, replacement: string): string;
}
declare interface ImportMeta {
webpackContext(
request: string,
@ -47,10 +42,6 @@ declare interface ImportMeta {
declare interface CanvasRenderingContext2D {
beginRoundedRect(x: number, y: number, w: number, h: 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

View File

@ -1,12 +1,10 @@
import { globalConfig } from "../core/config";
import { ExplainedResult } from "../core/explained_result";
import { createLogger } from "../core/logging";
import { ReadWriteProxy } from "../core/read_write_proxy";
import { globalConfig } from "../core/config";
import { Savegame } from "./savegame";
const logger = createLogger("savegame_manager");
import Rusha from "rusha";
/**
* @typedef {import("./savegame_typedefs").SavegamesData} SavegamesData
* @typedef {import("./savegame_typedefs").SavegameMetadata} SavegameMetadata
@ -217,9 +215,7 @@ export class SavegameManager extends ReadWriteProxy {
* Helper method to generate a new internal savegame id
*/
generateInternalId() {
return Rusha.createHash()
.update(Date.now() + "/" + Math.random())
.digest("hex");
return self.crypto.randomUUID();
}
// End

View File

@ -2,10 +2,10 @@ import { CHANGELOG } from "../changelog";
import { globalConfig } from "../core/config";
import { GameState } from "../core/game_state";
import { createLogger } from "../core/logging";
import { getLogoSprite, timeoutPromise } from "../core/utils";
import { getLogoSprite } from "../core/utils";
import { getRandomHint } from "../game/hints";
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");
@ -44,22 +44,6 @@ export class PreloadState extends GameState {
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() {
// TODO: Get rid of this analytics stuff
}
@ -78,9 +62,6 @@ export class PreloadState extends GameState {
return this.app.storage.initialize();
})
.then(() => this.setStatus("Connecting to api", 15))
.then(() => this.fetchDiscounts())
.then(() => this.setStatus("Initializing settings", 20))
.then(() => {
return this.app.settings.initialize();
@ -256,7 +237,7 @@ export class PreloadState extends GameState {
subElement.innerHTML = `
<div class="logo">
<img src="res/getLogoSprite()" alt="Shapez.io Logo">
<img src="res/${getLogoSprite()}" alt="Shapez.io Logo">
</div>
<div class="failureInner">
<div class="errorHeader">

View File

@ -7,7 +7,7 @@ const logger = createLogger("translations");
// @ts-ignore
import baseTranslations from "./built-temp/base-en.json";
export let T = baseTranslations;
export const T = baseTranslations;
if (G_IS_DEV && globalConfig.debug.testTranslations) {
// Replaces all translations by fake translations to see whats translated and what not
@ -67,18 +67,11 @@ function mapLanguageCodeToId(languageKey) {
* @returns {string}
*/
export function autoDetectLanguageId() {
let languages = [];
if (navigator.languages) {
languages = navigator.languages.slice();
} else if (navigator.language) {
languages = [navigator.language];
} else {
logger.warn("Navigator has no languages prop");
}
const languages = navigator.languages;
for (let i = 0; i < languages.length; ++i) {
logger.log("Trying to find language target for", languages[i]);
const trans = mapLanguageCodeToId(languages[i]);
for (const language of languages) {
logger.log("Trying to find language target for", language);
const trans = mapLanguageCodeToId(language);
if (trans) {
return trans;
}

View File

@ -3,16 +3,6 @@ import { compressX64 } from "../core/lzstring";
import { computeCrc } from "../core/sensitive_utils.encrypt";
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 => {
// @ts-ignore
const { jobId, job, data } = event.data;
@ -32,7 +22,7 @@ function performJob(job, data) {
const optimized = compressObject(data.obj);
const stringified = JSON.stringify(optimized);
const checksum = computeCrc(stringified + salt);
const checksum = computeCrc(stringified + globalConfig.info.file);
return data.compressionPrefix + compressX64(checksum + stringified);
}
default:

View File

@ -8580,11 +8580,6 @@ run-parallel@^1.1.9:
dependencies:
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:
version "3.1.2"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"